相关疑难解决方法(0)

寻找"标记器","解析器"和"词法分析器"的清晰定义以及它们如何相互关联和使用?

我正在寻找"tokenizer","parser"和"lexer"是什么以及它们如何相互关联的明确定义(例如,解析器是否使用了tokenizer,反之亦然)?我需要创建一个程序,将通过c/h源文件来提取数据声明和定义.

我一直在寻找示例,可以找到一些信息,但我真的很难掌握语法规则,解析树和抽象语法树等基础概念以及它们如何相互关联.最终这些概念需要存储在实际程序中,但1)它们看起来像什么,2)是否有共同的实现.

我一直在关注这些主题和程序,如Lex和Yacc维基百科,但从未经历过编译器类(EE专业),我发现很难完全理解正在发生的事情.

parsing tokenize lexer

134
推荐指数
3
解决办法
3万
查看次数

是什么让Java比C更容易解析?

我熟悉C和C++的语法是上下文相关的事实,特别是你需要在C中使用"lexer hack".另一方面,我的印象是你只能解析Java尽管两种语言之间存在相当大的相似性,但仍有2个前瞻性令牌.

你需要改变什么才能使它更易于解析?

我问,因为我所见过的关于C的上下文敏感性的所有例子在技术上都是允许的,但非常奇怪.例如,

foo (a);
Run Code Online (Sandbox Code Playgroud)

可以foo用参数调用void函数a.或者,它可以声明a是一个类型的对象foo,但你可以很容易地摆脱parantheses.在某种程度上,这种奇怪之处的发生是因为C语法的"直接声明者"生成规则实现了声明函数和变量的双重目的.

另一方面,Java语法具有用于变量声明和函数声明的单独生成规则.如果你写

foo a;
Run Code Online (Sandbox Code Playgroud)

然后你知道它是一个变量声明,foo可以毫不含糊地解析为一个类型名.如果foo尚未在当前作用域中的某处定义类,则这可能不是有效代码,但这是可以在稍后的编译器传递中执行的语义分析的工作.

我已经看到它说由于typedef很难解析C,但你也可以在Java中声明自己的类型.此外direct_declarator,哪种C语法规则有错?

c java grammar parsing

89
推荐指数
1
解决办法
5556
查看次数

GCC和Clang解析器真的是手写的吗?

似乎GCC和LLVM-Clang使用手写递归下降解析器,而不是机器生成,基于Bison-Flex,自下而上解析.

请问有人请确认是这种情况吗?如果是这样,为什么主流编译器框架使用手写解析器?

更新:这里有关此主题的有趣博客

c compiler-construction parsing compilation

84
推荐指数
5
解决办法
3万
查看次数

C++语法上下文的任何部分都是敏感的吗?

可能重复:
C++是无上下文还是上下文相关?

对于熟悉编译器的人来说,这可能是一个愚蠢的问题,但老实说我对答案一无所知.

C++语法是上下文敏感的吗?换句话说,C++语法是否无法用无上下文语法表达?

很明显,C++ 使用常规解析工具解析的,并且解析并不是特别无效(!),但我确实记得读过这个(我不记得在哪里),我想我会在传播之前直接了解社区谎言......也许C++的一个子集是CS?也许新的规格?任何帮助表示赞赏.

编辑:感谢所有的回复.但是,为了完整起见,编译的哪个部分处理歧义?CFG是一种语法,在规则的左侧只有一个非终端符号(例如A->zC),CSG是在左侧有一个终端(加上一个非终端)的语法(aAv->QT),其中大写字母是非终结符,小写是终结符.在解析 C++源代码的语法中是否有像后者那样的表示?

c++ parsing

21
推荐指数
0
解决办法
4726
查看次数

从c ++代码中获取人类可读的AST

为了更好地理解C++语言和语法的一些细节,我希望能够编写一个小的C++程序,并查看编译器从中生成的AST.

看起来clang过去有这个功能(-emit-asm),但它已经删除了.

今天有一个简单的方法吗?

c++ abstract-syntax-tree

20
推荐指数
3
解决办法
1万
查看次数

可以理论上/实际上使用Boost.Spirit来解析C++(0x)(或任何其他语言)吗?

这在理论上取决于任务吗?

它是否可以实际完成,并且生成的解析器是否可以使用足够的性能和输出(例如,LLVM IR或GCC的gimple)来集成到竞争编译器中?

c++ parsing boost boost-spirit c++11

19
推荐指数
2
解决办法
3424
查看次数

C解析器如何区分类型转换和函数调用?

我正在尝试为自己的教育编写一个C语法分析器.我知道我可以使用像YACC这样的工具来简化流程,但我想从经验中尽可能多地学习,所以我从头开始.

我的问题是我应该如何处理这样的一行:

doSomethingWith((foo)(bar));
Run Code Online (Sandbox Code Playgroud)

它可能(foo)(bar)是一个类型转换,如:

typedef int foo;

void doSomethingWith(foo aFoo) { ... }

int main() {
    float bar = 23.6;

    doSomethingWith((foo)(bar));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,它可能(foo)(bar)是一个函数调用,如:

int foo(int bar) { return bar; }

void doSomethingWith(int anInt) { ... }

int main() {
    int bar = 10;

    doSomethingWith((foo)(bar));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,解析器无法单独通过查看行来确定它处理的两种情况中的哪一种.doSomethingWith((foo)(bar));这让我很烦恼,因为我希望能够将解析阶段与您实际确定的"解释"阶段分开该行typedef int foo;表示foo现在是有效类型.在我想象的场景中,Type a = b + c * d即使Type,a,b,c和d没有在任何地方定义,也会解析得很好,并且只有在实际尝试"解析"标识符时才会出现问题.

所以,我的问题是:"真正的"C解析器如何处理这个?两个阶段之间的分离是我希望只是一个天真的愿望,还是我错过了什么?

c parsing casting function-call

19
推荐指数
2
解决办法
582
查看次数

如何从用户输入修改C++代码

我目前正在编写一个位于C++解释器之上的程序.用户在运行时输入C++命令,然后将其传递给解释器.对于某些模式,我想用修改后的表单替换给出的命令,以便我可以提供其他功能.

我想替换任何形式的东西

A->Draw(B1, B2)
Run Code Online (Sandbox Code Playgroud)

MyFunc(A, B1, B2).
Run Code Online (Sandbox Code Playgroud)

我首先想到的是正则表达式,但是这将是相当容易出错,因为任何的A,B1或者B2可以是任意的C++表达式.由于这些表达式本身可能包含带引号的字符串或括号,因此将所有情况与正则表达式匹配将非常困难.此外,此表达式可能有多种嵌套形式

我的下一个想法是将clang称为子进程,使用"-dump-ast"获取抽象语法树,修改它,然后将其重建为一个命令以传递给C++解释器.但是,这需要跟踪任何环境更改,例如包含文件和转发声明,以便为clang提供足够的信息来解析表达式.由于口译员没有公开这些信息,这似乎也是不可行的.

第三个想法是使用C++解释器自己的内部解析转换为抽象语法树,然后从那里构建.但是,这个解释器不会以任何我能够找到的方式揭示ast.

是否有任何关于如何继续进行的建议,无论是沿着其中一条规定的路线,还是完全沿着不同的路线?

c++ clang root-framework

19
推荐指数
1
解决办法
1615
查看次数

用于模糊解析C++的Clang

是否可以通过clang与现有的libclang API解析C++与不完整的声明?即解析.cpp文件,不包括所有标题,动态推断声明.所以,例如以下文字:

A B::Foo(){return stuff();}
Run Code Online (Sandbox Code Playgroud)

将检测未知符号A,使用我的魔法启发式调用我的回调来减去A是一个类,然后用B和Foo和东西以相同的方式调用此回调.最后我希望能够推断出我看到B级的成员Foo返回A,而东西是一个函数..或者是那种效果.上下文:我想看看我是否可以进行合理的语法突出显示和即时代码分析,而无需快速解析所有头文件.

[编辑]为了澄清,我正在寻找非常严格限制的C++解析,可能有一些启发式来解除一些限制.

C++语法充满了上下文依赖性.Foo()是函数调用还是Foo类的临时构造?是Foo <Bar>的东西; 模板Foo <Bar>实例化和变量东西的声明,还是看起来很奇怪2调用重载的运算符<和运算符>?它只能在上下文中讲述,而上下文通常来自解析头文件.

我正在寻找的是一种插入我的自定义约定规则的方法.例如,我知道我没有重载Win32符号,所以我可以安全地假设CreateFile 始终是一个函数,我甚至知道它的签名.我也知道我的所有课程都以大写字母开头,都是名词,函数通常是动词,所以我可以合理地猜测Foo和Bar是类名.在一个更复杂的场景中,我知道我不会像<b> c那样编写无副作用的表达式; 所以我可以假设a始终是模板实例化.等等.

所以,问题是每次遇到未知符号时是否可以使用Clang API回调,并使用我自己的非C++启发式给它一个答案.如果我的启发式失败,那么解析就会失败.我不是在谈论解析Boost库:)我说的是非常简单的C++,可能没有模板,仅限于clang在这种情况下可以处理的最小值.

c++ syntax parsing fuzzy clang

17
推荐指数
3
解决办法
2578
查看次数

分析器的选择

好的,我理解这个问题可能听起来很基于意见,但是由于我有几个特定的​​选择标准,我认为它会很适合SO.所以,我在这里......

我过去曾经使用编译器/解释器构建很多(显然主要是作为一种业余爱好)并且出于某种原因我坚持使用Lex/Yacc(或Flex/Bison,我对他们现在如何称呼它们感到困惑... 大声笑).

然而,由于我发现自己目前正在玩另一个业余爱好者翻译项目,我认为我应该尝试一些不同的东西,以避免我不喜欢Lex/Yacc.

所以,即:

  • 更好的C++ - 友好(比C友好)
  • 好的文档(最好已经实现了一些现有的语法+关于如何编译/使用它们的说明 - 听起来很明显,对吧?)
  • 可能是LALR,LL(*),递归下降,我并不在乎(注意:关于你喜欢哪种类型以及哪种类型的实现会很棒的输入;我从来没有真正理解他们的专业和缺点,说实话,即使我知道他们所指的是什么)
  • 将Lexer部分和Parser语法组合在一个文件中并不坏; 从来没有真正理解为什么它必须分成两部分.
  • 最后但同样重要的是:我总是遇到......问题.我的意思是 - 至少就Lex/Yacc而言,解析错误信息或多或少是神秘的(Syntax Error...... Yuhuu!),很少有人帮助诊断问题.(好吧,除非你是开发翻译的人......哈哈).那么,有没有比Lex/Yacc更好的错误报告

好的,我希望这不是太冗长.我全都耳朵!:-)

c++ parsing lex bison parser-generator

16
推荐指数
2
解决办法
9811
查看次数