我有一段看起来像这样的Jison代码:
%lex
%options flex
%{
if (!('regions' in yy)) {
yy.regions = [];
}
%}
text [a-zA-Z][a-zA-Z0-9]*
%%
\s+ /* skip whitespace */
\n+ return 'NL';
"," return ',';
"-" return '-';
"[" return '[';
"]" return ']';
{text} return 'TEXT';
<<EOF>> return 'EOF';
/lex
%start expressions
%%
expressions
: content EOF
{
console.log(yy.regions);
return yy.regions;
}
| EOF
{
console.log("empty file");
return yy.regions;
}
;
content
: line NL content
{ console.log("NL"); }
| line content
{ console.log("no NL"); }
//| line NL
// { console.log("parsing line with NL"); }
| line
{ console.log("parsing line"); }
;
line
: '[' text ']'
{ yy.regions.push($2); $$ = $2; }
;
text
: TEXT
{ $$ = $1; }
;
这是我的输入目前的样子(我从我计划的最基本的构造开始,我想从那里构建它):
[sectionA]
[sectionB]
[sectionC]
我遇到的问题是未检测到新行。它总是进入line content
而永远进入line NL content
。后来我想解析看起来更像这样的东西:
[sectionA]
something1, something2, something3
something4, something5, something6
[sectionB]
something4, something5, something6
[sectionC]
something4, something5, something6
something4, something5, something6
something4, something5, something6
将来这会变得有点复杂,但我最初的想法是将其分解为每行(在许多情况下,新行将作为分隔符)。我对这些东西都很陌生,所以我可能对如何解决这个问题有一个完全错误的想法。所以我的问题是如何检测新线?如果对我正在尝试做的事情有更好的方法,那么任何建议都非常受欢迎。感谢。
答案 0 :(得分:4)
这两条规则都会匹配换行符:
\s+ /* skip whitespace */
\n+ return 'NL';
由于第一个是第一个,它将获胜。 (Flex会给你一个关于第二条规则未被使用的警告,但我不认为jison会做那个分析。)
更改规则的顺序无济于事,因为第一个规则将匹配 SPACE NL ,从而如果前面有空格,则吞下换行符。您需要将空白规则更改为仅匹配不是换行符的空格。
一种可能性是:
\n\s* return 'NL';
[^\S\n]+ /* ignore whitespace other than newlines */
第一个模式将匹配换行符后跟任何空格序列,这意味着它将匹配多个换行符。当输入中有空行时,这将避免返回多个NL
令牌;除非空行是重要的,这可能就是你想要的。
第二种模式避免匹配任何换行符,因此它不会与第一种模式冲突。
有些人担心使用Windows行结尾(\r\n
),但由于Javascript的\s
包含\r
,因此这里没有真正的问题。第二条规则将忽略\r
,第一条规则将识别\n
。如果您认为有必要,可以将第一个规则更改为\r?\n\s*
以提高效率,但可能不会更快。
答案 1 :(得分:0)
@ rici的答案有所帮助,它让我走上正轨。但是,=
并没有做我需要的事情。这些是我最终使用的两行:
[ \t]+
我找到了他们here。
编辑:@ rici的更新答案比这个答案更清晰,完全符合我的要求,所以我接受了。