一些flex / bison问题

时间:2013-12-15 20:25:02

标签: bison lex

假设我的代码具有以下形式。

display <<"hello">> (number1) (number2) (number3) {
     a = 1;
     b = 2;
     ...
}

请注意,这只是一个例子,虽然是一个丑陋的例子,但它仍然只是对我想要做的事情的一种解释。 number1,number2,number3是数字,display将是一种运算符,后跟包含变量赋值的{}之间的块,并以特殊方式打印整个事物。如上所述,只是一个例子。

我的问题是......说这种语法,display <<str>> ()()() {}表单只与“display”关键字一起使用,之后从未使用过。让我们说&lt;&lt;和&gt;&gt;通常是运营商。我想知道......在这种情况下怎么可能告诉bison / flex&lt;&lt;和&gt;&gt;不是用作运算符而只是属于“显示”语法的分隔符? AND,你怎么能正确地提取&lt;&lt;&lt;&lt;&lt;和&gt;&gt;,()之间的数字,然后使用不同的,特定的语法解析整个块到{}之间的块?

例如,如果我有:

display <<"hello">> (1) (5) (8) {
    a = 1;
    b = 8 * 273 + 40;
}

我想打个电话:

handle_display_operator(szStr, num1, num2, num3)

// here szStr contains "hello", num1 = 1, num2 = 5, num3 = 8

在这个函数调用之后,我需要解析块。

有人可以解释我如何正确处理这个问题?

由于

1 个答案:

答案 0 :(得分:1)

您可以将其写为野牛规则,如:

statement: DISPLAY LSHIFT string RSHIFT '(' expr ')' '(' expr ')' '(' expr ')'
                { handle_display_operator($3, $6, $9, $12); }
           block
         ;

其中词法分析器将display识别为关键字DISPLAY,将<<>>识别为代币LSHIFT和RSHIFT。在其他情境中(例如表达式),您将使用LSHIFTRSHIFT作为移位运算符。

这允许括号中的任何表达式(您可以在expr规则中评估为整数),如果在string规则中处理它们,则可以允许字符串'表达式'。< / p>

另一种方法,如果您真的希望<< / >>(而不是字符串)之间的原始文本,则在display关键字之后使用flex独占状态。然后你会有像以下那样的弹性规则:

%x display, raw_text
%{
    /* use a dynamic buffer if you don't have an upper limit on the length */
    static char raw_text_buffer[MAX_LENGTH], *raw_text_end;
%}

%%

"display"      { BEGIN(display); return DISPLAY; }
<display>"<<"  { BEGIN(raw_text); raw_text_end = raw_text_buffer; }
<raw_text>.    { *raw_text_end++ = *yytext; /* DANGER -- may overflow */ }
<raw_text>\n   { error??  or just put it in the buffer... }
<raw_text>">>" { *raw_text_end = 0;
                 yylval.string = strdup(raw_text_buffer);
                 BEGIN(INITIAL);
                 return RAW_TEXT; }

现在您的规则将如下所示:

statement: DISPLAY RAW_TEXT '(' expr ')' '(' expr ')' '(' expr ')'
                { handle_display_operator($2, $4, $7, $10); }
           block

这允许像display << %" ,> >> (1)(2)(3)这样的输入,并将把你的句柄函数传递给字符串%" ,>(包括前导/尾随空格,引号和所有。

当然,您应该添加对缓冲区溢出的检查以及相应的错误消息。