Bison:如果令牌不符合规则,如何忽略令牌

Cas*_*ton 7 token bison flex-lexer

我正在编写一个处理评论的程序以及其他一些东西.如果评论在特定的地方,那么我的程序会做一些事情.

Flex在发现评论时传递令牌,然后Bison会查看该令牌是否符合特定规则.如果是,则需要与该规则相关联的操作.

事情就是这样:我收到的输入实际上可能在错误的地方有评论.在这种情况下,我只想忽略注释而不是标记错误.

我的问题:
如果令牌符合规则,我如何使用令牌,但如果不符合则忽略它?我可以将令牌设为"可选"吗?

(注意:我现在能想到的唯一方法就是在每个可能的规则中将注释标记分散到每个可能的位置.必须有一个比这更好的解决方案.也许有一些涉及根的规则?)

JXG*_*JXG 5

一种解决方案可能是使用 bison 的错误恢复(请参阅Bison 手册)。

总而言之,bison 定义了error表示错误的终端标记(例如,在错误位置返回的评论标记)。这样,您可以(例如)在发现任性注释后关闭括号或大括号。但是,这种方法可能会丢弃一定量的解析,因为我认为野牛不能“撤消”减少。(“标记”错误,就像向 stderr 打印消息一样,与此无关:您可以打印错误的情况下出现错误——这取决于您如何定义yyerror.)

您可能希望将每个终端包装在一个特殊的非终端中:

term_wrap: comment TERM
Run Code Online (Sandbox Code Playgroud)

这有效地完成了您害怕做的事情(在每个规则中添加注释),但它在较少的地方完成。

为了强迫自己吃自己的狗粮,我为自己编造了一种愚蠢的语言。唯一的语法是print <number> please,但如果##在数字和 之间(至少)有一个注释 ( ) please,它会以十六进制打印数字,而不是。

像这样:

print 1 please
1
## print 2 please
2
print ## 3 please
3
print 4 ## please
0x4
print 5 ## ## please
0x5
print 6 please ##
6
Run Code Online (Sandbox Code Playgroud)

我的词法分析器:

%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
%}

%%

print           return PRINT;
[[:digit:]]+    yylval = atoi(yytext); return NUMBER;
please          return PLEASE;
##              return COMMENT;

[[:space:]]+    /* ignore */
.               /* ditto */
Run Code Online (Sandbox Code Playgroud)

和解析器:

%debug
%error-verbose
%verbose
%locations

%{
#include <stdio.h>
#include <string.h>

void yyerror(const char *str) {
        fprintf(stderr, "error: %s\n", str);
}

int yywrap() {
        return 1;
} 

extern int yydebug;
int main(void) {
    yydebug = 0;
    yyparse();
}
%}

%token PRINT NUMBER COMMENT PLEASE

%%

commands: /* empty */
        |
        commands command
    ;

command: print number comment please {
        if ($3) {
            printf("%#x", $2);
        } else {
            printf("%d", $2);
        }
        printf("\n");
     }
     ;

print: comment PRINT
     ;

number: comment NUMBER {
        $$ = $2;
      }
      ;

please: comment PLEASE
      ;

comment: /* empty */ {
            $$ = 0;
       }
       |
        comment COMMENT {
            $$ = 1;
        }
    ;
Run Code Online (Sandbox Code Playgroud)

所以,正如你所看到的,不完全是火箭科学,但它确实有效。由于comment在多个位置匹配空字符串,因此存在移位/减少冲突。此外,没有规则可以在 finalpleaseEOF. 但总的来说,我认为这是一个很好的例子。


小智 1

在词法分析器级别将注释视为空格。\n但保留两条单独的规则,一条用于空格,一条用于注释,两者都返回相同的标记 ID。

\n\n
    \n
  • 注释规则(+可选空格)在专用结构中跟踪注释。
  • \n
  • 空白规则会重置结构。
  • \n
\n\n

当您输入\xe2\x80\x9c特定位置\xe2\x80\x9d时,查看最后一个空格是否是注释或触发错误。

\n