2010-01-10 78 views
0

我使用野牛搭建一个简单的语言的编译器。下面是语法的一部分:如何解析if语句野牛

stmt: IF '(' exp ')' stmt{ 
     if(exp) $$=$5; 
     } 
     |PRINT ';' { 
     cout<<"hi"; 
     } 
; 

exp: true|false 
; 

我在if语句解析此遇到了一个问题:假如我有这样的代码:

if(false) print; 

“喜”无论如何都会被打印,因为stmt-> PRINT是在stmt-> IF(exp)stmt之前解析。 我能做什么? (我是新来的野牛和编译,所以请随时纠正我的问题中的错误)。

回答

1

这是自然的。你正在解析print语句,所以'cout'被执行。你要做的是创建一些字节码,在那里存储打印指令。然后可以将此打印指令与if-表达式组合以形成if语句指令。我不记得Bison中的确切语句(你需要查看文档),但是你通常想为你的值栈定义一个类型,通常是结构,就像这样(但是有一个野牛命令,它会使它成为值栈的类型)。

union { 
int type; 
struct { 
    int type; // must always be first, this is a union 
    union stmt *stmt; // conditional stmt to execute 
    union expr *expr; // expression to evaluate 
} if_stmt; 
struct { 
    int type; 
} print_stmt; 
} stmt; 

,这将使你把一个规则,你的语法,像这样

stmt: IF '(' expr ')' stmt { $$.type = IF_STMT; $$.if_stmt.expr = copy ($3); $$.if_stmt.stmt = copy ($5); } 

等(有可能是一个差一错误在那里,不记得如果$ s从0或1开始)。你需要自己实现copy函数来管理内存分配,野牛只会为值提供堆栈。最后,你将有一个树(通常被称为语法树,我相信),您可以通过运行,对于类型IF_STMT节点,evalute if_stmt.expr,如果返回true,评估if_stmt.stmt,等等。

然后,当你完成语言分析后,你可以'执行'你的字节码,当你敲一个if语句,评估表达式,如果是true(不是),按照概述执行语句以上,然后当你打的打印指令(你会不会因为表达是假的哪个),打印您的“喜”,你有你正在寻找的结果(即,没有获取打印)。

这几乎是你需要如何去做。用bison解析时不能(很容易)执行条件执行。

0

如果你想要做它的工作原理只是如果,你可以做一个堆栈,在EXP EVAL,推进堆栈EXP的真值,在IF块只是检查是否可以执行的函数调用,分配等, on else否定堆栈中的最后一个值,并在IF减少时,只弹出Stack中的值。

例:

Stack (bool) x; 


    CanExec() 
    { 
     if x== NULL //no IF yet 
      return true; 
     for i in x 
      if i == false 
       return false; //if we have at last 1 if banch with FALSE, we cannot execute it 
     return true; 
    } 

    if_stmt: IF if_exp block    {Pop()} 
       |IF if_exp block else block {Pop()} 

    if_exp:  '(' exp ')'     {Push((bool)exp)} 

    else:  ELSE       {tmp = Pop(); Push(!tmp)} 

现在,所有的u需要做的是检查在所有侧efects操作如果CanExec()