1 系列说明
2 语法分析说明
语法:组合单词以形成词组 从句 或句子的方法。
经过词法分析,我们已经可以将输入文本识别成一个个的单词,本阶段的目标是将这些单词识别成句子,判断单词的这种组合形式是否符合我们定义的语法。
2.1 用文法来定义语法
语法分析需要由递归而获得的额外的表示能力,显然正则表达式已经不能满足我们的需求。
事实上,文法也可以用来描述词法单词的结构,但正则表达式已经可以满足需求,这时使用正则表达式更为简练。
2.2 LR(1) 分析法
@%……¥&%#¥太复杂不想说
总之,LR(1) 是一种非常非常强大的分析算法,能够解决很多归约-归约冲突,大多数用上下文无关文法描述其语法的程序设计语言都有一个 LR(1) 文法。
2.3 使用 Yacc 生成语法分析器
构造LR(1)分析表的算法简单得足以用计算机来自动完成,而且手工构造十分麻烦无趣,所以使用Yacc是一个明智的决定。
类似Lex,Yacc规范分为三部分
%{ ... %} ... %% ...
第一部分同Lex,包含include和声明
第二部分定义从词法分析中接收的终结符,开始符号,优先级等
第三部分定义文法及语义动作,语法分析阶段只定义文法,语义动作到语义分析时候再完成。
2.3.1 冲突
Yacc 选择移近来解决移进-归约冲突,选择使用在文法中先出现的规则来解决归约-归约冲突。
2.3.2 优先级指导
定义优先级是为了解决二义性,这样写文法的时候方便的多。
Yacc在第二部分可以假如优先级指导命令
%left COMMA %right PLUSASSIGN MINUSASSIGN TIMESASSIGN DIVIDEASSIGN ASSIGN %left OR %left AND %left EQ NEQ %left LE GE LT GT %left PLUS MINUS %left TIMES DIVIDE MOD %right INC DEC NOT %left LPAREN RPAREN LBRACK RBRACK
自上而下优先级降低,left right 说明单词是左结合还是右结合。
3 具体实现
语法分析器和改进过的词法分析器源码见文章开头。
进行到本阶段,编译器发展为四个模块:
1.错误处理模块(errormsg.c errormsg.h):用来产生含文件名和行号的报错信息
2.常用工具模块(util.c util.h):定义一些常用的函数
3.词法分析模块(simplec.lex):通过Lex进行词法分析
4.语法分析模块(simplec.yacc):通过Yacc进行语法分析
其中上一阶段的 token.h 已经不再需要,作为代替,Yacc会根据我们写的文法的单词规范自动生成一个与单词相关的头文件 y.tab.h ;parsetest.c是一个驱动程序,正常情况下会输出 Parsing successful!
附:ANSI C grammar (Lex) ANSI C grammar (Yacc)
语法分析 Done.