0

我正在尝试解析一个Name=Value对列表,其中值可以包含除空格以外的任何内容(即值可以包含等号)。
该名称仅限于通常的标识符字符。

问题是,“价值”标记匹配一切。例如,对于输入:

dude=sweet

解析器会将整个输入与“值”标记匹配(并抛出一个MismatchedTokenException)。

bison中,有可能将状态分配给标记(或者这只是用于非终结符?),以便它们只有在显式转换到该状态后才变得“有资格”进行匹配。

编辑考虑一下,这在野牛中也不起作用-令牌拆分已经发生(在flex中);但是,我认为有一种方法可以REJECT标记,迫使flex尝试次优匹配。

这是我的 ANTLR 语法。

grammar command_string;

start   
    :    commandParam* EOF
    ;
commandParam 
    :   IDENTIFIER '=' CONTINUOUS_VALUE 
    ;
IDENTIFIER 
    :   ('-'|'_'|'a'..'z'|'A'..'Z'|'0'..'9')+ 
    ;
CONTINUOUS_VALUE
    :   ~( ALL_WS )+
    ;
WS
    :   (ALL_WS) +      { $channel = HIDDEN; }
    ;
fragment ALL_WS     
    :   ' ' | '\t' | '\r' | '\n' 
    ;
4

1 回答 1

1

您在 CONTINUOUS_VALUE 和 IDENTIFIER 之间有一些重叠(IDENTIFIER 中的字符是 CONTINUOUS_VALUE 的子集。可能有几种方法可以解决这个问题。一种方法是使用 '=' 开始 CONTINUOUS_VALUE,然后将其从文本。在 CSharp 中,它看起来像这样:

CONTINUOUS_VALUE
    :   '=' ~( ALL_WS )+ { Text = Text.Substring(1, Text.Length - 1); }
    ;

然后只需将“=”从 commandParam 规则中取出。

第二种方法是制定 IDENTIFIER 和 CONTINUOUS_VALUE 解析器规则(至少第一个字母小写),然后你有上下文来确定哪个应该匹配。您也可以将它们制作成片段并在 commandParam 中引用它们,但我不确定您是否可以嵌套片段,因为您已经拥有 ALL_WS 片段。

此外,您不需要在 NameValue 对之间使用某种分隔符吗?

于 2009-08-31T03:26:05.010 回答