antlr4 как создать дерево в golang для синтаксического анализа javascript

#go #antlr4

# #Вперед #antlr4

Вопрос:

Я пытаюсь создать анализатор javascript в golang, используя antlr4. грамматика, которую я использую, это (https://github.com/antlr/grammars-v4/tree/master/javascript/ecmascript ) и я следую инструкциям из этого readme https://github.com/antlr/antlr4/blob/master/doc/go-target.md

итак, я сгенерировал файлы lexer и parser из грамматики, и я пытаюсь протестировать синтаксический анализ программы.

 func Parse(program string) {

    is := antlr.NewInputStream(program)

    lexer := parser.NewECMAScriptLexer(is)
    stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

    p := parser.NewECMAScriptParser(stream)
    antlr.ParseTreeWalkerDefault.Walk(amp;ParserListener{}, tree)

}
 

проблема antlr.ParseTreeWalkerDefault.Walk в том, что ожидается прослушиватель синтаксического анализа и дерево. но у BaseParser нет функции для генерации объекта типа дерева. https://godoc.org/github.com/antlr/antlr4/runtime/Go/antlr#BaseParser

Ответ №1:

Для каждого нетерминала в грамматике сгенерированный анализатор будет иметь метод с тем же именем, что и нетерминал, который не принимает аргументов и возвращает результат синтаксического анализа данного нетерминала в виде дерева синтаксического анализа. Это дерево, к которому вы должны перейти Walk .

Итак, поскольку используемая вами грамматика определяет нетерминальное имя program , вы можете вызвать p.Program() для синтаксического анализа программу и получить обратно соответствующее дерево синтаксического анализа.

Ответ №2:

Посмотрите на BaseECMAScriptListener функции в parser/ecmascript_base_listener.go файле.

 package main

import (
    "./parser"
    "fmt"
    "github.com/antlr/antlr4/runtime/Go/antlr"
)

type echoListener struct {
    *parser.BaseECMAScriptListener
}

// Example
func (s *echoListener) VisitTerminal(node antlr.TerminalNode) {
    fmt.Printf("%vn", node.GetText())
}

func Parse(program string) {
    is := antlr.NewInputStream(program)

    lexer := parser.NewECMAScriptLexer(is)
    stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

    p := parser.NewECMAScriptParser(stream)

    antlr.ParseTreeWalkerDefault.Walk(amp;echoListener{}, p.Program())
}

func main() {
    Parse("function test(a, b) { return a   b; }")
}