2013-12-15 28 views
0

说我有一个代码具有以下形式。一些弹性/野牛问题

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

注意这只是一个例子,虽然是一个丑陋的例子,不过,这只是我想去做的exageration。 number1,number2,number3是数字,显示将是一种操作符,后跟一个包含变量赋值的{}之间的块,并以特殊方式打印整个事物。如上所述,只是一个例子。

我的问题是......说这个语法,display <<str>>()()() {}表格只与“显示”关键字一起使用,并且从未使用过。假设< <和>>通常是运营商。我想知道......怎么可能告诉野牛/ flex在这种情况下< <和>>不是用作操作符,而只是属于“显示”语法的分隔符?并且,如何正确提取<和<和>>之间的数据,然后使用不同的,特定的语法将整个块解析为{}之间的块。

例如,如果我有:

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

你可以写为像野牛规则:

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

在词法分析器识别display为关键词进行显示和<<>>为令牌LSHIFT和RSHIFT。在其他情况下(例如表达式),您将使用LSHIFTRSHIFT作为移位运算符。

这允许括号中的任何表达式(您可以在您的expr规则中计算整数),并且如果您在string规则中处理它们,则可能允许字符串“表达式”。

如果您真的想在<</>>(而不是字符串)之间使用原始文本,另一种方法是在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)输入并会把你的处理函数的字符串%" ,>(包括前/后间隔,引号和全部。

当然,您应该添加检查缓冲区溢出与适当的错误消息。

+0

感谢您的理解敏捷而快速的回答克里斯。我仍然希望从您的经验中获益。在由显示器处理的块中,假设我想在其中有一个独特的语法。假设我有第二个运算符叫做'struct',它也可以接受struct {block}等块,并且struct语法中的块也有一个独特的语法。我再次展示了这个例子,但我想清楚地理解这个概念。我是否需要制作另一个yyparse()(前缀),还是可以在单个解析器中执行?谢谢! – Yannick