我正在尝试解析Name=Value
对的列表,其中值可以包含除空格之外的任何内容(即值可以包含等号)。
该名称仅限于通常的标识符字符。
问题是,'Value'标记匹配所有内容。例如,输入:
dude=sweet
解析器会将整个输入与“值”标记匹配(并抛出MismatchedTokenException
)。
在 bison 中,有可能将状态分配给令牌(或者这只是针对非终结符?),以便它们在显式转换到该状态后才“匹配”匹配。
编辑考虑到这一点,这在 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'
;
答案 0 :(得分:1)
你在CONTINUOUS_VALUE和IDENTIFIER之间有一些重叠(IDENTIFIER中的字符是CONTINUOUS_VALUE的子集。可能有几种方法可以解决这个问题。一种方法是用'='启动CONTINUOUS_VALUE然后去掉它在文本中。在CSharp中,它看起来像这样:
CONTINUOUS_VALUE
: '=' ~( ALL_WS )+ { Text = Text.Substring(1, Text.Length - 1); }
;
然后从命令参数规则中取出'='。
第二种方法是制作IDENTIFIER和CONTINUOUS_VALUE解析器规则(小写至少是第一个字母),然后你有上下文来确定哪一个应该匹配。您也许可以将它们作为片段并在commandParam中引用它们,但我不确定您是否可以嵌套片段,因为您已经拥有ALL_WS片段。
另外,你不需要在NameValue对之间使用某种分隔符吗?