标签:
继上节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);
同理,其他语法规则的执行动作也可以进行相应的修改,这样当一个表达式语法分析完毕后,对应的表达式语法树也就构建完成了。
可支持如下的代码: 
其为迭代法解一元二次方程组,方程的三个参数为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;     
    }  
}
标签:
原文地址:http://blog.csdn.net/lpstudy/article/details/51340644