zoukankan      html  css  js  c++  java
  • 递归下降语法分析

    一、实验目的:

    利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

    编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

    二、实验原理

    每个非终结符都对应一个子程序。

    该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

    • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
    • 每遇到一个非终结符,则调用相应的子程序

    三、实验要求说明

    输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

    例如:

    输入begin a:=9;x:=2*3;b:=a+x end #

    输出success

    输入x:=a+b*c  end #

    输出‘end' error

    四、实验步骤

    1.待分析的语言的语法(参考P90)

    2.将其改为文法表示,至少包含

    –语句

    –条件

    –表达式

    3. 消除其左递归

    4. 提取公共左因子

    5. SELECT集计算

    6. LL(1)文法判断

    7. 递归下降分析程序

    各种单词符号对应的种别码

    单词符号 种别码 单词符号 种别码
    begin 1 : 17
    if 2 := 18
    then 3 < 20
    while 4 <> 21
    do 5 <= 22
    end 6 > 23
    letter(letter+digit)* 10 >= 24
    digit* 11 = 25
    + 13 : 26
    - 14 ( 27
    * 15 ) 28
    / 16 # 0

    #include<stdio.h>


    #include<stdlib.h> #include<string.h> //程序段 单词 char prog[800], dc[8]; //单词中的字符 char ch; //单词符号种别码 int syn, p, m = 0; //整数sum int n, sum = 0; //保留字 char *word[6] = { "begin","if","then","while","do","end" }; //判断是否有错误 int kk = 0; void scaner(); void lrparser(); void yucu(); void statement(); void condition(); void expression(); void term(); void factor(); void scaner() { m = 0; for (n = 0; n < 8; n++) { dc[n] = NULL; } ch = prog[p++]; while (ch == ' ') { ch = prog[p]; //指针+1往后移一位 p++; } //判断输入是否位数字或字母 if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { m = 0; while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { dc[m++] = ch; ch = prog[p++]; } p--; syn = 10; //保留字 for (n = 0; n < 6; n++) { if (strcmp(dc, word[n]) == 0) { syn = n + 1; break; } } } //数字 else if ((ch >= '0'&&ch <= '9')) { sum = 0; while ((ch >= '0'&&ch <= '9')) { sum = sum * 10 + ch - '0'; ch = prog[p++]; } p--; syn = 11; } else { switch (ch) { case '<':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '>') { syn = 22; dc[m++] = ch; } else if (ch == '=') { syn = 21; dc[m++] = ch; } else { syn = 20; p--; } break; case '>':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '=') { syn = 24; dc[m++] = ch; } else { syn = 23; p--; } break; case ':':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '=') { syn = 18; dc[m++] = ch; } else { syn = 17; p--; } break; case '*': syn = 15; dc[0] = ch; break; case '/': syn = 16; dc[0] = ch; break; case '+': syn = 13; dc[0] = ch; break; case '-': syn = 14; dc[0] = ch; break; case '=': syn = 25; dc[0] = ch; break; case ';': syn = 26; dc[0] = ch; break; case '(': syn = 27; dc[0] = ch; break; case ')': syn = 28; dc[0] = ch; break; case '#': syn = 0; dc[0] = ch; break; case ' ': syn = -2; dc[0] = ch; break; } } } //判断是否以begin开始,end #结束 void lrparser() { //begin if (syn == 1) { scaner(); yucu(); //end if (syn == 6) { scaner(); if (syn == 0 && kk == 0) { printf("success "); } } else { printf("编译出错,缺少 'end' ! "); kk = 1; exit(0); } } else { printf("编译出错缺少 'begin' ! "); kk = 1; exit(0); } return; } //语句串 void yucu() { statement(); while (syn == 26) { scaner(); statement(); } return; } //语句 void statement() { //为标识符 if (syn == 10) { scaner(); if (syn == 18) { //:= scaner(); expression(); } else { printf("error!"); kk = 1; exit(0); } } else if (syn == 2) { //if condition(); scaner(); if (syn == 3) { statement(); } else { printf("编译出错缺少 'then' ! "); kk = 1; exit(0); } } else { printf("error!"); kk = 1; exit(0); } return; } //条件 void condition() { expression(); if (syn == 25 || syn == 0 || syn == 20 || syn == 21 || syn == 23 || syn == 24) { scaner(); } else { printf("error! "); kk = 1; exit(0); } expression(); return; } //表达式 void expression() { term(); while (syn == 13 || syn == 14) { scaner(); term(); } return; } //项 void term() { factor(); while (syn == 15 || syn == 16) { scaner(); factor(); } return; } //因子 void factor() { if (syn == 10 || syn == 11) { //为标识符或整常数时,读下一个单词符号 scaner(); } else if (syn == 27) { scaner(); expression(); if (syn == 28) { scaner(); } else { printf(" ')' 错误 "); kk = 1; exit(0); } } else { printf("表达式错误 "); kk = 1; exit(0); } return; } int main(void) { //从0开始逐个读取 p = 0; int i; printf("请输入源程序: "); do { scanf("%c", &ch); prog[p++] = ch; } while (ch != '#'); //指针从0开始 p = 0; do { scaner(); lrparser(); } while (syn != 0); printf("语法分析结束! "); }


    运行结果

     

  • 相关阅读:
    python活力练习Day13
    检测一个字符串在另外一个字符串中的位置
    Python活力练习Day12
    Python多进程与单进程效率对比
    HTML-Note
    Python判断自定义的参数格式是否正确
    图片的灰与彩
    Git常用命令
    Linux 单引号和双引号的区别
    类函数中获取进程池对象的地址
  • 原文地址:https://www.cnblogs.com/createwell/p/12686636.html
Copyright © 2011-2022 走看看