1、一个简化子集作为分析对象,根据如下描述其语法结构的 BNF 定义 G2, 任选一种学过的语法分析方法, 针对运算对象为无符号常数和变量 的四则运算,设计并实现一个语法分析程序。G2: | +-因式 |*/运算对象 | ()若将语法范畴 、 和 分别用 E 、 T 、 F 和 i 代表,则 G2可写成:G2E:E T | E+T | E-T T F | T*F | T/F F i | (E)由实验一输出的单词串,例如:UCON , PL , UCON , MU ,ID输出:若输入源程序中的符号串是给定文法的句子,则输出“ RIGHT ” ,并且给出 每一步分析过程;若不是句子,即输入串有错误,则
2、输出“ ERROR ” ,并且显示分 析至此所得的中间结果, 如分析栈、 符号栈中的信息等, 以及必要的出错说明信 息。3、语义分析程序设计与实现对文法 G2中的产生式添加语义处理子程序,完成运算对象 是简单变量 (标识符) 和无符号数的四则运算的计值处理, 将输入的四则运算转 换为四元式形式的中间代码。包含测试用例(由标识符、无符号数和 +、 、 *、 /、 (、 ) 构成的算术 表达式)的源程序文件。输出 :将源程序转换为中间代码形式表示, 并将中间代码序列输出到文件中。 若源程序中有错误,应指出错误信息二、设计思路1、词法分析程序设计与实现1) 单词分类为了编程的实现。我们假定要编译的语
3、言中,全部关键字都是保留字,程序 员不得将它们作为源程序中的标识符; 作了这些限制以后, 就可以把关键字和标 识符的识别统一进行处理。 即每当开始识别一个单词时, 若扫视到的第一个字符 为字母, 则把后续输入的字母或数字字符依次进行拼接, 直至扫视到非字母、 数 字字符为止, 以期获得一个尽可能长的字母数字字符串, 然后以此字符串查所谓 保留字表(此保留字表要事先造好) ,若查到此字符串,则取出相应的类别码; 反之,则表明该字符串应为一标识符。表 1语言中的各类单词符号及其分类码表2)词法分析器的设计函数 GETCHAR :每调用一次,就把扫描指示器当前所指示的源程序字符送入 字符变量 ch
4、,然后把扫描指示器前推一个字符位置。字符数组 TOKEN :用来依次存放一个单词词文中的各个字符。函数 CAT :每调用一次, 就把当前 ch 中的字符拼接于 TOKEN 中所存字符串的 右边。函数 LOOKUP :每调用一次,就以 TOKEN 中的字符串查保留字表,若查到,就 将相应关键字的类别码赋给整型变量 c ;否则将 c 置为零。函数 RETRACT :每调用一次,就把扫描指示器回退一个字符位置(即退回多 读的那个字符) 。函数 OUT :一般仅在进入终态时调用此函数,调用的形式为 OUT(c, VAL) 。图 1 识别表 I 所列语言中的部分单词的 DFA 及相关的语义过程3)词法分
5、析程序的实现 编写的扫描器 :char TOKEN20,TOKEND20,TOKENDO20; int lookup (char*); void out (int, char*); void report_error (void); /extern void LEX(void); int siagn=0;/标志位 FILE *fp1; char *KeyWordTableMAX_KEY_NUMBER=/* 查保留字表,判断是否为关键字*/int lookup (char *token)int n=0;while (strcmp(KeyWordTablen, KEY_WORD_END) /*st
6、rcmp比较两串是否 相同,若相同返回 0*/if (!strcmp(KeyWordTablen, token) /*比较 token 所指向的关键字 和保留字表中哪个关键字相符 */return n+1; /*根据单词分类码表 I ,设置正确的关键字类别码,并 返回此类别码的值 */break;n+;return 0;void scanner_example (FILE *fp)char ch; int i, c, isd,cpoint; double o;ch=fgetc (fp);/fgetc函数 在文件中读取一个字符if (isalpha (ch) /*it must be a ide
7、ntifer! 它必须是一个标识符 判 断字符 ch 是否为英文字母,若为小写字母,返回 2,若为大写字母,返回 1。若 不是字母,返回 0*/TOKEN0=ch;ch=fgetc(fp);i=1;while (isalnum (ch)|ch=.)/isalnum函数 判断 ch 是否为空 当 ch 为数字 0-9或字母 a-z 及 A-Z 时,返回非零值,否则返回零if(ch=)cpoint=-1;/标志字符串中有小数点TOKENi=ch;i+;TOKENi= 0;=:) fseek (fp,-2,1);siagn=1;else fseek (fp,-1,1);/fseek(fp,-1,1)
8、; /* retract fseek函数 每调用一次,就把扫描 指示器回退一个字符位置(即退回多读的那个字符) */i=0;if(TOKENi=o|TOKENi=O i+;xXwhile(TOKENi!if(!isdigit(TOKENi)|TOKENi!a|TOKENi!bc def|TOKENi!ABCD|TOK ENi!EFisd=-1;isd=16;/标志字符串十六进制else0123|TOKEN i=4567isd=8;/标志字符串八进制if(TOKENi!|TO KENi! .if(isd=8)strncpy(TOKEND,TOKEN+1,strlen(TOKEN)-1);/拷贝函
9、数/printf(o=octal(TOKEND);sprintf(TOKENDO, out(OCTAL,TOKENDO);else if(isd=16)strncpy(TOKEND,TOKEN+2,strlen(TOKEN)-2);out(HEX,TOKENDO);if(cpoint=-1)report_error();/当字符串中有小数点时,为错误elsec=lookup (TOKEN);/looup查询函数 查找保留字if (c=0)out (ID,TOKEN);out (c,if(isdigit(ch)/isdigit函数 检查参数 c 是否为阿拉伯数字 0到 9。 /*TOKEN0=ch;while(isdigit(ch)|ch=-*/int Class;fseek (fp,-1,1);Class=LEX(fp);if(Class=1)char pi30 =
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1