在 ANTLR 中创建强制令牌
Create mandatory token in ANTLR
我刚开始接触 ANTLR。我正在尝试创建一个简单的 hello world ANTLR。我的目标是使“Hello world”成为强制性字符串。因此,我期望“Hello”的输入被认为是无效的,它给我一个错误,指出它需要一个“world”令牌。
编辑:请注意,我确实希望“hello”和“world”是单独的标记(将它们视为关键字),以便我可以轻松地分别识别它们。
我有下面的 helloworld.g4:
grammar helloworld;
WHITESPACE: [ \r\n\t]+ -> skip;
HELLO : 'Hello' ;
WORLD : 'world' ;
start : HELLO WORLD EOF ;
我有以下 main.go:
package main
import (
"fmt"
"test/parser"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
const rule = `Hello`
type testListener struct {
*parser.BasehelloworldListener
}
func main() {
// Setup the input
is := antlr.NewInputStream(rule)
// Create the Lexer
lexer := parser.NewhelloworldLexer(is)
// Read all tokens
for {
t := lexer.NextToken()
if t.GetTokenType() == antlr.TokenEOF {
break
}
fmt.Printf("%s (%q)\n",
lexer.SymbolicNames[t.GetTokenType()],
t.GetText())
}
// Finally parse the expression
stream := antlr.NewCommonTokenStream(lexer,
antlr.TokenDefaultChannel)
// Create the Parser
p := parser.NewhelloworldParser(stream)
// Finally parse the expression
antlr.ParseTreeWalkerDefault.Walk(&testListener{}, p.Start())
}
我正在构建一个 Go 解析器,并使用以下命令测试结果:
antlr -Dlanguage=Go -o parser helloworld.g4 && go run main.go
输出:
HELLO ("Hello")
line 1:5 mismatched input '<EOF>' expecting 'Hello'
我想知道我能做些什么来给我一个输出,说明“world”是“hello”之后的预期标记。它不应该期待另一个“Hello”,它应该期待“world”然后是 EOF。
您在词法分析器中定义了 2 个单独的标记,因此词法分析器对输入没有问题 "Hello"
。
如果该 hello-token 应始终跟在 "world"
之后,则您必须将其包含在令牌中:
HELLO : 'Hello' ' '+ 'world';
如果您调用解析器规则 start
, 将 导致错误。这通常是强制存在 WORLD
标记(在解析器中)而不是在词法分析器中的方法。
编辑
您正在使用所有标记,然后将这个“使用过的词法分析器”提供给解析器。跳过标记的打印,或者在打印标记后重新初始化词法分析器。
应该这样做:
func main() {
is := antlr.NewInputStream(`Hello`)
lexer := parser.NewhelloworldLexer(is)
stream := antlr.NewCommonTokenStream(lexer,
antlr.TokenDefaultChannel)
p := parser.NewhelloworldParser(stream)
antlr.ParseTreeWalkerDefault.Walk(&testListener{}, p.Start())
}
我刚开始接触 ANTLR。我正在尝试创建一个简单的 hello world ANTLR。我的目标是使“Hello world”成为强制性字符串。因此,我期望“Hello”的输入被认为是无效的,它给我一个错误,指出它需要一个“world”令牌。
编辑:请注意,我确实希望“hello”和“world”是单独的标记(将它们视为关键字),以便我可以轻松地分别识别它们。
我有下面的 helloworld.g4:
grammar helloworld;
WHITESPACE: [ \r\n\t]+ -> skip;
HELLO : 'Hello' ;
WORLD : 'world' ;
start : HELLO WORLD EOF ;
我有以下 main.go:
package main
import (
"fmt"
"test/parser"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
const rule = `Hello`
type testListener struct {
*parser.BasehelloworldListener
}
func main() {
// Setup the input
is := antlr.NewInputStream(rule)
// Create the Lexer
lexer := parser.NewhelloworldLexer(is)
// Read all tokens
for {
t := lexer.NextToken()
if t.GetTokenType() == antlr.TokenEOF {
break
}
fmt.Printf("%s (%q)\n",
lexer.SymbolicNames[t.GetTokenType()],
t.GetText())
}
// Finally parse the expression
stream := antlr.NewCommonTokenStream(lexer,
antlr.TokenDefaultChannel)
// Create the Parser
p := parser.NewhelloworldParser(stream)
// Finally parse the expression
antlr.ParseTreeWalkerDefault.Walk(&testListener{}, p.Start())
}
我正在构建一个 Go 解析器,并使用以下命令测试结果:
antlr -Dlanguage=Go -o parser helloworld.g4 && go run main.go
输出:
HELLO ("Hello")
line 1:5 mismatched input '<EOF>' expecting 'Hello'
我想知道我能做些什么来给我一个输出,说明“world”是“hello”之后的预期标记。它不应该期待另一个“Hello”,它应该期待“world”然后是 EOF。
您在词法分析器中定义了 2 个单独的标记,因此词法分析器对输入没有问题 "Hello"
。
如果该 hello-token 应始终跟在 "world"
之后,则您必须将其包含在令牌中:
HELLO : 'Hello' ' '+ 'world';
如果您调用解析器规则 start
, 将 导致错误。这通常是强制存在 WORLD
标记(在解析器中)而不是在词法分析器中的方法。
编辑
您正在使用所有标记,然后将这个“使用过的词法分析器”提供给解析器。跳过标记的打印,或者在打印标记后重新初始化词法分析器。
应该这样做:
func main() {
is := antlr.NewInputStream(`Hello`)
lexer := parser.NewhelloworldLexer(is)
stream := antlr.NewCommonTokenStream(lexer,
antlr.TokenDefaultChannel)
p := parser.NewhelloworldParser(stream)
antlr.ParseTreeWalkerDefault.Walk(&testListener{}, p.Start())
}