假设我的代码具有以下形式。
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
在这个函数调用之后,我需要解析块。
有人可以解释我如何正确处理这个问题?
由于
答案 0 :(得分:1)
您可以将其写为野牛规则,如:
statement: DISPLAY LSHIFT string RSHIFT '(' expr ')' '(' expr ')' '(' expr ')'
{ handle_display_operator($3, $6, $9, $12); }
block
;
其中词法分析器将display
识别为关键字DISPLAY,将<<
和>>
识别为代币LSHIFT和RSHIFT。在其他情境中(例如表达式),您将使用LSHIFT
和RSHIFT
作为移位运算符。
这允许括号中的任何表达式(您可以在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)
这样的输入,并将把你的句柄函数传递给字符串%" ,>
(包括前导/尾随空格,引号和所有。
当然,您应该添加对缓冲区溢出的检查以及相应的错误消息。