antlr - ANTLR4:错误的词法规则匹配
问题描述
我刚刚开始学习 ANTLR4 词法分析器规则。我的目标是为 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
当我运行时grun
,我得到以下输出:
[@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]
我不明白为什么Value
定义匹配。但是,在注释掉Value
定义时,它会识别Key
和Equal
定义:
[@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]
但是如何让它识别Key
,Equal
和 Value
定义呢?
解决方案
ANTLR 的词法分析器规则匹配尽可能多的字符,这就是为什么您会看到所有这些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
;
推荐阅读
- android - Navigation Drawer 使用 customadapter 实现 Master/Detail
- vue.js - 从 VueRouter 实例访问路由对象
- marklogic - 在 marklogic 中与 JSearch 一起使用时,区分大小写的过滤器不起作用:
- java - 在 SOAP UI 中获取响应错误
- php - WooCommerce AJAX 分页没有插件
- rest - 为什么 atmoicinteger (incrementAndGet) 在每个新的 restful (stateless) 服务调用中返回新值
- perforce - 获取最新的 Perforce 时如何排除文件类型
- javascript - 在无限循环中迭代更改数据库
- xshell - xshell:无法加载更新数据文件 - 可能的客户端/数据版本不匹配
- sql - 获取实例未在nodejs中返回值