Python 3 interpreter in Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

196 lines
4.3 KiB

package ast
import (
"fmt"
"strconv"
"github.com/brettlangdon/gython/grammar"
"github.com/brettlangdon/gython/symbol"
"github.com/brettlangdon/gython/token"
)
func ASTFromGrammar(root *grammar.FileInput) (Mod, error) {
mod := NewModule()
for _, child := range root.Children() {
if child.ID() == symbol.STMT {
stmt := astForStatement(child.(*grammar.Statement))
mod.Append(stmt)
}
}
return mod, nil
}
func isToken(node grammar.Node, tokId token.TokenID) bool {
if n, isTokenNode := node.(*grammar.TokenNode); isTokenNode {
return n.Token.ID == tokId
}
return false
}
func astForStatement(root *grammar.Statement) Statement {
stmt := root.Child()
if stmt.ID() == symbol.SIMPLE_STMT {
stmt = stmt.(*grammar.SimpleStatement).Children()[0]
}
switch stmt := stmt.(type) {
case *grammar.SmallStatement:
switch child := stmt.Child().(type) {
case *grammar.ExpressionStatement:
return astForExpressionStatement(child)
}
case *grammar.CompoundStatement:
fmt.Println(stmt)
}
return nil
}
func astForExpressionStatement(root *grammar.ExpressionStatement) Statement {
children := root.Children()
if len(children) == 1 {
} else if "todo" == "augassign" {
} else {
if !isToken(children[1], token.EQUAL) {
return nil
}
length := len(children)
var value Expression
switch child := children[length-1].(type) {
case *grammar.TestlistStarExpression:
value = astForTestList(child)
default:
value = nil
}
assign := NewAssign(value)
for i := 0; i < length-2; i++ {
target := astForTestList(children[i].(grammar.ExpressionStatementChild))
switch target := target.(type) {
case *Name:
target.Context = NewStore()
}
assign.Append(target)
}
return assign
}
return nil
}
func astForTestList(root grammar.ExpressionStatementChild) Expression {
switch root := root.(type) {
case *grammar.TestlistStarExpression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
}
return nil
}
func astForExpression(root grammar.Node) Expression {
switch root := root.(type) {
case *grammar.Test:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.OrTest:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.AndTest:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.NotTest:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.Comparison:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.Expression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.XorExpression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.AndExpression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.ShiftExpression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.ArithmeticExpression:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.Term:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.Factor:
if root.Length() == 1 {
return astForExpression(root.Children()[0])
}
case *grammar.Power:
return astForPower(root)
default:
fmt.Println(symbol.SymbolNames[root.ID()])
}
return nil
}
func astForPower(root *grammar.Power) Expression {
children := root.Children()
var expr Expression
if child, isAtomExpr := children[0].(*grammar.AtomExpression); isAtomExpr {
expr = astForAtomExpression(child)
} else {
return nil
}
if len(children) == 1 {
return expr
}
return nil
}
func astForAtomExpression(root *grammar.AtomExpression) Expression {
children := root.Children()
switch child := children[0].(type) {
case *grammar.Atom:
return astForAtom(child)
}
return nil
}
func astForAtom(root *grammar.Atom) Expression {
children := root.Children()
if len(children) == 1 {
switch child := children[0].(type) {
case *grammar.TokenNode:
switch child.Token.ID {
case token.NAME:
// TODO: Check for "None", "True", and "False"
return NewName(child.Token.Literal, NewLoad())
case token.NUMBER:
value, err := strconv.ParseInt(child.Token.Literal, 10, 64)
if err != nil {
return nil
}
return NewNum(value)
}
}
}
return nil
}