当前位置: 首页 > 知识库问答 >
问题:

ANTLR4:错误的lexer规则匹配

白驰
2023-03-14

我刚刚开始学习ANTLR4 lexer规则。我的目标是为Java属性文件创建一个简单的语法。以下是我目前掌握的信息:

lexer grammar PropertiesLexer;

LineComment
    : ( LineCommentHash
      | LineCommentExcl
      )
      -> skip
    ;

fragment LineCommentHash
    : '#' ~[\r\n]*
    ;

fragment LineCommentExcl
    : '!' ~[\r\n]*
    ;

fragment WrappedLine
    : '\\'
      ( '\r' '\n'?
      | '\n'
      )
    ;

Newline
    : ( '\r' '\n'?
      | '\n'
      )
      -> skip
    ;

Key
    : KeyLetterStart
      ( KeyLetter
      | Escaped
      )*
    ;

fragment KeyLetterStart
    : ~[ \t\r\n:=]
    ;

fragment KeyLetter
    : ~[\t\r\n:=]
    ;

fragment Escaped
    : '\\' .?
    ;

Equal
    : ( '\\'? ':'
      | '\\'? '='
      )
    ;

Value
    : ValueLetterBegin
      ( ValueLetter
      | Escaped
      | WrappedLine
      )*
    ;

fragment ValueLetterBegin
    : ~[ \t\r\n]
    ;

fragment ValueLetter
    : ~ [\r\n]+
    ;

Whitespace
    : [ \t]+
      -> skip
    ;
# comment 1
# comment 2
# 
.key1= value1
key2\:sub=value2
key3 \= value3

key4=value41\
value42

# comment3
#comment4
key=value
[@0,30:42='.key1= value1',<Value>,4:0]
[@1,45:60='key2\:sub=value2',<Value>,5:0]
[@2,63:76='key3 \= value3',<Value>,6:0]
[@3,81:102='key4=value41\\r\nvalue42',<Value>,8:0]
[@4,130:138='key=value',<Value>,13:0]
[@5,141:140='<EOF>',<EOF>,14:0]
[@0,30:34='.key1',<Key>,4:0]
[@1,35:35='=',<Equal>,4:5]
[@2,37:42='value1',<Key>,4:7]
[@3,45:49='key2\',<Key>,5:0]
[@4,50:50=':',<Equal>,5:5]
[@5,51:53='sub',<Key>,5:6]
[@6,54:54='=',<Equal>,5:9]
[@7,55:60='value2',<Key>,5:10]
[@8,63:68='key3 \',<Key>,6:0]
[@9,69:69='=',<Equal>,6:6]
[@10,71:76='value3',<Key>,6:8]
[@11,81:84='key4',<Key>,8:0]
[@12,85:85='=',<Equal>,8:4]
[@13,86:93='value41\',<Key>,8:5]
[@14,96:102='value42',<Key>,9:0]
[@15,130:132='key',<Key>,13:0]
[@16,133:133='=',<Equal>,13:3]
[@17,134:138='value',<Key>,13:4]
[@18,141:140='<EOF>',<EOF>,14:0]

共有1个答案

松英喆
2023-03-14

ANTLR的lexer规则匹配尽可能多的字符,这就是为什么您会看到所有这些value标记被创建(它们匹配的字符最多)。

词汇模式似乎很适合在这里使用。类似于这样:

lexer grammar PropertiesLexer;

COMMENT
 : [!#] ~[\r\n]* -> skip
 ;

KEY
 : ( '\\' ~[\r\n] | ~[\r\n\\=:] )+
 ;

EQUAL
 : [=:] -> pushMode(VALUE_MODE)
 ;

NL
 : [\r\n]+ -> skip
 ;

mode VALUE_MODE;

  VALUE
   : ( ~[\\\r\n] | '\\' . )+
   ;

  END_VALUE
   : [\r\n]+ -> skip, popMode
   ;
 类似资料:
  • 我试图了解ANTLR4是如何基于lexer和解析器规则工作的,但我在下面的示例中遗漏了一些内容: 我正在尝试解析一个文件,并匹配所有的数学加法(例如1+2+3等)。我的文件包含以下文本: 我想和 4+5+22+1 而且 2+4+255 以上所述都与lexer匹配输入的方式有关?我知道lexer会查找第一个最长的匹配规则,但我如何更改语法以便只匹配添加的规则呢?

  • null null 以下是我的(不完整和不成功的)尝试: 如果不能在lexer中解决这个问题,我可以使用标记、、、、、和自行编写解析器规则。

  • 可能在内部使用的代码将在规则之后被取消,如下所示: ANTLR4就是这样做事的吗?

  • 我正在为使用ANTLR4的某种语言开发一个小型IDE,当lexer无法匹配错误字符时,我需要在错误字符下划线。在这种情况下,内置的实现向stderr输出一条消息,类似于如下所示: 我完全可以理解如何获得关于错误的行和列的信息(作为参数传递给回调),但如何在回调中获得字符串? 当解析器是错误的来源时,它会将违规令牌作为回调的第二个参数传递,因此提取关于错误输入的开始和停止偏移量的信息变得很简单,参考

  • 我正在重新学习一些基本的Antlr,并尝试编写一个生成todo项的语法: 我遇到的问题是,有三个lexer规则特别“不匹配”,这取决于它们使用的上下文: 以下是我的完整语法以求清晰: 旁白:我知道还有其他奇怪的地方,比如一个事件的名称只能是一个单词,但我是在一次处理一个问题。