kor*_*rok 89 c java grammar parsing
我熟悉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语法规则有错?
Ira*_*ter 76
解析C++变得越来越难.解析Java变得同样困难.
看到这个SO回答讨论为什么C(和C++)"难以"解析.简短的总结是C和C++ 语法本质上是模棱两可的; 他们会给你多个解析,你必须使用上下文来解决歧义.然后人们会假设你在解析时必须解决歧义; 不是这样,见下文.如果你在解析时坚持解决歧义,你的解析器会变得更复杂,而且构建起来要困难得多; 但这种复杂性是一种自我伤害.
IIRC,Java 1.4的"明显的"LALR(1)语法并不含糊,因此解析起来很"容易".我不太确定现代Java至少没有长距离的局部模糊; 总是存在决定"... >>"关闭两个模板还是"右移操作符"的问题.我怀疑现代Java不再用LALR(1)解析了.
但是,对于这两种语言,可以通过使用强解析器(或弱解析器和上下文收集黑客,因为C和C++前端主要执行此操作)来解决问题.C和C++具有预处理器的额外复杂性; 这些在实践中比它们看起来更复杂.一种说法是C和C++解析器非常难以完成,必须手工编写. 事实并非如此; 你可以使用GLR解析器生成器很好地构建Java和C++解析器.
但解析并不是问题所在.
解析后,您将需要使用AST/parse树执行某些操作.实际上,您需要知道每个标识符的定义是什么以及它的使用位置("名称和类型分辨率",粗略地构建符号表).事实证明,这比通过继承,接口,重载和模板更加复杂,并且由于所有这些语义都是用非正式的自然语言编写,这些语言分布在数十到数百页之间,这使得它更加困难.语言标准.C++在这里真的很糟糕.从这个角度来看,Java 7和8变得非常糟糕.(而且符号表并不是你所需要的;请参阅我的生物文章,阅读更长篇文章"解析后的生活").
大多数人都在使用纯解析部分(通常永远不会完成;检查SO本身是否有很多关于如何为实际语言构建工作解析器的问题),所以他们在解析后看不到生命.然后我们得到关于难以解析的内容的民间定理,并且没有关于该阶段之后发生的事情的信号.
修复C++语法不会让你到处都是.
关于更改C++语法:你会发现你需要修补很多地方来处理任何C++语法中的各种局部和真实歧义.如果你坚持,以下列表可能是一个很好的起点.我认为,如果你不是C++标准委员会,这样做没有意义; 如果你这样做,并使用它构建了一个编译器,没有人会理智地使用它.为了方便构建解析器的人们,现有的C++应用程序投入太多了.此外,他们的痛苦已经结束,现有的解析器工作正常.
您可能想要编写自己的解析器.好没关系; 只是不要指望社区的其他人让你改变他们必须使用的语言,以使你更容易.他们都希望他们更容易,这就是使用记录和实施的语言.
| 归档时间: |
|
| 查看次数: |
5556 次 |
| 最近记录: |