类似于 JSON 的自定义语法

customized grammar similar to json

提问人:fluter 提问时间:10/20/2023 更新时间:10/21/2023 访问量:52

问:

我正在尝试创建一个类似于json的语法,但不完全是,数据是这样的:

{foo=123,bar=abc}

基本上,名称和字符串没有双引号和等号而不是键值分隔符的逗号,我有基于 json v4 语法的语法,除了我有以下修改:

pair
   : STRING '=' value
   ;

value
   : STRING
   |  NUMBER ....;

STRING
    : (ESC | SAFECODEPOINT)+
    ;

但是,在解析上述数据片段时,解析器会将 whol 字符串视为单个值,而不会将其分解为标记。我认为问题出在STRING定义上。如何修复 STRING 令牌定义?

java 解析 antlr antlr4

评论


答:

2赞 jon hanson 10/21/2023 #1

问题在于你的 STRING 规则是贪婪的,例如不排除“=”,所以直到最后一个大括号的所有内容都被该规则消耗掉了。

解决此问题的一种方法是限制字段名称中可以显示的内容,例如,限制为仅字母字符。下面显示的 Antlr 语法正是这样做的。你可以在这里测试它。对于示例输入:

{foo=123,bar=abc}

它生成一个成功的解析树。

完整语法:

grammar JSON;

json
   : value EOF
   ;

obj
   : '{' pair (',' pair)* '}'
   | '{' '}'
   ;

pair
   : STRING '=' value
   ;

value
   : STRING
   | NUMBER
   | obj
   ;

STRING
   : [a-zA-Z]+
   ;

fragment ESC
   : '\\' (["\\/bfnrt] | UNICODE)
   ;

fragment UNICODE
   : 'u' HEX HEX HEX HEX
   ;

fragment HEX
   : [0-9a-fA-F]
   ;

fragment SAFECODEPOINT
   : ~ ["\\\u0000-\u001F]
   ;

NUMBER
   : '-'? INT ('.' [0-9] +)? EXP?
   ;

fragment INT
   : '0' | [1-9] [0-9]*
   ;

fragment EXP
   : [Ee] [+\-]? [0-9]+
   ;

WS
   : [ \t\n\r] + -> skip
   ;