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. 递归下降分析程序

    #include<string.h>
    #include<stdio.h>
    #include<stdlib.h>
    void lrparser();
    void yucu();
    void scaner(); //词法分析
    void statement();//语句
    void condition();//条件
    void expression();//表达式
    void term();//项
    void factor();//因子
    int kk=0;
    char prog[100],token[10];//输入程序段数组,大小为80
    int syn,i=0,ks=0,js=0,m,n,sum=0,k=0;
    char ch;
    const char *blz[7]= {"begin","if","then","while","do","end","odd"};//保留字

    int main() {
    // for(n=0;n<7;n++){
    // printf("%s",blz[n]);
    // }
    printf("********************语法分析程序*************** ");
    printf("请输入源程序,以#结束: ");
    ch=getchar();
    while(ch!='#') {
    prog[i]=ch;
    ch=getchar();
    i++;
    }
    prog[i]='#';
    i++;
    prog[i]='';
    i=0;
    scaner();
    lrparser();
    printf("语法分析结束! ");

    }

    void scaner() {
    printf("%c",ch);
    ch=prog[i++];
    while(ch == ' ' || ch == 10 || ch == 9||ch== 13) {//忽略空格换行回车和tab
    ch=prog[i++];
    }

    if((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')) {//判断是保留字还是标识符
    n=0;
    syn=10;//字母数字码为10
    char a=ch;
    while((ch>='a' && ch<='z') ||(ch>='A' && ch<='Z')||(ch>='0' && ch<='9')) {
    token[n++]=ch;
    ch=prog[i++];
    }
    token[n++]='';
    for(n=0; n<7; n++) {
    if(strcmp(token,blz[n])==0) {
    syn=n+1;//给保留字赋值,begin为1,if为2,then为3,while为4,do为5,end为6,odd为7
    printf("<%s,%d> ",token,syn);
    if(syn==1) {
    ks=1;
    }
    if(syn==6) {
    js=6;
    }
    break;
    }
    }
    i--;
    if(syn==10) {
    ch=a;
    printf("<%c,%d> ",ch,syn);
    }

    } else if(ch>='0' && ch<='9') {//数字判断
    syn=11;
    printf("<%c,%d> ",ch,syn);
    } else {
    switch(ch) {//运算符,界符判断
    case '<':
    ch=prog[i++];
    if(ch=='>') {
    syn=21;//当为<>时,数字码为21
    printf("<%c,%d> ",ch,syn);
    } else if(ch=='=') {
    syn=22;//当为<=时,数字码为22
    printf("<%c,%d> ",ch,syn);
    } else {
    i=i-1;
    ch=token[i];
    syn=20;//当为<时,数字码为20
    printf("<%c,%d> ",ch,syn);
    }
    break;
    case '>':
    ch=prog[i++];
    if(ch=='=') {
    syn=24;//当为>=时,数字码为24
    printf("<%c,%d> ",ch,syn);
    } else {
    i=i-1;
    ch=prog[i];
    syn=23;//当为>时,数字码为23
    printf("<%c,%d> ",ch,syn);
    }
    break;
    case ':':
    ch=prog[i++];
    if(ch=='=') {
    syn=18;//当为:=时,数字码为18
    printf("<%c,%d> ",ch,syn);
    } else {
    syn=17;//当为:时,数字码为17
    i=i-1;
    ch=prog[i];
    printf("<%c,%d> ",ch,syn);
    }
    break;
    case '+':
    syn=13;//当为+时,数字码为13
    printf("<%c,%d> ",ch,syn);
    break;
    case '-'://当为-时,数字码为14
    syn=14;
    printf("<%c,%d> ",ch,syn);
    break;
    case '*':
    syn=15;//当为*时,数字码为15
    printf("<%c,%d> ",ch,syn);
    break;
    case '/':
    syn=16;//当为<>时,数字码为21
    printf("<%c,%d> ",ch,syn);
    break;
    case ';':
    syn=26;//当为;时,数字码为26
    printf("<%c,%d> ",ch,syn);
    break;
    case '(':
    syn=27;//当为(时,数字码为27
    printf("<%c,%d> ",ch,syn);
    break;
    case ')'://当为)时,数字码为28
    syn=28;
    printf("<%c,%d> ",ch,syn);
    break;
    case '='://当为=时,数字码为25
    syn=25;
    break;
    case '#'://当为#时,数字码为0
    syn=0;
    printf("<%c,%d> ",ch,syn);
    break;
    default:
    syn=-1;
    }
    }
    }
    void lrparser() {
    if(ks==1) {
    scaner();
    yucu();
    } else {
    yucu();
    printf("语法错误缺失'begin' ");
    }
    return;
    }

    void yucu() {
    statement();
    while(syn==26) {
    scaner();
    statement();
    }
    return;
    }

    void statement() {
    if (syn==10) { //为标识符
    scaner();
    if (syn==18||syn==25) { //为 :=
    scaner();
    expression();
    } else {
    printf("error! ");
    }
    } else {
    if(syn==0&&ks==1&&js==6)
    printf("Success!语法无错误!分析完成 "); //当匹配到#且begin、end存在时,输出语法无错误
    else if(syn==0&&js!=1) {
    printf("语法错误,缺失'end' ");
    }
    }
    return;
    }
    void condition(){
    expression();
    if(syn==25||syn==20||syn==22||syn==23||syn==24)
    expression();
    while(syn==7){
    expression();
    }
    return;
    }

    void expression() {
    if(syn==13 || syn==14) {//为+或-时
    scaner();
    term();//处理项
    } else {
    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)
    scaner();
    else if(syn==11)
    scaner();
    else if(syn==27) {//左括号
    expression();
    if(syn==28)
    scaner();
    else {
    printf(" ')' 错误 ");
    kk=1;
    }
    }
    return;
    }

     

     

  • 相关阅读:
    Array中使用异步函数遍历元素,Array循环同步执行
    vscode设置快捷键"h"快速生成html模板
    IOS(苹果手机)使用video播放HLS流,实现在内部播放及全屏播放(即非全屏和全屏播放)。
    FTP服务器与客户端的安装与配置
    移动端页面顶部滑动实现菜单的弹出与隐藏
    JS十大经典排序排序算法
    【bug】table重新加载数据,页面滚动条下沉到底部,记录scrollTop后将其恢复scrollTop出现闪烁
    寄生组合式继承
    扁平对象,转为树形对象
    使用CSS禁止textarea调整大小功能的方法
  • 原文地址:https://www.cnblogs.com/hoioh/p/11959086.html
Copyright © 2011-2022 走看看