我正在尝试修改flex + bison生成器,以允许包含由周围的{{'}表示的代码段。和'}}'。与多行注释案例不同,我必须捕获所有内容。
我的尝试要么在{' {{'和'}}'是在同一条线上,或者它们很慢。
我的第一次尝试是这样的:
%{
#include <stdio.h>
// sscce implementation of a growing string buffer
char codeBlock[4096];
int codeOffset;
const char* curFilename = "file.l";
extern int yylineno;
void add_code_line(const char* yytext)
{
codeOffset += sprintf(codeBlock + codeOffset, "#line %u \"%s\"\n\t%s\n", yylineno, curFilename, yytext);
}
%}
%option stack
%option yylineno
%x CODE_FRAG
%%
"{{"[ \n]* { codeOffset = 0; yy_push_state(CODE_FRAG); }
<CODE_FRAG>"}}" { codeBlock[codeOffset] = 0; printf("// code\n%s\n", codeBlock); yy_pop_state(); }
<CODE_FRAG>[^\n]* { add_code_line(yytext); }
<CODE_FRAG>\n
\n
.
注意:&#34; codeBlock&#34;实施只是为了SSCCE的目的。这不是我实际使用的。
这适用于一个简单的测试用例:
{{ from line 1
from line 2
}}
{{
from line 7
}}
输出
// code
#line 1 "file.l"
from line 1
#line 2 "file.l"
from line 2
// code
#line 7 "file.l"
from line 7
但它无法处理
{{ hello }}
我能想到的两个解决方案是:
/* capture character-by-character */
<CODE_FRAG>. { add_code_character(yytext[0]); }
和
<INITIAL>"{{".*?"}}" { int n = strlen(yytext); yytext + (n - 2) = 0; add_code(yytext + 2); }
前者似乎很慢,而后者只是感觉不对。
有什么想法吗?
---编辑---
以下似乎可以达到预期的效果,但我不确定它是否是一个好的&#34;灵活的方式来做到这一点:
"{{"[ \n]* { codeOffset = 0; yy_push_state(CODE_FRAG); }
<CODE_FRAG>"}}" { codeBlock[codeOffset] = 0; printf("// code\n%s\n", codeBlock); yy_pop_state(); }
<CODE_FRAG>.*?/"}}" { add_code_line(yytext); }
<CODE_FRAG>.*? { add_code_line(yytext); }
<CODE_FRAG>\n
答案 0 :(得分:2)
Flex不会实现非贪婪的匹配。所以.*?
将无法按照您期望的方式在flex中工作。 (它将是一个可选的.*
,与.*
无法区分
这是一个正则表达式,在没有{{
的情况下尽可能与}}
匹配:
"{{"([}]?[^}])*
这可能不是您想要的,因为它不允许在您的代码块中嵌套{{...}}
。但是,您没有提到这是一个要求,并且您的示例都没有这样的功能。
上面的正则表达式不匹配结束}}
,它似乎是您想要的,因为它允许您在不修改临时缓冲区的情况下调用add_code(yytext+2)
。但是,您需要在操作中处理}}
。见下文。
如果没有匹配的}}
,上面的正则表达式将匹配文件的末尾。你可能想把它当作一个错误处理;最简单的方法是在您尝试忽略}}
"{{"([}]?[^}])* { add_code(yytext+2);
if (input() == EOF || input() == EOF) {
/* Produce an error, unclosed {{ */
}
}