一尘不染

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

java

为了使C解析起来更容易处理,您需要更改什么?

我之所以问是因为,我所见过的有关C的上下文敏感度的所有示例在技术上都是允许的,但非常奇怪。例如,

foo (a);

可能正在foo使用arguments
调用void函数a。或者,它可能声明a是type的对象foo,但您也可以轻松摆脱寄生。在某种程度上,这种怪异之所以会发生是因为C语法的“直接声明符”生成规则满足了声明函数和变量的双重目的。

另一方面,Java语法对变量声明和函数声明有单独的生产规则。如果你写

foo a;

那么您知道它是一个变量声明,foo可以明确地解析为类型名。如果foo尚未在当前作用域的某个位置定义该类,则这可能不是有效的代码,但这是语义分析的工作,可以在以后的编译器遍历中执行。

我已经看到它说C由于typedef很难解析,但是您也可以在Java中声明自己的类型。除了之外direct_declarator,还有哪些C语法规则有误?


阅读 197

收藏
2020-12-03

共1个答案

一尘不染

解析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
/解析树进行操作。实际上,您需要知道每个标识符的定义以及定义的用途(“名称和类型解析”,草率地构建符号表)。事实证明,这比完成正确的解析器要花很多功夫,再加上继承,接口,重载和模板,所有这些语义都是用非正式的自然语言编写的,这分散了数十到数百个页面语言标准。C
++在这里真的很糟糕。从这个角度来看,Java 7和8变得非常糟糕。(而且符号表并不是您所需要的;请参阅我的简历,以获取有关“解析后的生活”的更长的文章)。

大多数人都在为纯解析部分而苦苦挣扎(通常永不完结;请检查SO本身是否有很多有关如何为实际语言构建解析器的问题),因此他们永远都看不到解析后的生命。然后,我们得到了关于难以解析的内容的民间定理,而没有任何关于该阶段之后发生的情况的信号。

修复C ++语法将无济于事。

关于更改C 语法:您会发现需要修补很多地方,以照顾任何C
语法中各种局部和实际的歧义。如果您坚持认为,以下列表可能是一个很好的起点。我认为,如果您不是C
标准委员会的成员,那么这样做是没有意义的。如果这样做,并使用该代码构建了编译器,那么没有人会理智地使用它。在现有的C
应用程序上投入了太多资金,无法切换以方便构建解析器的人员。此外,他们的痛苦已经过去,现有的解析器可以正常工作。

您可能要编写自己的解析器。好没关系;
只是不要期望社区中的其他人能够让您更改他们必须使用的语言以使其更容易使用。他们都希望对他们来说更容易,那就是使用已记录和实现的语言。

2020-12-03