如何强迫野牛立即编译

时间:2014-06-18 16:26:16

标签: bison

我想编写一个混合了更多自由格式的“经典”BASIC语法,例如:

a=5:b=6:c=a+b           // writing several instructrions into a single line
                // using colon as separator
                // but eliminating mandatory terminals (like ';' in c)

while (x < 3 ) {        // condition has mandatory parentheses around, but
x=x+1:y=y+2         // body of 'while' may also have multi-statements line(s)
z=y+y               // and may have several lines as well
}

要实现它,我设置了以下规则。我的flex会尽职尽责,正确地消除不必要的换行等等:

^[ \t\r\n]*\n           /*ignore empty line */
\/\/.*\n ;          /* skip comment */
[ \t\r\n]+ ;            /* ignore whitespace */
\{[ \t\r\n]*\} ;        return EMPTY;
\{[ \t\r\n]* ;          return '{';
\}[ \t\r\n]* ;          return '}';

不幸的是,stmt后跟冒号并不会强制编译器执行立即编译。 但是,在该行的后半部分通常会预期正在编译的代码。 这是我的野牛文件的结构。

%type <nPtr> stmt stmt_list expr

%%
line:
    line stmt_list ':' {        // <-- this is my problem
        ex($2); freeNode($2);
        }
    | line stmt_list '\n' {
        ex($2); freeNode($2);
        }
    | /* NULL */
    ;

stmt:   VARIABLE '=' expr       { $$ = opr('=', 2, $3, id($1)); }
    | PORT '=' expr         { $$ = opr('=', 2, $3, id($1)); }
    | .... etc.
    | WHILE '(' expr ')' EMPTY  { $$ = opr(WHILE, 1, $3); }
    | WHILE '(' expr ')' stmt_list  { $$ = opr(WHILE, 2, $3, $5); }
    ;

stmt_list:
    stmt                { $$ = $1; }
    | '{' stmt_list '}'     { $$ = $2; }
    | '{' error '}'         { errorflag=1; }
    | error  '\n'           { errorflag=1; }
    ;

expr:
    INTEGER             { $$ = con($1); }
    | VARIABLE          { $$ = id($1); }
    | .... etc.
    | '(' expr ')'          { $$ = $2; }
    ;

如何修改它以达到预期的行为?

2 个答案:

答案 0 :(得分:2)

关于野牛行动要记住的重要一点是,当右手边被完全解析时,它们会被执行。

考虑两个简单的递归制作:

a: N a | %empty ;

a: a N | %empty ;

让我们将它们应用于输入:

N1 N2 N3

使用右递归的情况(第一个),产品将如下(下标只是为了清晰):

a0 → N1 a1 a1 → N2 a2 a2 → N3 a3 a3 → ε

,解析树是:

a0
+-----+-----+
| |
| a1
| +---+---+
| | |
| | a2
| | +-+-+
| | | |
| | | a3
| | | |
N1 N2 N3 ε

而左递归的(第二个)产生:

a0 → a1 N3 a1 → a2 N2 a2 → a3 N1 a3 → ε

,解析树是:

a0
+-----+-----+
| |
a1 |
+---+---+ |
| | |
a2 | |
+-+-+ | |
| | | |
a3 | | |
| | | |
ε N1 N2 N3

要注意的重要一点是,在右递归的情况下,所有产品都包含整个输入字符串,因此解析器操作从从右到左进行。相反,在左递归的情况下,产生连续产生字符串的前缀,解析器操作发生在从左到右

总之,如果您希望从左到右执行操作,请使用左递归。

答案 1 :(得分:2)

我看到你的例子存在许多严重问题

  • 您的语法使用'\n'(换行符)令牌,但您的词法分析器会忽略换行符并且永远不会返回它们,因此涉及换行符的规则永远不会减少
  • 您的示例说多个语句行(带冒号)可以出现在WHILE正文中,但您的语法不允许这样的

因为这些,解析器甚至无法正确解析输入的第二行,更不用说进入循环了。