antlr4go

https://github.com/bramp/antlr4-grammars
https://github.com/bramp/antlr4-grammars/tree/master/xml
https://github.com/bramp/antlr4-grammars/blob/master/json/json_test.go
安装
$curl -O https://www.antlr.org/download/antlr-4.8-complete.jar
$java jar /Users/antlr-4.8-complete.jar
错误: 找不到或无法加载主类 jar
注意命令是java -jar
$java -jar /Users/antlr-4.8-complete.jar
ANTLR Parser Generator Version 4.8
-o __ specify output directory where all output is generated
-lib __
specify location of grammars, tokens files
-atn generate rule augmented transition network diagrams
-encoding __ specify grammar file encoding; e.g., euc-jp
-message-format __
specify output style for messages in antlr, gnu, vs2005
-long-messages show exception details when available for errors and warnings
-listener generate parse tree listener (default)
-no-listener don’t generate parse tree listener
-visitor generate parse tree visitor
-no-visitor don’t generate parse tree visitor (default)
-package ___ specify a package/namespace for the generated code
-depend generate file dependencies
-D



$java -jar ../calc/antlr-4.8-complete.jar
ANTLR Parser Generator Version 4.8
-o __ specify output directory where all output is generated
-lib __
specify location of grammars, tokens files



注意4.5.1这个包有问题
$java -jar antlr-4.5.1-complete.jar
错误: 找不到或无法加载主类 org.antlr.v4.Tool
$java -jar /Users/didi/PhpstormProjects/c/json-parser/antlr/antlr-4.5.1-complete.jar
错误: 找不到或无法加载主类 org.antlr.v4.Tool


// Calc.g4
grammar Calc;

// Tokens
MUL: '*';
DIV: '/';
ADD: '+';
SUB: '-';
NUMBER: [0-9]+;
WHITESPACE: [ \r\n\t]+ -> skip;

// Rules
start : expression EOF;

expression
: expression op=('*'|'/') expression # MulDiv
| expression op=('+'|'-') expression # AddSub
| NUMBER # Number
;

生成代码
$java -jar ../calc/antlr-4.8-complete.jar -Dlanguage=Go -o parser Calc.g4



$tree
.
|__Calc.g4
|
parser
| |
Calc.interp
| |
Calc.tokens
| |
calc_base_listener.go
| |
calc_lexer.go
| |
calc_listener.go
| |
calc_parser.go
| |
CalcLexer.interp
| |
__CalcLexer.tokens



$go mod init github.com/xiazemin/json-parser/antlr/antlr4go
go: creating new go.mod: module github.com/xiazemin/json-parser/antlr/antlr4go



https://www.antlr.org/download.html
$go get github.com/antlr/antlr4/runtime/Go/antlr



// example1.go
package main



import (
“fmt”
“github.com/antlr/antlr4/runtime/Go/antlr”



”./parser”
)



func main() {
// Setup the input
is := antlr.NewInputStream(“1 + 2 * 3”)



// Create the Lexer
lexer := parser.NewCalcLexer(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())
} }


package main



import “github.com/xiazemin/json-parser/antlr/antlr4go/parser”



// example2.go
package main



import (
“github.com/xiazemin/json-parser/antlr/antlr4go/parser”
“github.com/antlr/antlr4/runtime/Go/antlr”
)



type calcListener struct {
*parser.BaseCalcListener
}



func main() {
// Setup the input
is := antlr.NewInputStream(“1 + 2 * 3”)



// Create the Lexer
lexer := parser.NewCalcLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

// Create the Parser
p := parser.NewCalcParser(stream)

// Finally parse the expression
antlr.ParseTreeWalkerDefault.Walk(&calcListener{}, p.Start()) }


package main



import (
“fmt”
“github.com/antlr/antlr4/runtime/Go/antlr”
“github.com/xiazemin/json-parser/antlr/antlr4go/parser”
“strconv”
)



type calcListener struct {
*parser.BaseCalcListener



stack []int }


func (l *calcListener) push(i int) {
l.stack = append(l.stack, i)
}



func (l *calcListener) pop() int {
if len(l.stack) < 1 {
panic(“stack is empty unable to pop”)
}



// Get the last value from the stack.
result := l.stack[len(l.stack)-1]

// Remove the last element from the stack.
l.stack = l.stack[:len(l.stack)-1]

return result }


func (l *calcListener) ExitMulDiv(c *parser.MulDivContext) {
right, left := l.pop(), l.pop()



switch c.GetOp().GetTokenType() {
case parser.CalcParserMUL:
l.push(left * right)
case parser.CalcParserDIV:
l.push(left / right)
default:
panic(fmt.Sprintf("unexpected op: %s", c.GetOp().GetText()))
} }


func (l *calcListener) ExitAddSub(c *parser.AddSubContext) {
right, left := l.pop(), l.pop()



switch c.GetOp().GetTokenType() {
case parser.CalcParserADD:
l.push(left + right)
case parser.CalcParserSUB:
l.push(left - right)
default:
panic(fmt.Sprintf("unexpected op: %s", c.GetOp().GetText()))
} }


func (l *calcListener) ExitNumber(c *parser.NumberContext) {
i, err := strconv.Atoi(c.GetText())
if err != nil {
panic(err.Error())
}



l.push(i) }


// calc takes a string expression and returns the evaluated result.
func calc(input string) int {
// Setup the input
is := antlr.NewInputStream(input)



// Create the Lexer
lexer := parser.NewCalcLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

// Create the Parser
p := parser.NewCalcParser(stream)

// Finally parse the expression (by walking the tree)
var listener calcListener
antlr.ParseTreeWalkerDefault.Walk(&listener, p.Start())

return listener.pop() }


func main() {
print(calc(“1+2*3-4+5”))
}



package main
import (
“bramp.net/antlr4/json” // The parser
“github.com/antlr/antlr4/runtime/Go/antlr”
)



type exampleListener struct {
// https://godoc.org/bramp.net/antlr4/json#BaseJSONListener
*json.BaseJSONListener
}



func main() {
// Setup the input
is := antlr.NewInputStream(
{
"example": "json",
"with": ["an", "array"]
}
)



// Create the JSON Lexer
lexer := json.NewJSONLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)



// Create the JSON Parser
p := json.NewJSONParser(stream)



// Finally walk the tree
antlr.ParseTreeWalkerDefault.Walk(&exampleListener{}, p.Json())
}



https://github.com/antlr/antlr4/blob/master/doc/grammars.md
https://zhuanlan.zhihu.com/p/47179842
https://github.com/thesues/antlr-calc-golang-example



https://blog.gopheracademy.com/advent-2017/parsing-with-antlr4-and-go/
https://liangshuang.name/2017/08/20/antlr/
https://github.com/antlr/antlr4/tree/master/runtime/Go/antlr



$export GOPROXY=https://goproxy.io
$go run example1.go
build command-line-arguments: cannot load github.com/antlr/antlr4/runtime/Go/antlr: module github.com/antlr/antlr4/runtime/Go/antlr: Get https://goproxy.io/github.com/antlr/antlr4/runtime/%21go/antlr/@v/list: x509: certificate has expired or is not yet valid



$ GOPROXY=”https://goproxy.cn”
$cd ../parser/
$go mod init github.com/xiazemin/json-parser/antlr/antlr4go/parser
go: creating new go.mod: module github.com/xiazemin/json-parser/antlr/antlr4go/parser



$cd exp1
replace github.com/xiazemin/json-parser/antlr/antlr4go/parser => ../parser



$go run example1.go
NUMBER (“1”)
ADD (“+”)
NUMBER (“2”)
MUL (“*”)
NUMBER (“3”)



$go mod edit -replace github.com/xiazemin/json-parser/antlr/antlr4go/parser=../parser



$go run example2.go
go: finding github.com/antlr/antlr4 latest


command-line-arguments


./example2.go:6:1: syntax error: non-declaration statement outside function body



$go mod init github.com/xiazemin/json-parser/antlr/antlr4go
go: creating new go.mod: module github.com/xiazemin/json-parser/antlr/antlr4go
$go mod edit -replace github.com/xiazemin/json-parser/antlr/antlr4go/parser=../parser
$go run example3.go
go: finding github.com/antlr/antlr4 latest
8



$go run example4.go
go: finding github.com/antlr/antlr4 latest
go: finding bramp.net/antlr4 latest
go: downloading bramp.net/antlr4 v0.0.0-20190812013724-3751fbacda98
go: extracting bramp.net/antlr4 v0.0.0-20190812013724-3751fbacda98
https://blog.gopheracademy.com/advent-2017/parsing-with-antlr4-and-go/


Category golang