(使用antlr-4.1-complete.jar)
我是ANTLR4的新手,并创建了一个简单的语法来测试我学到的东西。我发现结果令人困惑,我觉得必须有一些基本的概念(通过我所有的阅读)都无法掌握。
这是我定义的语法:
grammar Gm;
// parser RULES
gmModel
: obj+
EOF
;
obj : objItem nameItem begin pairs end ;
objItem : OBJDECL ;
nameItem : OBJNAME ;
begin : OPEN ;
end : CLOSE ;
pairs : Pair+ ;
// LEXER RULES
OBJDECL : 'object' ;
OBJNAME : 'anotherobj' | 'testobj';
OPEN : '{' ;
CLOSE : '}' ;
fragment Var : ID_START (ID_CONT)+ ; // variable names start with an alpha
fragment Val : .*? ';' ; // values can be anything; capture everything up to the semicolon
Pair : Var Val ;
// fragments
fragment ID_START : [a-zA-Z] ;
fragment ID_CONT : [-_a-zA-Z0-9] ;
WS : [ \t]+ -> skip ;
这是我用作输入的文件。每个对象都有一些名称 - 值组。大多数情况下,它是一对 - 只有一个值(空格/制表符分隔)但有时,名称后面有两个值,这就是它捕获到分号的原因
object testobj {
testvar testval;
v_B 1234.9876;
}
object anotherobj {
name o611;
phases "CN";
v_A 2401.7771;
groupid OBJTEST;
timeslice 1 hour;
}
即使我定义了
OBJDECL : 'object' ;
作为Lexer规则,它不被识别为令牌(TestRig基本上显示了几个文本)。 我甚至把它放在首位,因为我读到第一个定义的标记优先。我还读到使用了最长的令牌,也许这就是这里发生的事情,但在这种情况下,我无法理解如何定义可以匹配不可预测长度的字符串的有用令牌。
非常感谢您提供的任何帮助!
此外,更多修补后的最终评论:如果我做了以下两个更改,标记化是正确的,除了每对只包含一个分号(内容在哪里?)
pairs : Pair+ ;
->
pairs : pair+ ;
和
Pair : Var Val ;
->
pair : ID_START (ID_CONT)+ .*? ';' ;
(换句话说,将'pair'作为解析器规则并用就地定义替换Var / Val片段)
从我有限的理解,我认为这种改变“改善”了因为我有效地删除了之前可以匹配的最长可能的令牌(配对+),但我仍然对为什么名称/值(s)感到困惑现在完全失踪了,我(显然!)仍然不清楚创建令牌的推荐方式,以确保它们不会太贪婪。
为什么现在只有分号才被拿走?不理解这是我觉得我仍然遗漏一些基本原因的一个原因。 (但是如果你不能从我的频繁编辑中说出来,我一直在考虑这个问题,并且已经阅读了很多其他先前发布的问题和答案,以便不问一个愚蠢的问题,但我真的很难过。 )
感谢您的指导!
答案 0 :(得分:0)
你是对的,“最长的正则表达式在这里匹配”。因此,当您处理未知长度的文本时,您可以使用词法模式。可能是以下语法可以正确解析您的文本。
以下是SampleObjectLexer.g4的内容:
lexer grammar SampleObjectLexer;
OBJECTDECLARATION : 'object';
OBJECTNAME : 'testobj'|'anotherobj';
OPEN : '{';
CLOSE : '}';
NEWLINE : [\r\n] -> skip;
WHITESPACE : [ \t] -> skip;
Var : ID_START (ID_CONT)+ -> pushMode(VALMODE);
fragment ID_START : [a-zA-Z];
fragment ID_CONT : [a-zA-Z0-9_-]+;
mode VALMODE;
Val : .*?';' -> popMode;
以下是SampleObjectParser.g4的内容
parser grammar SampleObjectParser;
options {tokenVocab = SampleObjectLexer;}
gmModel : obj+;
obj : OBJECTDECLARATION OBJECTNAME OPEN pair+ CLOSE;
pair : Var Val;
我们在词法分析器语法中做的是每当我们匹配令牌Var时,我们指示Antlr Lexer移动到VALMODE,在VALMODE中我们匹配该值并使用popMode返回到默认模式。由于默认模式不知道令牌Val(以前是最长的正则表达式),现在在默认模式下,词法分析器可以匹配像'object','testobj'等标记。