COMMIT TO BE AMENDED
This commit is contained in:
parent
89ca1b3b5d
commit
04e669c156
36
pj1-go/ast.go
Normal file
36
pj1-go/ast.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Code generated by tools/gen-ast.go DO NOT EDIT.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "git.bonsai.cool/kayprish/pj1/pj1-go/lexer"
|
||||||
|
|
||||||
|
type Expr interface {
|
||||||
|
isExpr()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Binary struct {
|
||||||
|
left Expr
|
||||||
|
operator lexer.Token
|
||||||
|
right Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Binary) isExpr() {}
|
||||||
|
|
||||||
|
type Grouping struct {
|
||||||
|
expression Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Grouping) isExpr() {}
|
||||||
|
|
||||||
|
type Literal struct {
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Literal) isExpr() {}
|
||||||
|
|
||||||
|
type Unary struct {
|
||||||
|
operator lexer.Token
|
||||||
|
right Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Unary) isExpr() {}
|
||||||
|
|
112
pj1-go/gen-ast.go
Normal file
112
pj1-go/gen-ast.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
//go:build generate
|
||||||
|
//go:generate go run ./gen-ast.go ./
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
var modulePath string
|
||||||
|
|
||||||
|
// returns a string which contains the current module path, keep in mind this
|
||||||
|
// program is meant to be run in the root of the module using go generate
|
||||||
|
func getModulePath() string {
|
||||||
|
goModFile, err := os.Open("./go.mod")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Could not open go.mod file, is this command being run in the module root folder?")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(goModFile)
|
||||||
|
scanner.Scan()
|
||||||
|
fstLine := scanner.Text()
|
||||||
|
if fstLine[:7] != "module " {
|
||||||
|
fmt.Fprintln(os.Stderr, "The first line of go.mod seems malformed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
goModFile.Close()
|
||||||
|
path := strings.TrimSpace(fstLine[7:])
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) != 2 {
|
||||||
|
fmt.Fprintln(os.Stderr, "Usage: go run gen-ast.go <output directory>")
|
||||||
|
os.Exit(64)
|
||||||
|
}
|
||||||
|
outputDir := os.Args[1]
|
||||||
|
modulePath = getModulePath()
|
||||||
|
defineAst(outputDir, "Expr",
|
||||||
|
[]string{"Binary : left Expr, operator lexer.Token, right Expr",
|
||||||
|
"Grouping : expression Expr",
|
||||||
|
"Literal : value interface{}",
|
||||||
|
"Unary : operator lexer.Token, right Expr"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func lowerFirst(s string) string {
|
||||||
|
if s == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
r, n := utf8.DecodeRuneInString(s)
|
||||||
|
return string(unicode.ToLower(r)) + s[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func defineAst(outputDir string, baseName string, types []string) {
|
||||||
|
fileName := "ast"
|
||||||
|
var path string = outputDir + "/" + fileName + ".go"
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Could not open file \""+path+"\"")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
fmt.Fprintln(f, "// Code generated by tools/gen-ast.go DO NOT EDIT.")
|
||||||
|
fmt.Fprintln(f, "package main")
|
||||||
|
fmt.Fprintln(f)
|
||||||
|
fmt.Fprintln(f, "import \"" + modulePath + "/lexer\"")
|
||||||
|
fmt.Fprintln(f)
|
||||||
|
// Creates a dummy interface just to limit types which can be
|
||||||
|
// considered an "Expr"
|
||||||
|
fmt.Fprintln(f, "type "+baseName+" interface {")
|
||||||
|
fmt.Fprintln(f, "\tis"+baseName+"()")
|
||||||
|
fmt.Fprintln(f, "}")
|
||||||
|
fmt.Fprintln(f)
|
||||||
|
|
||||||
|
// The AST types.
|
||||||
|
for _, t := range types {
|
||||||
|
tSplit := strings.Split(t, ":")
|
||||||
|
typeName := strings.TrimSpace(tSplit[0])
|
||||||
|
fields := strings.TrimSpace(tSplit[1])
|
||||||
|
defineType(f, baseName, typeName, fields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func defineType(f io.Writer, baseName string, typeName string, fieldList string) {
|
||||||
|
fmt.Fprintln(f, "type " + typeName + " struct {")
|
||||||
|
|
||||||
|
// Fields.
|
||||||
|
var fields []string = strings.Split(fieldList, ", ")
|
||||||
|
for _, field := range fields {
|
||||||
|
fmt.Fprintln(f, "\t" + field)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(f, "}")
|
||||||
|
fmt.Fprintln(f)
|
||||||
|
|
||||||
|
// Interface dummy function
|
||||||
|
fmt.Fprintln(f, "func (x "+typeName+") is"+ baseName +"() {}")
|
||||||
|
fmt.Fprintln(f)
|
||||||
|
|
||||||
|
// TODO: may have to generate constructor, according to top of
|
||||||
|
// page 110, right now it seems that defining structs without
|
||||||
|
// the constructor does the job
|
||||||
|
}
|
Loading…
Reference in a new issue