1

我有一段 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

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

4

2 回答 2

5

这两个规则都将匹配换行符:

\s+                 /* skip whitespace */
\n+                 return 'NL';

因为第一个是第一个,所以它会赢。(Flex 会警告您第二条规则未使用,但我不相信 jison 会进行这种分析。)

但是,更改规则的顺序无济于事,因为第一条规则将 match SPACE NL,因此如果换行符前面有空格,则会将其吞下。您需要更改空格规则以仅匹配不是换行符的空格。

一种可能性是:

\n\s*     return 'NL';
[^\S\n]+  /* ignore whitespace other than newlines */

第一个模式将匹配一个换行符后跟任何空格序列,这意味着它将匹配多个换行符。NL当输入中有空行时,这将避免返回多个标记;除非空行很重要,否则这可能就是您想要的。

第二个模式避免匹配任何换行符,因此它不会与第一个模式冲突。

有些人担心 Windows 行尾 ( \r\n) 的使用,但由于 Javascript 的\sinclude \r,这里没有真正的问题。将\r被第二个规则忽略并被\n第一个规则识别。如果您认为有必要,可以将第一条规则更改\r?\n\s*为提高效率,但结果可能不会更快。

于 2016-05-31T16:20:22.597 回答
0

@rici 的回答很有帮助,它让我走上了正确的轨道。但是,[ \t]+没有做我需要的。这些是我最终使用的两行:

(\r?\n)+\s*         return 'NEWLINE';
[^\S\r\n]+          ; /* whitespace */

我在这里找到了它们。

编辑:@rici 的更新答案比这个答案更清晰,并且完全符合我的需要,所以我接受了。

于 2016-05-31T18:13:30.893 回答