我知道,the grammars of C and C++ are context-sensitive,尤其是你需要一个C语言的"lexer hack".另一方面,我的印象是,尽管这两种语言之间有相当大的相似性,但你只需要两个前瞻标记就可以解析Java.

What would you have to change about C to make it more tractable to parse?

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

foo (a);

可以用参数a调用void函数foo.或者,它可以将a声明为foo类型的对象,但您也可以轻松地摆脱偏执.在某种程度上,之所以出现这种奇怪现象,是因为C grammar的"直接声明器"生成规则实现了声明函数和变量的双重目的.

另一方面,Java grammar对变量声明和函数声明有单独的产生式规则.如果你写信

foo a;

然后你知道它是一个变量声明,foo可以明确地被解析为一个类型名.如果类foo没有在当前范围内的某个地方定义,那么这可能不是有效代码,但这是一项语义分析工作,可以在以后的编译器过程中执行.

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

推荐答案

Parsing C++ is getting hard. Parsing Java is getting to be just as hard.

看这个SO answer discussing why C (and C++) is "hard" to parse.简短的总结是C和C++ grammars本质上是含糊的;它们将为您提供多个解析,您可以使用上下文来解决歧义.然后,人们会错误地认为在解析时必须解决歧义;并非如此,见下文.如果你坚持在解析时解决歧义,你的解析器会变得更复杂,也更难构建;但这种复杂性是一种self 造成的伤害.

IIRC, Java 1.4's "obvious" LALR(1) grammar was not ambiguous, so it was "easy" to parse. I'm not so sure that modern Java hasn't got at least long distance local ambiguities; there's always the problem of deciding whether "...>>" closes off two templates or is a "right shift operator". I suspect modern Java does not parse with LALR(1) anymore.

但是,对于两种语言,可以通过使用强解析器(或弱解析器和上下文集合HAG作为C和C++前端来完成)来解决解析问题.

But parsing isn't really where the problem is.

解析之后,您将需要对AST/parse树进行一些操作.实际上,对于每个标识符,您都需要知道它的定义是什么,以及在哪里使用("名称和类型解析",草率地,构建符号表).事实证明,这比正确使用解析器要困难得多,其中包括继承、接口、重载和模板,而且所有这些的语义都是用非正式的自然语言编写的,跨越了语言标准的数十到数百页.这里的C++非常糟糕.从这个Angular 来看,Java7和Java8变得非常糟糕.(符号表并不是你所需要的全部;请参阅我的个人简历,以获得一篇关于"解析后的生活"的长篇文章).

大多数人都在为纯粹的解析部分而挣扎(通常永远不会完成;关于如何为真正的语言构建有效的解析器,有很多很多问题,请自己判断一下),所以他们永远看不到解析之后的生活.然后我们得到了一些民间定理,关于什么是很难解析的,并且没有信号表明在那个阶段之后会发生什么.

Fixing C++ syntax won't get you anywhere.

关于改变C++语法:你会发现你需要修补很多地方来处理任何C++语法中的局部和真实模糊.如果你坚持,following list might be a good starting place美元.我认为如果你不是C++标准委员会,那么做这件事没有意义.如果你这么做了,并用它构建了一个编译器,没有人会理智地使用它.太多的投资在现有的C++应用程序中,为了便于构建解析器的人而切换;此外,他们的痛苦已经过go ,现有的解析器工作正常.

您可能希望编写自己的解析器.好的,那很好;只是不要指望社区的睡觉会让你改变他们必须使用的语言来让你更容易.他们都想让自己更轻松,那就是按照文档和实现的方式使用语言.

C++相关问答推荐

C限制限定符是否可以通过指针传递?

Mbed TLS:OAEP的就地en—/decryption似乎不起作用'

编译SDL 2时缺少SDL_ttf

ATTiny1606定时器TCA 0中断未触发

在C中使用JMP_buf数组进行线程化(在xv6中测试)

如何在C中从函数返回指向数组的指针?

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

为什么memcpy进入缓冲区和指向缓冲区的指针工作相同?

为什么中断函数会以这种方式影响数组?

如何使用_newindex数组我总是得到错误的参数

如何使用C++在控制台中以彩色打印被阻止的客户端

C代码在字符串中删除不区分大小写的子字符串的问题

C语言中的外部关键字

C语言中MPI发送接收字符串时出现的分段错误

运行时错误:在索引数组时加载类型为';char';`的空指针

GetText不适用于包含国际字符的帐户名称

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

即使我在C++中空闲,也肯定会丢失内存

Malloc和对齐

挥发性语义的形式化理解