https://github.com/padraicbc/gojsp
https://github.com/padraicbc/gojsp
antlr4 golang javascript parser
Last synced: 25 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/padraicbc/gojsp
- Owner: padraicbc
- Created: 2021-04-02T13:31:48.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-04-29T17:24:39.000Z (almost 5 years ago)
- Last Synced: 2024-11-13T15:55:51.090Z (about 1 year ago)
- Topics: antlr4, golang, javascript, parser
- Language: Go
- Homepage:
- Size: 2.69 MB
- Stars: 4
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Very early attempt at creating an [ANTLR](https://www.antlr.org/) visitor for javascript files using GO. Going to change like Irish weather so don't expect things to stay the same any time soon.
The `base` is the result of running what is described [here](https://github.com/padraicbc/gojsp/tree/master/runantlr#readme)
The [vast](https://github.com/padraicbc/gojsp/tree/master/vast) folder is the implementation so far toward creating an ast which will allow easy manipulation/translation of the original source.
Thre are a few example functions in the exampls folder including how to parse and [manipulate](https://github.com/padraicbc/gojsp/blob/master/examples/singleexpress.go) a single expression.
import (
"log"
antlr "github.com/padraicbc/antlr4"
"github.com/padraicbc/gojsp/base"
"github.com/padraicbc/gojsp/vast"
)
code := `i + j;`
v := vast.NewVisitor(code)
// do whatever with errors
go v.DefaultError()
// start at ExpressionSequence
tree := v.Parser.ExpressionSequence()
exp := visit(tree, v).(*vast.ExpressionSequence)
expc := exp.FirstChild().(*vast.LRExpression)
fmt.Println(expc.Left().(vast.Token).Value(), expc.OP().Value(), expc.Right().(vast.Token).Value())
// change OP
expc.OP().SetValue("/")
expc.Right().(vast.Token).SetValue("1000")
fmt.Println(expc.Left().(vast.Token).Value(), expc.OP().Value(), expc.Right().(vast.Token).Value())
// reuse lexer and parser
v.Stream.Seek(0)
v.Lexer.SetInputStream(v.Stream)
tokenStream := antlr.NewCommonTokenStream(v.Lexer, antlr.TokenDefaultChannel)
v.Parser.SetInputStream(tokenStream)
tree2 := v.Parser.ExpressionStatement()
exp2 := visit(tree2, v).(*vast.ExpressionStatement).FirstChild()
expc = exp2.FirstChild().(*vast.LRExpression)
// can be any singleExpression so any VNode
fmt.Println(expc.Left().(vast.Token).Value(), expc.OP().Value(), expc.Right().(vast.Token).Value())
expc = exp2.FirstChild().(*vast.LRExpression)
// can be any singleExpression so any VNode
fmt.Println(expc.Left().(vast.Token).Value(), expc.OP().Value(), expc.Right().(vast.Token).Value())
And a very incomplete conversion from arrow to es5 functions but it shows the general idea:
code := `
// Arrow Function Break Down
// 1. Remove the word "function" and place arrow between the argument and opening body bracket
(a) => {
return a + 100;
}
// 2. Remove the body brackets and word "return" -- the return is implied.
(b) => b + 100;
// 3. Remove the argument parentheses
c => c
// Arrow Function
(a, b) => {
let chuck = 42;
return a + b + chuck;
}
`
v := vast.NewVisitor(code)
tree := v.Parser.Program()
go v.DefaultError()
// v.Debug = true
rfs := visit(tree, v).(*vast.Program).Body
// Statement ->ExpressionStatememts -> ExpressionSequence
for _, fn := range rfs {
var trans string
// all with one child
af := fn.FirstChild().FirstChild().FirstChild().(*vast.ArrowFunction)
// either has a function body with {} of a single expression.
if af.Body.SingleExpression != nil {
// can be there or not
var open, close string
if af.FunctionParameters.OpenParen == nil {
open, close = "(", ")"
}
trans = fmt.Sprintf("function%s%s%s {\n\treturn %s;\n}",
open, af.FunctionParameters.Source, close, af.Body.SingleExpression.Code())
} else {
trans = fmt.Sprintf("function%s %s", af.FunctionParameters.Source, af.Body.Source)
}
fmt.Println("After ->", trans)
}
Quite verbose but more about getting it working than pretty to start...