作者回复: 是的。
我们通过改写规则的方法,能够避免左递归,但无法同时照顾结合性。这是很多教科书都没有提到的一件事情。
好在,这个事情比较简单,因为改写后的规则,是多了一个标准的“尾巴”。对,很多人都称呼它为尾巴。这个尾巴可以特别处理。
也就是说,结合性的信息已经不是单纯通过上下文无关文法提供了,要辅助额外的信息。
无独有偶,还有的作者用别的方法来解决算法优先级问题,比如LLVM的一个初学者教程,用的也是标注算符优先级的方法,也要在文法的基础上提供额外的信息给算法。
http://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html
本课程讲究实践。在实践中才会看到这些教科书上讲不到的点,但在面对实际问题时必须要解决。
作者回复: 我给你解释一下吧:
以 add -> mul | add + mul 为例,
-> 意思是推导出;
| 意思是“或者”
这个加号,我回头修改一下吧,可以用引号引起来,'+'只是匹配一个+号字符的意思,没有别的意思。
所以,这个产生式的意思是:
加法表达式,要么是一个乘法表达式,要么是一个加法表达式,后面跟个+号,然后再跟一个乘法表达式。
参考书的话,看看这个链接:https://time.geekbang.org/column/article/125948
作者回复: 厉害!点赞!
作者回复: 有道理!用EBNF的话,+号有特殊含义。
我们修改一下文稿。
谢谢你的建议,你很细心,并且自己去做研究了!
作者回复: 是,没错。
作者回复: 好的,我对于公式推导过程再加个图。加完了在回复中告诉你。
你指的是用:
add -> mul add'
add' -> + mul add' | ε
来推导2+3+4的过程不清楚吗?
作者回复: 转化成EBNF:add ::= mul ( '+' mul)*
一个表达式就解决了,更简洁。不需要add'了。
推导过程,要看算法。每种算法采用的推导过程是不一样的。如果用递归下降算法,推导:2+3*5
我们按照调用过程分成几层:
第1层:采用 mul add',因为mul能完整的匹配2,不能再往后匹配了,所以第一个子节点建立完毕。接着用add'去建立第二个子节点。
第2层:运用add'的第一个产生式,先匹配上了+号,之后去匹配mul,也就是3*5,也是成功的。然后再去匹配add'。
第3层:这次用add'的时候,还是先尝试第一个产生式,失败。为什么呢?因为没有+号。回溯。尝试第二个产生式,即epsilon。也就是返回空。那么第3层就完成了。
第3层成功后第2层,第2层也就成功完成了。
同理,返回第1层,第1层也成功。
这个过程是否听得清楚?
可以换着不同的例子多推导几遍,就会变得很熟练了!
作者回复: AST是对计算机语言的结构化表示,它是一切后续工作的基础,比如做语义分析,翻译成目标代码。
看了一下你发的那个链接。是从类似lisp语言的函数调用翻译到C语言的格式。这属于语言翻译的范畴。
我有两点点评:
1.lisp语言很容易翻译,一个递归下降算法肯定搞定。因为它的语法结构很简单,所有的语法结构都是一层层括号的嵌套。
2.翻译后得到AST,再生成C的格式,这就很简单了。基本上就是把括号位置改一下而已。
感谢你经常参与讨论!
作者回复: 理论上是可以的,但需要给算法提供额外的信息。
采用递归下降算法的时候,我们在函数中标准的处理放肆,都是创建一个AST节点,并返回给调用者。调用者都是把返回的AST作为自己的子节点。
如果要改变结合性,相当于要知道什么时候把返回的节点作为自己的父节点。
Antlr里用属性标注的方法,来提供这个额外的信息。这种信息在标准的上下文无关文法中是无法提供的。
作者回复: 嗯。编译且运行了一下。
作者回复: 所有的操作符,你可以加上引号,也就是去匹配这样一个字符而已。没有太复杂的意思。
add -> mul | add '+' mul | add '-' mul
参考书籍的话,参见这篇攻略:https://time.geekbang.org/column/article/125948
作者回复: 如果想练习语法规则的推导,那么随便买哪本教材都可以。一般也都会带些练习。
其他的扩展资料,我后面有想到的,会提供链接。
作者回复: 嗯。留言中别人遇到的问题,对自己也会有用。你如果有问题的话,也多提问!
作者回复: 是的。
作者回复: 这两个产生式应该是不等价的。
你修改后的产生式,不能解析3*5这样的纯乘法表达式。
作者回复: 对的,递归下降算法都是先匹配完第一个元素,再匹配第二个,从左向右。
作者回复: 非常对!
1.就是要把这些看上去很难的概念,变成自己的直观理解。
2.基础概念,比如啥叫推导,就是要重视。不要觉得不好意思。还是那个话,在别人提不出问题的地方提问,才叫厉害。基础概念,我们容易一模糊就过去了。但推敲一下呢,很有意思。