小白说编译原理-9-最简单minus-c语言编译器

简介

继上节8说到利用手动构建的语法树解析下面的c语言代码:

    a = 1
    sum = 0
    input(x)
    while(a <= x){
       sum = sum + a
       a = a+1;
    }
    print(sum)

而一个编译器不应该依赖用户去手动构建对应语言的语法树,我们需要的是一种支持自动构建语法树的策略。本节将要说明的就是如何利用前面1-6节学到的lex,yacc以及符号表,7-8节学到的语法树来支持给定c语言代码自动构建过程。

动机

在第5节变量支持的计算器中,对于expr的语法解析有如下的yacc代码:

 lines   :   lines expr EOL  { printf("%g\n", $2); }
            |   lines EOL
            |   lines COMMENT
            |   
            ;

    expr    :   expr PLUS expr  { $$ = $1 + $3; }
			|	expr MINUS expr	{ $$ = $1 - $3; }
			|	expr TIMES expr	{ $$ = $1 * $3; }
			|	expr OVER expr	{ $$ = $1 / $3; }
			|	LP expr RP	{ $$ = $2; }
			|	'-' expr %prec UMINUS	{ $$ = -$2; }
			|	NUMBER {$$=$1;} //$$=$1 can be ignored
            |   ID {$$ = sym_table.getValue($1);}//get value from sym_table
			|   ID ASSIGN expr {sym_table.setValue($1, $3); $$=$3; }//modify the value

已经知道的是上面每一行都是对应的语法匹配规则(例如expr PLUS expr)以及当规则匹配后要执行的动作(位于{}中,例如$$ = $1 + $3;)。如果将上面要执行的动作修改为创建对应的语法表达式节点,不就可以实现自动构建语法树了吗? 针对上面的expr PLUS expr,其对应的动作可以修改为

$$ = expr.NewRoot(EXPR_NODE, OP_EXPR, NodeAttr(PLUS), Integer, $1, $3);

同理,其他语法规则的执行动作也可以进行相应的修改,这样当一个表达式语法分析完毕后,对应的表达式语法树也就构建完成了。

总体概览

  1. lex和yacc进行相应的词法,语法分析,并构建对应的语法树
  2. tree.h和tree.cpp用来支撑语法树的构建过程,提供相应的创建函数,被yacc使用
  3. symtable.h和symtable.cpp用来支撑符号表的构建过程,提供符号表的创建,访问,修改等操作,用于支持变量以及可能的函数扩展。
  4. 只支持最基本的c语言,也就是第8节已经进行测试过的。总述如下:变量,变量赋值,算术逻辑等运算,if语句,while语句,输入输出语句,表达式语句,复合语句(不支持变量声明,变量名出现的第一次开始将其加入到符号表,默认值为0,使用赋值运算符可对变量值进行修改)。

可支持如下的代码:
其为迭代法解一元二次方程组,方程的三个参数为a,b,c。

void interation() 
{      
    //求解X1,在曲线对称轴处选择初始点     
    double index=(-1.0*b)/(2*a),temp;     
    if(b!=0)//b不等于0时进行迭代     
    {          
        temp=index;          
        index=-1.0*(a*temp*temp+c)/b;          
        while((absolute(index-temp))>accuracy)         
        {              
            temp=index;              
            index=-1.0*(a*temp*temp+c)/b;         
        }          
        x1=index;          
        x2=(-1.0*b)/a-x1; 
    }      
    else//b=0时ax^2+c=0直接求解     
    {          
        x1=sqrt(-1.0*c/a);         
        x2=-x1;     
    }  
}

未完待续

你可能感兴趣的:(编译器,编译原理)