【编译原理】扩展试验_语法制导翻译_2_B_2.将表达式翻译为后缀式-LR分析

编译原理最后的单人实验。

学校:烟大

老师是孔老师,孔老师是位十分认真负责的老师,跟着孔老师学了半年感觉学到了很多东西,感谢孔老师。

题目如上:扩展试验_语法制导翻译_2_B_2.将表达式翻译为后缀式-LR分析

 

本题扩展了乘法,括号的后缀转换,由于加法和减法,乘法和除法运算逻辑相同,所以只需实现加法,乘法,括号运算。

后面会贴上自己源码的下载链接:

词法分析部分由lex实现,语法分析手动构造的。

本实验代码参考了老师给的计算器calc.lex范例程序,和16级学长的实现方法,在此鸣谢。


源码分享:https://download.csdn.net/my/uploads 编译原理-2019压缩包正在审核。

百度云:链接:https://pan.baidu.com/s/1DZdJzZO4gCbaHyCZlxXxHw 
提取码:o2vq


lex:

%option noyywrap
%{
    #include <stdio.h>
       #include <stdlib.h>
    int num=0;
       int num_num = 0;
       int num_op = 0;
       int aa[200]={0};
       char cc[200]={0};
%}

INTEGER [1-9][0-9]*

ID [a-zA-Z][a-zA-Z]*

operate [+-*()]

SPACE [ \n\t]

over [#]

%%
{over} {
    return 0;
}
{operate} {
    cc[num]=*yytext;
    num++;
        
}

{INTEGER} { 

    aa[num_num]=atoi(yytext);
    cc[num]='i';
    num++;     
      num_num++;

    /*数字数加一*/

}


 

{SPACE} {

   /*什么也不做,滤掉白字符和其它字符*/

}
. {
    printf("error\n");
}
%%

int www()

{
    yylex();
     return 0;

}
 


LR分析部分:

LR.c文件:

#include<stdio.h>
#include<string.h>
#include"lex.h"
char *action[12][6]={"S5#",NULL,NULL,"S4#",NULL,NULL,            /*ACTION表*/
                      NULL,"S6#",NULL,NULL,NULL,"acc",
                      "R2#","R2#","S7#","R2#","R2#","R2#",
                      "R4#","R4#","R4#","R4#","R4#","R4#",
                      "S5#",NULL,NULL,"S4#",NULL,NULL,
                      "R6#","R6#","R6#","R6#","R6#","R6#",
                      "S5#",NULL,NULL,"S4#",NULL,NULL,
                      "S5#",NULL,NULL,"S4#",NULL,NULL,
                      NULL,"S6#",NULL,NULL,"S11#",NULL,
                      "R1#","R1#","S7#","R1#","R1#","R1#",
                      "R3#","R3#","R3#","R3#","R3#","R3#",
                      "R5#","R5#","R5#","R5#","R5#","R5#"};

int goto1[12][3]={1,2,3,                          /*GOTO表*/
                  0,0,0,
                  0,0,0,
                  0,8,0,
                  8,2,3,
                  0,0,0,
                  0,9,3,
                  0,0,10,
                  0,0,0,
                  0,0,0,
                  0,0,0,
                  0,0,0};

char vt[6]={'i','+','*','(',')','#'};                       /*存放非终结符*/
char vn[3]={'E','T','F'};                           /*存放终结符*/
char *LR[7]={"L-E#","E-E+T#","E-T#","T-T*F#","T-F#","F-(E)#","F-i#"};    /*存放产生式*/

int a[20];                /*状态栈*/
char b[20],c[20],c1;    /*符号栈, 剩余符号栈*/
int top1,top2,top3,top,m,n;
/*运行*/
void main(){
    int g,h,i,j,k,l,p,y,z,count,dd=0;
    char x,copy[10],copy1[10];
    int top4=0;
    char id[20];
    top1=0;            //状态栈栈顶
    top2=0;            //符号栈栈顶
    top3=0;            //指向最后一个符号串,记录输入符号的个数
    top=0;            //top指向输入栈栈顶

    a[0]=0;            //状态栈
    y=a[0];
    b[0]='#';        //符号栈
    count=0;z=0;

    printf("请输入表达式\n");
    www();
    cc[num]='#';
    do{
        y=z;            /*y,z指向状态栈栈顶*/
        m=0;
        n=0;
        g=top;                //top指向输入栈栈顶
        j=0;
        k=0;
        x=cc[top];

        while(x!=vt[j]&&j<=5) j++;            //判断当前符号是否是终结符

        if(j==5&&x!=vt[j]){
            printf("error\n");
            return;
        }

        if(action[y][j]==NULL){                /*查表*/
            printf("error\n");
            return;
        }
        else
            strcpy(copy,action[y][j]);

        if(copy[0]=='S')

        {                    /*处理移进*/
            i=1;
            h=copy[i]-'0';                            //计算下一个状态
            i++;
            while(copy[i]>='0'&&copy[i]<='9')
            {
                h=copy[i]-'0';
                i++;
            }
            i=i-1;

            z=copy[1]-'0';
            for(j=2;j<=i;j++)
            {
                z=z*10+copy[j]-'0';
            }

            top1=top1+1;
            top2=top2+1;
            a[top1]=z;                        //将下一个状态数移进状态栈
            b[top2]=x;                        //将读到的这个字符移进符号栈

            top=top+1;

        }

        if(copy[0]=='R'){                      /*处理归约*/

            h=copy[1]-'0';                    //H记录的是归约用到的产生式

            if(h==6)
            {
                printf("%d ",aa[dd]);
                dd++;
            }
            if(h==3)
            {
                printf("* ");
            }
            if(h==1)
            {
                printf("+ ");
            }

            strcpy(copy1,LR[h]);            //copy1记录当前归约用到的产生式

            while(copy1[0]!=vn[k]) k++;        //k记录归约后产生的非终结符的位置

            l=strlen(LR[h])-4;

            //top1=top1-l+1;
            //top2=top2-l+1;
            top1=top1-l;
            top2=top2-l;

            y=a[top1-1];                    //记录当前状态的上一个状态

            p=goto1[y][k];                    //下一个要跳转的状态

            a[top1]=p;
            b[top2]=copy1[0];
            z=p;

        }
    }while(action[y][j]!="acc");
    printf("\nacc\n");
    for(i=0;i<top4;i++)
        printf("%c ",id[i]);
    printf("\n");
}

lex.h文件

/* A lexical scanner generated by flex */
/*LEX头文件*/

/* Scanner skeleton version:
 * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.85 95/04/24 10:48:47 vern Exp $
 */

#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5

#include <stdio.h>


/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
#ifndef __cplusplus
#define __cplusplus
#endif
#endif


#ifdef __cplusplus

#include <stdlib.h>
#include <unistd.h>

/* Use prototypes in function declarations. */
#define YY_USE_PROTOS

/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST

#else    /* ! __cplusplus */

#if __STDC__

#define YY_USE_PROTOS
#define YY_USE_CONST

#endif    /* __STDC__ */
#endif    /* ! __cplusplus */

#ifdef __TURBOC__
 #pragma warn -rch
 #pragma warn -use
#include <io.h>
#include <stdlib.h>
#define YY_USE_CONST
#define YY_USE_PROTOS
#endif

#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif


#ifdef YY_USE_PROTOS
#define YY_PROTO(proto) proto
#else
#define YY_PROTO(proto) ()
#endif

/* Returned upon end-of-file. */
#define YY_NULL 0

/* Promotes a possibly negative, possibly signed char to an unsigned
 * integer for use as an array index.  If the signed char is negative,
 * we want to instead treat it as an 8-bit unsigned char, hence the
 * double cast.
 */
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)

/* Enter a start condition.  This macro really ought to take a parameter,
 * but we do it the disgusting crufty way forced on us by the ()-less
 * definition of BEGIN.
 */
#define BEGIN yy_start = 1 + 2 *

/* Translate the current start state into a value that can be later handed
 * to BEGIN to return to the state.  The YYSTATE alias is for lex
 * compatibility.
 */
#define YY_START ((yy_start - 1) / 2)
#define YYSTATE YY_START

/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)

/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart( yyin )

#define YY_END_OF_BUFFER_CHAR 0

/* Size of default input buffer. */
#define YY_BUF_SIZE 16384

typedef struct yy_buffer_state *YY_BUFFER_STATE;

extern int yyleng;
extern FILE *yyin, *yyout;

#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2

/* The funky do-while in the following #define is used to turn the definition
 * int a single C statement (which needs a semi-colon terminator).  This
 * avoids problems with code like:
 *
 *     if ( condition_holds )
 *        yyless( 5 );
 *    else
 *        do_something_else();
 *
 * Prior to using the do-while the compiler would get upset at the
 * "else" because it interpreted the "if" statement as being all
 * done when it reached the ';' after the yyless() call.
 */

/* Return all but the first 'n' matched characters back to the input stream. */

#define yyless(n) \
    do \
        { \
        /* Undo effects of setting up yytext. */ \
        *yy_cp = yy_hold_char; \
        yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
        YY_DO_BEFORE_ACTION; /* set up yytext again */ \
        } \
    while ( 0 )

#define unput(c) yyunp

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值