如何检测Jison中的新线?

时间:2016-05-31 16:03:21

标签: parsing bison jison

我有一段看起来像这样的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

将来这会变得有点复杂,但我最初的想法是将其分解为每行(在许多情况下,新行将作为分隔符)。我对这些东西都很陌生,所以我可能对如何解决这个问题有一个完全错误的想法。所以我的问题是如何检测新线?如果对我正在尝试做的事情有更好的方法,那么任何建议都非常受欢迎。感谢。

2 个答案:

答案 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的更新答案比这个答案更清晰,完全符合我的要求,所以我接受了。