gpt4 book ai didi

go - Antlr4 - 输入时没有可行的替代方案

转载 作者:IT王子 更新时间:2023-10-29 02:11:38 24 4
gpt4 key购买 nike

我正在尝试创建一个简单的 HOCON 解析器(从现有的 JSON 解析器开始)。

语法定义为:

/** Taken from "The Definitive ANTLR 4 Reference" by Terence Parr */

// Derived from http://json.org
grammar HOCON;

hocon
: value
| pair
;

obj
: object_begin pair (','? pair)* object_end
| object_begin object_end
;

pair
: STRING KV? value {fmt.Println("pairstr",$STRING.GetText())}
| KEY KV? value {fmt.Println("pairkey",$KEY.GetText())}
;

array
: array_begin value (',' value)* array_end
| array_begin array_end
;

value
: STRING {fmt.Println($STRING.GetText())}
| REFERENCE {fmt.Println($REFERENCE.GetText())}
| RAWSTRING {fmt.Println($RAWSTRING.GetText())}
| NUMBER {fmt.Println($NUMBER.GetText())}
| obj
| array
| 'true'
| 'false'
| 'null'
;

COMMENT
: '#' ~( '\r' | '\n' )* -> skip
;

STRING
: '"' (ESC | ~ ["\\])* '"'
| '\'' (ESC | ~ ['\\])* '\''
;

RAWSTRING
: (ESC | ALPHANUM)+
;

KEY
: ( '.' | ALPHANUM | '-')+
;

REFERENCE
: '${' (ALPHANUM|'.')+ '}'
;

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


fragment UNICODE
: 'u' HEX HEX HEX HEX
;

fragment ALPHANUM
: [0-9a-zA-Z]
;

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

KV
: [=:]
;

array_begin
: '[' { fmt.Println("BEGIN [") }
;

array_end
: ']' { fmt.Println("] END") }
;

object_begin
: '{' { fmt.Println("OBJ {") }
;

object_end
: '}' { fmt.Println("} OBJ") }
;

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

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

// no leading zeros

fragment EXP
: [Ee] [+\-]? INT
;

// \- since - means "range" inside [...]

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

错误是:

line 2:2 no viable alternative at input '{journal'
pairkey akka.persistence

给出错误的示例输入是:

akka.persistence {
journal {
# Absolute path to the journal plugin configuration entry used by
# persistent actor or view by default.
# Persistent actor or view can override `journalPluginId` method
# in order to rely on a different journal plugin.
plugin = ""
}
}

但是,如果我将其更新为使用带引号的字符串:

akka.persistence {
'journal' {
# Absolute path to the journal plugin configuration entry used by
# persistent actor or view by default.
# Persistent actor or view can override `journalPluginId` method
# in order to rely on a different journal plugin.
'plugin' = ""
}
}

一切都按预期进行。

看起来我在 KEY 定义中遗漏了一些东西,但我真的无法找出到底是什么。

测试它的 Go 代码是:

package main

import (
"github.com/antlr/antlr4/runtime/Go/antlr"
"go-hocon/parser"
)

func main() {
is, _ := antlr.NewFileStream("test/simple1.conf")

lex := parser.NewHOCONLexer(is)
p := parser.NewHOCONParser(antlr.NewCommonTokenStream(lex, 0))
p.BuildParseTrees = true
p.Hocon()
}

最佳答案

您的第一个输入使journal lex 成为RAWSTRING

[@0,0:15='akka.persistence',<KEY>,1:0]
[@1,17:17='{',<'{'>,1:17]
[@2,22:28='journal',<RAWSTRING>,2:2]
[@3,30:30='{',<'{'>,2:10]
[@4,277:282='plugin',<RAWSTRING>,7:4]
[@5,284:284='=',<KV>,7:11]
[@6,286:287='""',<STRING>,7:13]
[@7,292:292='}',<'}'>,8:2]
[@8,295:295='}',<'}'>,9:0]
[@9,298:297='<EOF>',<EOF>,10:0]
line 2:2 no viable alternative at input '{journal'

另一方面,'journal' 词法是一个字符串,但是有那些你显然不想要的单引号:

[@0,0:15='akka.persistence',<KEY>,1:0]
[@1,17:17='{',<'{'>,1:17]
[@2,22:30=''journal'',<STRING>,2:2] <-- now it's a string implicit token
[@3,32:32='{',<'{'>,2:12]
[@4,279:284='plugin',<RAWSTRING>,7:4]
[@5,286:286='=',<KV>,7:11]
[@6,288:289='""',<STRING>,7:13]
[@7,294:294='}',<'}'>,8:2]
[@8,297:297='}',<'}'>,9:0]
[@9,300:299='<EOF>',<EOF>,10:0]
line 7:4 no viable alternative at input '{plugin'
line 8:2 mismatched input '}' expecting {'true', 'false', 'null', '[', '{', STRING, RAWSTRING, REFERENCE, KV, NUMBER}

为什么?因为词法分析器规则以下列方式绑定(bind):1.首先匹配最长的输入。2.匹配隐式标记(如“journal”)3. 如果输入匹配的长度相等,则根据词法规则的顺序进行匹配。

在您的情况下,放置 'journal' 使其作为隐式标记匹配,因此它似乎工作正常。但仅仅因为那些单引号,这使得它符合上面的规则 2 没有引号,这两个标记被匹配为 RAWSTRING,这不符合规则

pair
: STRING KV? value //{fmt.Println("pairstr",$STRING.GetText())}

因此错误。

如何解决?好吧,我颠倒了词法分析器规则:

RAWSTRING
: (ESC | ALPHANUM)+
;

STRING
: '"' (ESC | ~ ["\\])* '"'
| '\'' (ESC | ~ ['\\])* '\''
;

并更改了:

pair
: RAWSTRING KV? value //{fmt.Println("pairstr",$STRING.GetText())}

现在它可以正常解析了:

[@0,0:15='akka.persistence',<KEY>,1:0]
[@1,17:17='{',<'{'>,1:17]
[@2,22:28='journal',<RAWSTRING>,2:2]
[@3,30:30='{',<'{'>,2:10]
[@4,277:282='plugin',<RAWSTRING>,7:4]
[@5,284:284='=',<KV>,7:11]
[@6,286:287='""',<STRING>,7:13]
[@7,292:292='}',<'}'>,8:2]
[@8,295:295='}',<'}'>,9:0]
[@9,298:297='<EOF>',<EOF>,10:0]

关于go - Antlr4 - 输入时没有可行的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44961694/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com