我正在尝试解析许多文本记录,其中记录中的元素由“+”字符分隔,并且整个记录以“#”字符结尾。例如E1 + E2 + E3 + E4 + E5 + E6#
可以要求或选择单个元素。如果一个元素是可选的,那么它的值就会丢失。例如,如果E2丢失,输入字符串将为:E1 ++ E3 + E4 + E5 + E6#。
但是,在处理空尾随元素时,也可能缺少分隔符char('+')。例如,如果缺少最后3个元素,则字符串可以是:E1 + E2 + E3#,但它也可以是: E1 + E2 + E3 +++#
我在Antlr中尝试了以下规则:
'R1''E1 + E2 + E3''+'? 'E4'? '+'? 'E5'? '+'? 'E6'? '#
但是Antlr抱怨它的含糊不清当然是正确的(E3之后的每个令牌都可能是E4,E5或E6)。输入语法是固定的(它来自传统的大型机系统),所以我想知道是否有人有这个问题的解决方案?
另一种方法是在规则中指定所有不同的排列,但这将是一项重大任务。
致以最诚挚的问候和谢谢,
迈克尔答案 0 :(得分:1)
对于ANTLR,这个任务听起来有点过分,你是不是因为没有使用'+'作为分隔符将字符串拆分成数组?
如果它来自大型机,它很可能是以一种微不足道的方式处理的。
如,
C ++:http://www.cplusplus.com/reference/clibrary/cstring/strtok/
PHP:http://us3.php.net/manual/en/function.explode.php
Java:http://java.sun.com/javase/6/docs/api/java/lang/String.html#split%28java.lang.String%29
C#:http://msdn.microsoft.com/en-us/library/system.string.split%28VS.71%29.aspx
只是一个想法。
答案 1 :(得分:0)
如果这是不明确的,可能是因为您的E
具有相同的格式(更复杂的情况是您的E
只是以相同的k
个字符开头其中k
是你的前瞻,但我会假设情况并非如此。如果是,这仍然可行;它只需要一个额外的步骤。)
所以看起来你最多可以有6 E
秒和最多5 +
秒。我们会说“细分”是一个可选的E
,后跟一个+
- 您可以有5个细分,也可以选择尾随E
。
这个语法大致可以这样表示(不完美的ANTLR语法,因为我对它不是很熟悉):
r : (e_opt? PLUS){1,5} e_opt? END
e_opt : E // whatever your E is
PLUS : '+'
END : '#'
如果ANTLR不支持{1,5}
之类的内容,那么这与:
(e_opt? PLUS) ((e_opt? PLUS) ((e_opt? PLUS) ((e_opt? PLUS) (e_opt? PLUS)?)?)?)?
这不是那么干净,所以也许有更好的方法可以做到。