Bison &引用;“行的其余部分”;野牛
考虑一下这个简单的lex/yacc定义: 在第1段中:Bison &引用;“行的其余部分”;野牛,bison,yacc,Bison,Yacc,考虑一下这个简单的lex/yacc定义: 在第1段中: PRINT { return PRINT;} 年: PRINT printlist { statement_t *new = mkstatement(PRINT); new->parms.print.using = NULL; new->parms.print.l = $2; $$ = new; } printlist: expression { printitem_t *new = malloc(siz
PRINT { return PRINT;}
年:
PRINT printlist
{
statement_t *new = mkstatement(PRINT);
new->parms.print.using = NULL;
new->parms.print.l = $2;
$$ = new;
}
printlist:
expression
{
printitem_t *new = malloc(sizeof(*new));
new->e = $1;
new->sep = 0;
$$ = g_list_prepend(NULL, new);
} | { strings of expressions }
很简单。现在我想查看和存储评论。经典的解决方案很简单:
"//".*\n
这将整个注释标记为yacc端的单个标记。现在,我可以使用字符串处理提取实际注释,但这就是lex/yacc的用途。那么,我是否缺少一种像打印一样解析REM的简单方法,也就是说,有没有一种简单的方法可以将“行中的所有其他内容”都转换为2美元?我已经尝试了几种方法,但总是会导致lex端匹配每一行,因为它是最长的匹配。(F)lex不提供任何类似于regex库中“捕获”的机制yytext
始终是(f)lex模式识别的完整标记
有时,您可以使用固定偏移量来提取文本标记的有趣部分。例如,您可能会看到这种(f)lex操作,它从字符串文本中删除引号:(简化;真正的解析器可能会关心反斜杠转义):
这当然适用于您的注释案例,我将在不使用终止换行符的情况下编写该案例(部分原因是可能没有换行符,部分原因是换行符几乎肯定会在扫描仪中的其他位置处理,并且可能会有一些与换行符相关的操作):
也许您更愿意在传递文本之前删除注释中的前导空格(如果有)。在讨论这一点之前,我建议您实际上可能希望保留空白。可能注释包含一个缩进良好的代码示例,删除所有注释正文中的前导空格将破坏其格式
但是如果您真的想删除空白,那么您有两种可能:
yylval
中。我想这正是你所说的“使用字符串处理”的意思,我可以理解为什么你会认为这很难看。(尽管在这种情况下,它具有简单的优点。)%x SC_COMMENT
%%
"//"[[:blank:]]* { BEGIN(SC_COMMENT); }
<SC_COMMENT>.* { yylval.str = strdup(yytext); return TOK_COMMENT; }
<SC_COMMENT>\n { BEGIN(INITIAL); }
%x SC\u注释
%%
“/”[[:blank:][]*{BEGIN(SC_COMMENT);}
.*{yylval.str=strdup(yytext);返回TOK_COMMENT;}
\n{开始(首字母);}
它将注释文本与注释标记本身相关联,从而避免使用额外的解析器规则。但是,如果出于某种原因,您确实想编写一个冗余解析器规则,那么您可以很容易地修改上述内容,以生成两个令牌:
%x SC_COMMENT
%%
"//"[[:blank:]]* { BEGIN(SC_COMMENT); return TOK_COMMENT; }
<SC_COMMENT>.* { yylval.str = strdup(yytext); return TOK_COMMENT_BODY; }
<SC_COMMENT>\n { BEGIN(INITIAL); }
%x SC\u注释
%%
“/”[[:blank:][]*{BEGIN(SC_COMMENT);return TOK_COMMENT;}
.*{yylval.str=strdup(yytext);返回TOK_COMMENT_BODY;}
\n{开始(首字母);}
野牛消耗代币,而不是线。没有内置的行的概念,所以如果你想要一个叫做“行”的东西,你需要制定规则来识别它:在lexer中将它转换成token(s),然后在解析器中解析它。综观这些选项,看起来修剪才是正确的选择。我考虑了状态,这在大多数/*风格注释的引用中都有显示,但在本例中,我发现结果比处理字符串更混乱,这是经典的C。因此,字符串黑客就是这样!
%x SC_COMMENT
%%
"//"[[:blank:]]* { BEGIN(SC_COMMENT); }
<SC_COMMENT>.* { yylval.str = strdup(yytext); return TOK_COMMENT; }
<SC_COMMENT>\n { BEGIN(INITIAL); }
%x SC_COMMENT
%%
"//"[[:blank:]]* { BEGIN(SC_COMMENT); return TOK_COMMENT; }
<SC_COMMENT>.* { yylval.str = strdup(yytext); return TOK_COMMENT_BODY; }
<SC_COMMENT>\n { BEGIN(INITIAL); }