运用Yacc和Lex来DIY计算器(代码部分)

前言

这篇文章有点makefile的感觉
直接看代码应该问题不大,这里直接附上代码,本来想弄在GitHub上,后来觉得太麻烦了,还是直接复制黏贴吧。毕竟这是个小工程,如果大家有更好的想法或者在跑代码的时候有什么疑惑欢迎留言啊!!

介绍

我们的代码支持识别if-else, while, {}, (), sin, 二进制转十进制(B2D), 计算阶乘(Factorial), 基础四则运算等简单功能。可以通过compiler.c做出伪代码汇编语言版本,graph.c可以画出我们代码的syntax tree,interpreter.c是直接给出运行的结果的代码。

代码文件概览

  1. calc3.h
  2. LA.l
  3. SA.y
  4. compiler.c
  5. graph.c
  6. interpreter.c
  7. text.c

编译方式

因为我们用到了C++里面的map,所以这里我们都是用g++编译的,会有很多warnings,但没有什么大问题(不出意外的话。。)

#!/bin/sh 
flex LA.l
yacc -dtv SA.y
# 编译interpreter.c
g++ -c interpreter.c
g++ -c lex.yy.c
g++ -c y.tab.c
g++ -o a_i.out y.tab.o lex.yy.o interpreter.o
# 编译compiler.c
g++ -c compiler.c 
g++ -c lex.yy.c
g++ -c y.tab.c
g++ -o a_c.out y.tab.o lex.yy.o compiler.o
# 编译graph.c
g++ -c graph.c 
g++ -c lex.yy.c
g++ -c y.tab.c
g++ -o a_g.out y.tab.o lex.yy.o graph.o
# 运行测试程序
echo --------------------------Test File------------------------------------------
cat test.txt
echo --------------------------Output of Interpreter------------------------------
./a_i.out < test.txt
echo --------------------------Output of Compiler---------------------------------
./a_c.out < test.txt
echo --------------------------Output of Graph------------------------------------
./a_g.out < test.txt

代码部分

calc3.h

#include <map>
#include <utility>
#include <string.h>
typedef enum { typeCon, typeId, typeOpr, typeStr} nodeEnum; 
 
/* constants */ 
typedef struct { 
    float value;                  /* value of constant */ 
} conNodeType;  

typedef struct { 
    char* value;                  /* value of constant */ 
} strNodeType;

/* identifiers */ 
typedef struct { 
    char* idName;                      /* subscript to sym array */ 
} idNodeType;  

/* operators */ 
typedef struct { 
    int oper;                   /* operator */
    int nops;                   /* number of operands */ 
    struct nodeTypeTag *op[1];  /* operands, extended at runtime */ 
} oprNodeType; 

typedef struct nodeTypeTag { 
    nodeEnum type;              /* type of node */ 
     union { 
      conNodeType con;        /* constants */ 
      strNodeType str;        /* string */
      idNodeType id;          /* identifiers */ 
      oprNodeType opr;        /* operators */ 
    }; 
} nodeType;  

struct cmp_str /* 自定义函数,用来判断两个str是否是一样的,用来辅助map*/
{
   bool operator()(char const *a, char const *b) const
   {
      return strcmp(a, b) < 0;
   }
};

extern std:: map<char *, float, cmp_str> sym;


LA.l

%{
#include <stdlib.h>
#include "calc3.h"
#include "y.tab.h"
#include <string>
void yyerror(char *);
%}

%%
0                                               {yylval.iValue = atoi(yytext); return FLOAT;}

[0-9]+(\.[0-9]+)?([eE][0-9]+)?                  {yylval.iValue = atof(yytext); return FLOAT;}
[01]+B                                          {yylval.s = (char*)malloc(sizeof(yytext)); strcpy(yylval.s,yytext); return BIN;}
"sin"                                           {return SIN;}
"cos"                                           {return COS;}
"pi"                                            {return PI;}
"fac"                                           {return FAC;}
"B2D"                                           {return B2D;}

[-()<>=+*/;{}.^]                                { return *yytext;}

">="        return GE;
"<="        return LE;
"=="        return EQ;
"!="        return NE;
"while"     return WHILE;
"if"        return IF;
"else"      return ELSE;
"print"     return PRINT;

[_[:alpha:]][_[:alnum:]]*                       {yylval.s = (char*)malloc(sizeof(yytext)); strcpy(yylval.s,yytext);   return VARIABLE;}

[ \t\n]+ ;
.                                               yyerror("Unknown character");
%%

int yywrap(void) {
    return 1;
}


SA.y

%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include "calc3.h"
#define _USE_MATH_DEFINES
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(char* str);
nodeType *con(float value);
nodeType *str(char* value);
void freeNode(nodeType *p);
int ex(nodeType *p);
int yylex(void);
void yyerror(char *s);

std::map<char *, float, cmp_str> sym;
%}

%union {
    float iValue;
    char sIndex;
    nodeType *nPtr;
    char* s;
};

%token <iValue> FLOAT
%token <s> VARIABLE
%token <s> BIN
%token PI
%token WHILE IF PRINT SIN COS B2D FAC
%nonassoc IFX
%nonassoc ELSE

%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%left '^'

%type <nPtr> stmt expr stmt_list

%%
program:
  function  { exit(0); }
  ;

function:
    function stmt {ex($2); freeNode($2);}
    |
    ;

stmt: 
    ';'                                     { $$ = opr(';', 2, NULL, NULL); } 
  | expr ';'                                { $$ = $1; } 
  | PRINT expr ';'                          { $$ = opr(PRINT, 1, $2); } 
  | VARIABLE '=' expr ';'                   { $$ = opr('=', 2, id($1), $3); } 
  | WHILE '(' expr ')' stmt                 { $$ = opr(WHILE, 2, $3, $5); } 
  | IF '(' expr ')' stmt %prec IFX          { $$ = opr(IF, 2, $3, $5); } 
  | IF '(' expr ')' stmt ELSE stmt          { $$ = opr(IF, 3, $3, $5, $7); } 
  | '{' stmt_list '}'                       { $$ = $2; } 
    ;  

stmt_list:     
    stmt                                    { $$ = $1; } 
  | stmt_list stmt                          { $$ = opr(';', 2, $1, $2); } 
  ;  

expr: 
    FLOAT                                   { $$ = con($1); } 
  | BIN                                     { $$ = str($1); }
  | VARIABLE                                { $$ = id($1);} 
  | '-' expr %prec UMINUS                   { $$ = opr(UMINUS, 1, $2); } 
  | expr '+' expr                           { $$ = opr('+', 2, $1, $3); }   
  | expr '-' expr                           { $$ = opr('-', 2, $1, $3); }   
  | expr '*' expr                           { $$ = opr('*', 2, $1, $3); }   
  | expr '/' expr                           { $$ = opr('/', 2, $1, $3); } 
  | expr '<' expr                           { $$ = opr('<', 2, $1, $3); } 
  | expr '>' expr                           { $$ = opr('>', 2, $1, $3); } 
  | expr '^' expr                           { $$ = opr('^', 2, $1, $3); } 
  | expr GE expr                            { $$ = opr(GE, 2, $1, $3); } 
  | expr LE expr                            { $$ = opr(LE, 2, $1, $3); } 
  | expr NE expr                            { $$ = opr(NE, 2, $1, $3); } 
  | expr EQ expr                            { $$ = opr(EQ, 2, $1, $3); } 
  | '(' expr ')'                            { $$ = $2; } 
  | SIN '(' expr ')'                        { $$ = opr(SIN, 1, $3 ); }
  | COS '(' expr ')'                        { $$ = opr(COS, 1, $3 ); }
  | PI                                      { $$ = con(M_PI);}
  | FAC '(' expr ')'                        { $$ = opr(FAC,1,$3); }
  | B2D '(' expr ')'                        { $$ = opr(B2D,1,$3); }
  ; 
%%

#define SIZEOF_NODETYPE ((char *)&p->con - (char *)p) 
 
nodeType *con(float value) {     nodeType *p; 
 
    /* allocate node */ 
    if ((p = (nodeType*)malloc(sizeof(nodeType))) == NULL)         yyerror("out of memory"); 
 
    /* copy information */     p->type = typeCon;     p->con.value = value; 
     return p; 
}  
nodeType *str(char* value) {     nodeType *p; 
 
    /* allocate node */ 
    if ((p = (nodeType*)malloc(sizeof(nodeType))) == NULL)         yyerror("out of memory"); 
 
    /* copy information */     p->type = typeStr;     p->str.value = value; 
     return p; 
}
nodeType *id(char* str) {     nodeType *p; 
 
    /* allocate node */ 
    if ((p = (nodeType*)malloc(sizeof(nodeType))) == NULL)         yyerror("out of memory"); 
 
    /* copy information */     p->type = typeId;     p->id.idName = str; 
     return p; 
}  

nodeType *opr(int oper, int nops, ...) {     
    va_list ap;     
    nodeType *p;     
    int i; 
    /* allocate node, extending op array */
    if ((p = (nodeType*)malloc(sizeof(nodeType) + (nops-1) * sizeof(nodeType *))) == NULL)
        yyerror("out of memory");
    /* copy information */
    p->type = typeOpr;
    p->opr.oper = oper;
    p->opr.nops = nops;
    va_start(ap, nops);
    for (i = 0; i < nops; i++)
        p->opr.op[i] = va_arg(ap, nodeType*);
    va_end(ap);
    return p;
}

void freeNode(nodeType *p) {
    int i;
    if (!p) return;
    if (p->type == typeOpr) {
        for (i = 0; i < p->opr.nops; i++)
            freeNode(p->opr.op[i]);
    }       
    
    free (p);
}

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

int main(void) {
    yyparse();
    return 0;
}

compiler.c

#include <stdio.h> 
#include "calc3.h" 
#include "y.tab.h" 
 
static int lbl; 
 
int ex(nodeType *p) {     
    int lbl1, lbl2; 
 
    if (!p) 
        return 0;     
    switch(p->type) {     
        case typeCon:                
            printf("\tpush\t%.4f\n", p->con.value);          
            break;     
        case typeId:         
            printf("\tpush\t%s\n", p->id.idName);          
            break;
        case typeStr:         
            printf("\tpush\t%s\n", p->str.value);          
            break;     
        case typeOpr: 
            switch(p->opr.oper) {         
                case WHILE:             
                    printf("L%03d:\n", lbl1 = lbl++);             
                    ex(p->opr.op[0]); 
                    printf("\tjz\tL%03d\n", lbl2 = lbl++);             
                    ex(p->opr.op[1]);             
                    printf("\tjmp\tL%03d\n", lbl1);             
                    printf("L%03d:\n", lbl2);             
                    break;         
                case IF:             
                    ex(p->opr.op[0]);             
                    if (p->opr.nops > 2) {                 
                        /* if else */ 
                        printf("\tjz\tL%03d\n", lbl1 = lbl++);                 
                        ex(p->opr.op[1]); 
                        printf("\tjmp\tL%03d\n", lbl2 = lbl++);                 
                        printf("L%03d:\n", lbl1);                 
                        ex(p->opr.op[2]);                 
                        printf("L%03d:\n", lbl2); 
                    } else {                 
                        /* if */ 
                        printf("\tjz\tL%03d\n", lbl1 = lbl++);                 
                        ex(p->opr.op[1]);                 
                        printf("L%03d:\n", lbl1); 
                    }             
                    break; 
                case PRINT:                  
                    ex(p->opr.op[0]);             
                    printf("\tprint\n");             
                    break; 
            
                case '=':                    
                    ex(p->opr.op[1]); 
                    printf("\tpop\t%s\n", p->opr.op[0]->id.idName);             
                    break;         
                    case UMINUS:                 
                    ex(p->opr.op[0]);             
                    printf("\tneg\n");             
                    break;
                case FAC:
		            ex(p->opr.op[0]); 
            	    printf("\tfac\n");
                    break;
                case SIN:
		            ex(p->opr.op[0]); 
            	    printf("\tsin\n");
                    break;
                case COS:
		            ex(p->opr.op[0]); 
            	    printf("\tcos\n");
                    break;
                case B2D:
		            ex(p->opr.op[0]); 
            	    printf("\tb2d\n");
                    break;
                default:             
                    ex(p->opr.op[0]);             
                    ex(p->opr.op[1]);             
                    switch(p->opr.oper) {             
                        case '+':   printf("\tadd\n"); 
                        break;             
                        case '-':   printf("\tsub\n"); 
                        break;              
                        case '*':   printf("\tmul\n"); 
                        break;             
                        case '/':   printf("\tdiv\n"); 
                        break;             
                        case '<':   printf("\tcompLT\n"); 
                        break;             
                        case '>':   printf("\tcompGT\n"); 
                        break;   
                        case '^':   printf("\tpow\n"); 
                        break;          
                        case GE:    printf("\tcompGE\n"); 
                        break;             
                        case LE:    printf("\tcompLE\n"); 
                        break;             
                        case NE:    printf("\tcompNE\n"); 
                        break;             
                        case EQ:    printf("\tcompEQ\n"); 
                        break;             
                    } 
            }     
    }     
    return 0; 
} 


graph.c

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "calc3.h"
#include "y.tab.h"

int del = 1; /* distance of graph columns */ int eps = 3; /* distance of graph lines */

/* interface for drawing (can be replaced by "real" graphic using GD or other) */
void graphInit (void); void graphFinish();
void graphBox (char *s, int *w, int *h);
void graphDrawBox (char *s, int c, int l);
void graphDrawArrow (int c1, int l1, int c2, int l2);

/* recursive drawing of the syntax tree */
void exNode (nodeType *p, int c, int l, int *ce, int *cm);

/***********************************************************/

/* main entry point of the manipulation of the syntax tree */ 
int ex (nodeType *p) {
    int rte, rtm;
    graphInit ();
    exNode (p, 0, 0, &rte, &rtm);     
    graphFinish();
    return 0;
}

/*c----cm---ce---->                       drawing of leaf-nodes  l leaf-info
 */

/*c---------------cm--------------ce----> drawing of non-leaf-nodes  l            node-info
*	|
*	-------------     ...----  *    |       |               |  *    v       v               v
*	child1  child2  ...     child-n
*	che     che             che
*cs      cs      cs              cs
*
*/
void exNode(nodeType*p,
            int c, int l,/* start column and line of node */
            int *ce, int *cm     /* resulting end column and mid of node */
)
{
    int w, h;           /* node width and height */
    char *s;            /* node text */
    int cbar;       /* "real" start column of node (centred above subnodes)*/
    int k;              /* child number */
    int che, chm;       /* end column and mid of children */
    int cs;             /* start column of children */
    char word[20];      /* extended node text */

    if (!p) return;
    strcpy (word, "???"); /* should never appear */
    s = word;
    switch(p->type) {
        case typeCon:
            sprintf (word, "c(%.4f)", p->con.value);
            break;
        case typeStr:
            sprintf (word, "str(%s)", p->str.value);
            break;
        case typeId:
            sprintf (word, "id(%s)", p->id.idName);
            break;
        case typeOpr:
            switch(p->opr.oper){
                case WHILE:
                    s = "while";
                    break;
                case IF:
                    s = "if";
                    break;
                case ELSE:
                    s = "else";
                    break;
                case PRINT:
                    s = "print"; 
                    break;
                case ';':
                    s = "[;]";
                    break;
                case '=':
                    s = "[=]";
                    break;
                case UMINUS:
                    s = "[_]";
                    break;
                case '+':
                    s = "[+]";
                    break;
                case '-':
                    s = "[-]";
                    break;
                case '*':
                    s = "[*]";
                    break;
                case '/':
                    s = "[/]";
                    break;
                case '<':
                    s = "[<]";
                    break;
                case '>':
                    s = "[>]";
                    break;
                case '^':
                    s = "[^]";
                    break;
                case GE:
                    s = "[>=]";
                    break;
                case LE:
                    s = "[<=]";
                    break;
                case NE:
                    s = "[!=]";
                    break;
                case EQ:
                    s = "[==]";
                    break;
                case SIN:
                    s = "sin";
                    break;
                case COS:
                    s = "cos";
                    break;
                case FAC:
                    s = "fac";
                    break; 
                case B2D:
                    s = "b2d";
                    break;
            }
            break;
    }

    /* construct node text box */
    graphBox (s, &w, &h);
    cbar = c;
    *ce = c + w;
    *cm = c + w / 2;

    /* node is leaf */
    if (p->type == typeCon ||p->type == typeStr || p->type == typeId || p->opr.nops == 0) {
        graphDrawBox (s, cbar, l);
        return;
    }

    /* nodezhas children*/
    cs = c;
    for (k = 0; k < p->opr.nops; k++) {
        exNode (p->opr.op[k], cs, l+h+eps, &che, &chm);
        cs = che;
    }

    /* total node width */
    if (w < che - c) {
        cbar += (che - c - w) / 2;
        *ce = che;
        *cm = (c + che) / 2;
    }

    /* draw node */
    graphDrawBox (s, cbar, l);

    /* draw arrows (not optimal: children are drawn a second time) */
    cs = c;
    for (k = 0; k < p->opr.nops; k++) {
        exNode (p->opr.op[k], cs, l+h+eps, &che, &chm);
        graphDrawArrow (*cm, l+h, chm, l+h+eps-1);
        cs = che;
    }
}

/* interface for drawing */

#define lmax 200
#define cmax 200

char graph[lmax][cmax]; /* array for ASCII-Graphic */
int graphNumber = 0;

void graphTest (int l, int c)
{   int ok;
    ok = 1;
    if (l < 0) ok = 0;     
    if (l >= lmax) ok = 0;     
    if (c < 0) ok = 0;     
    if (c >= cmax) ok = 0;     
    if (ok) return;
    printf ("\n+++error: l=%d, c=%d not in drawing rectangle 0, 0 ... %d,%d",l, c, lmax, cmax);
    exit (1);
}

void graphInit (void) {
    int i, j;
    for (i = 0; i < lmax; i++)
        for (j = 0; j < cmax; j++)
            graph[i][j] = ' ';
}

void graphFinish() {
    int i, j;
    for (i = 0; i < lmax; i++) {
        for (j = cmax-1; j > 0 && graph[i][j] == ' '; j--);
        graph[i][cmax-1] = 0;
        if (j < cmax-1)
            graph[i][j+1] = 0;
        if (graph[i][j] == ' ')
            graph[i][j] = 0;
    }

    for (i = lmax-1; i > 0 && graph[i][0] == 0; i--);
    printf ("\n\nGraph %d:\n", graphNumber++);

    for (j = 0; j <= i; j++)
        printf ("\n%s", graph[j]);
    printf("\n");
}
void graphBox (char *s, int *w, int *h) {
    *w = strlen (s) + del;
    *h = 1;
}
void graphDrawBox (char *s, int c, int l) {
    int i;
    graphTest(l, c+strlen(s)-1+del);
    for (i = 0; i < strlen (s); i++) {
        graph[l][c+i+del] = s[i];
    }
}

void graphDrawArrow (int c1, int l1, int c2, int l2) {
    int m;
    graphTest (l1, c1);
    graphTest (l2, c2);
    m = (l1 + l2) / 2;
    while (l1 != m) {
        graph[l1][c1] = '|'; if (l1 < l2) l1++; else l1--;
    }
    while (c1 != c2) {
        graph[l1][c1] = '-'; if (c1 < c2) c1++; else c1--;
    }
    while (l1 != l2) {
        graph[l1][c1] = '|'; if (l1 < l2) l1++; else l1--;
    }
    graph[l1][c1] = '|';
}

interpreter.c

#include <stdio.h> 
#include "calc3.h" 
#include "y.tab.h" 
#include "math.h"
float factorial(float fac);
float BtoD(char* bin);
float res;
int count = 0;
std::map<char *, float, cmp_str>::iterator it;
float ex(nodeType *p) {
    if (!p) return 0;
    switch(p->type) {
        case typeCon:
            return p->con.value;
        case typeStr:
            return 0; //meaningless
        case typeId:
            return sym[p->id.idName];
        case typeOpr:
            switch(p->opr.oper) {
                case WHILE:
                    while(ex(p->opr.op[0]))
                        ex(p->opr.op[1]);
                    return 0;
                case IF:
                    if (ex(p->opr.op[0]))
                        ex(p->opr.op[1]);
                    else if (p->opr.nops > 2)
                        ex(p->opr.op[2]);
                    return 0;
                case PRINT:
                    printf("%.4f\n", ex(p->opr.op[0]));
                    return 0;
                case ';':
                    ex(p->opr.op[0]); return ex(p->opr.op[1]);
                case '=':
                    it = sym.find(p->opr.op[0]->id.idName);
                    if(it!=sym.end()){
                        sym[p->opr.op[0]->id.idName] = ex(p->opr.op[1]);
                    }
                    else
                    {
                        sym.insert(std::pair<char*, float>(p->opr.op[0]->id.idName, ex(p->opr.op[1])));
                    }
                    
                    return ex(p->opr.op[1]);
                case UMINUS:      return -ex(p->opr.op[0]);
                case '+':         return ex(p->opr.op[0]) + ex(p->opr.op[1]);
                case '-':         return ex(p->opr.op[0]) - ex(p->opr.op[1]);
                case '*':         return ex(p->opr.op[0]) * ex(p->opr.op[1]);
                case '/':         return ex(p->opr.op[0]) / ex(p->opr.op[1]);
                case '<':         return ex(p->opr.op[0]) < ex(p->opr.op[1]);
                case '>':         return ex(p->opr.op[0]) > ex(p->opr.op[1]);
                case '^':         return pow(ex(p->opr.op[0]), ex(p->opr.op[1]));
                case GE:          return ex(p->opr.op[0]) >= ex(p->opr.op[1]);
                case LE:          return ex(p->opr.op[0]) <= ex(p->opr.op[1]);
                case NE:          return ex(p->opr.op[0]) != ex(p->opr.op[1]);
                case EQ:          return ex(p->opr.op[0]) == ex(p->opr.op[1]);
                case SIN:         return sin(ex(p->opr.op[0]));
                case COS:         return cos(ex(p->opr.op[0]));
                case B2D:         return BtoD(p->opr.op[0]->str.value);
                case FAC:         
                    res = factorial(ex(p->opr.op[0]));
                    if(res==-1&&count==0){
                        printf("Fraction number is not allowed.\n");
                        count++;
                        return res;
                    } 
                    else if(res==-2&&count==0){
                        printf("Negative number is not allowed.\n");
                        count++;
                        return res;
                    } 
                    if(count==1) count = 0;
                    return res;
            }
    }
    return 0;
}

float BtoD(char* bin)
{
 int i = 0;
    int dec = 0;
    while(bin[i]!='B'){
        if (bin[i] == '1') dec = dec * 2 + 1; 
        else if (bin[i] == '0') dec *= 2; 
        i++;
    }
    return dec;
}

float factorial(float fac){
    if(fac<0){
        return -2;
    }
    int fac2 = (int)fac;
    if (fac2!=fac){
        return -1;
    }
    float sum = 1;
    while(fac!=0){
	sum*=fac;
	fac--;
    }
    return sum;
}

test.txt

x = 0;
while (x<3) {
    print x;
    x = x + 1;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用lexyacc制作一个算术计算器的步骤: 1. 定义词法分析器 使用lex工具定义词法分析器,即将输入的字符串分解为一个个符号(token),并将其传递给语法分析器(yacc)。在这个例子中,我们需要定义数字、加号、减号、乘号、除号以及左右括号等符号。 下面是一个简单的词法分析器的例子: ``` %{ #include "y.tab.h" %} %% [0-9]+ { yylval = atoi(yytext); return NUMBER; } "+" { return PLUS; } "-" { return MINUS; } "*" { return TIMES; } "/" { return DIVIDE; } "(" { return LPAREN; } ")" { return RPAREN; } [ \t] { /* ignore whitespace */ } \n { /* end of line */ } . { printf("invalid input\n"); } %% int yywrap() { return 1; } ``` 2. 定义语法分析器 使用yacc工具定义语法分析器,即定义输入符号串的语法规则,并生成可执行的语法分析器。在这个例子中,我们需要定义算术表达式的语法规则,例如加法、减法、乘法、除法以及括号等。 下面是一个简单的语法分析器的例子: ``` %{ #include <stdio.h> #include <stdlib.h> %} %token NUMBER PLUS MINUS TIMES DIVIDE LPAREN RPAREN %% input: /* empty */ | input line line: exp '\n' { printf("= %d\n", $1); } exp: exp PLUS exp { $$ = $1 + $3; } | exp MINUS exp { $$ = $1 - $3; } | exp TIMES exp { $$ = $1 * $3; } | exp DIVIDE exp { $$ = $1 / $3; } | LPAREN exp RPAREN { $$ = $2; } | NUMBER { $$ = $1; } ; %% int main() { yyparse(); return 0; } int yyerror(char *s) { fprintf(stderr, "error: %s\n", s); return 0; } ``` 3. 编译和运行 使用以下命令编译并运行程序: ``` $ lex calc.l $ yacc -d calc.y $ gcc lex.yy.c y.tab.c -o calc $ ./calc ``` 之后就可以输入算术表达式并得到计算结果了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值