yacc语法树系列(七)

475 阅读4分钟

这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

本文为译文,原文链接:dinosaur.compilertools.net/yacc/

接上文,继续下一节。

8:yacc环境(The Yacc Environment)

当用户输入一个规范给yacc时,output是C程序的文件,在大多数系统中叫做y.tab.c(由于本地文件系统的约定,不同安装文件名称可能不同)。yacc生成的函数叫做yyparse;这是一个数字值的函数。当它被调用时,它轮流重复调用用户提供的词法分析器的yylex(第三章)来获得输入的token。最终,要么检测到一个错误,yyparse返回1(如果不可能恢复错误);要么词法分析器返回结束标识符token,然后解析器接受。在这里,yyparse返回0.

用户必须给解析器提供一个确定的环境数量,为了获取一个工作中的程序。比如,在每个C语言程序,一个程序被调用的main方法必须被定义,最终调用yyparse。此外,一个叫做yyerror的程序会在侦测到语法错误后打印错误日志。

这两个程序必须被用户以某种方式提供。为了减轻使用yacc的初始化消耗,一个库已经被提供在默认的默认的main和yyerror的版本中。这个库的名称是system dependent;在很多系统中,这个库被通过一个 -ly的参数访问到加载器loader中。为了展示这些默认程序的片段,源代码在下面给出了:

        main(){
                return( yyparse() );
                }
and
        # include <stdio.h>

        yyerror(s) char *s; {
                fprintf( stderr, "%s\n", s );
                }

yyerror的参数是一个包含错误信息的字符串,经常是字符串”syntax error“。一般的应用想要做得比这个号。普遍来说,程序应该保持追踪输入的行号,然后在当语法错误被侦查出来的时候跟错误信息一起打印出来。外部的整形变量yychar在错误被检测到的时候会包含先行token号;这可以提供更好的诊断。由于主程序可能是由用户提供的(用户读取参数等),因此yacc库只在小型项目或者大型项目的早期阶段有用。

外部变量yydebug经常被设置成0.如果它被设置为非零,解析器将会给它的操作输出一个冗长的描述,包括哪个输入标识已经被读取的论述,还有解析器做了什么动作。依赖了操作环境,通过使用一个调试系统来设置这个变量是可能的。

9: Hints for Preparing Specifications

这个章节包含着各种各样的提示,以提高准备效率,容易修改,明确规范。这个独特子章节或多或少比较独立。

输入规范

很难提供一些包含大量操作的规则然后还有一个可读的规范文件。接下来的风格提示大多数归功于Brian Kernighan。

a. token名称使用所有的大写字母,所有的小写字母是非终止符号的名称。这条规则属于:"当事情出问题的时候知道应该怪谁"。

b. 把语法规则和操作放到分开的行。这允许在不自动更改另一个的情况下更改其中一个。

c. 把所有的规则一起放在同一左手边。主需要设置左手边一次,然后让所有后续的规则以一个竖线开始。

d. 只有在左侧的最后一条规则设置一个分号,然后把分号设置在单独一行。这允许新的规则很容易添加。

e. 缩进规则的主体用两次tab退格,动作主体使用三个tab退格

附录A的例子是根据这种风格写的,本文中的例子也是如此(空间允许的地方)。用户必须组织他自己的想法关于这些格式问题;然而,核心问题是通过混乱的操作代码让规则可见。

今天就到这里,下一节继续为大家讲解语法规则。