diff --git a/example/main.go b/example/main.go index d63d910..5b7365c 100644 --- a/example/main.go +++ b/example/main.go @@ -8,11 +8,11 @@ package main // Remove local imports import ( "flag" - "github.com/HashCode55/GPython" + "github.com/puneets2811/GPython" ) func main() { boolPtr := flag.Bool("log", true, "Set it to true to log the details.") flag.Parse() - gpython.ParseEngine("hello = 3 * 6 - ( 5 / 2 )", *boolPtr) + gpython.ParseEngine("hello = 2 * (3 - 5)", *boolPtr) } diff --git a/grammar.txt b/grammar.txt index 04ff58b..b5e8673 100644 --- a/grammar.txt +++ b/grammar.txt @@ -6,4 +6,4 @@ start := TokenName '=' TokenString | factExpr factExpr := termExpr (TokenPlus | TokenMinus termExpr)* termExpr := atom (TokenStar | TokenSlash atom)* -atom := TokenNumber | TokenName \ No newline at end of file +atom := TokenNumber | TokenName | TokenLpar factExpr TokenRpar \ No newline at end of file diff --git a/parser.go b/parser.go index fe7ec88..3c97563 100644 --- a/parser.go +++ b/parser.go @@ -16,6 +16,7 @@ package gpython // Handle identifier startng with a number import ( + "strconv" "fmt" log "github.com/Sirupsen/logrus" ) @@ -63,6 +64,35 @@ func (ast *AST) Traverse(root *Node) []string { return tokenList } + +func (ast *AST) EvaluateTree(root *Node) float64 { + if root == nil { + return 0; + } + + if root.left == nil && root.right == nil { + value, _ := strconv.ParseFloat(root.token.Val, 64) + return value + } + + leftValue := ast.EvaluateTree(root.left) + rightValue := ast.EvaluateTree(root.right) + + if root.token.Type_ == TokenPlus { + return leftValue + rightValue + } + if root.token.Type_ == TokenMinus { + return leftValue - rightValue + } + if root.token.Type_ == TokenStar { + return leftValue * rightValue + } + if root.token.Type_ == TokenSlash { + return leftValue / rightValue + } + return -1 +} + // Advance modifies two pointers of the Parser construct. // It makes the current token as next token and get the next token // from the channel. @@ -258,5 +288,8 @@ func ParseEngine(input string, lg bool) (*Node, error) { } ast.Traverse(ast) } + + fmt.Println(ast.EvaluateTree(ast.right)) + return ast, nil } diff --git a/parser_test.go b/parser_test.go index 78b1a8f..6475d6a 100644 --- a/parser_test.go +++ b/parser_test.go @@ -32,6 +32,81 @@ func TestParseString(t *testing.T) { } } +func TestParenthesis(t *testing.T) { + // TestParenthesisPass + _, err := ParseEngine("hello = ((((3))))", false) + if err != nil { + t.Error("Parser failed for fine syntax") + } + + _, err = ParseEngine("hello = (3) + ((4))", false) + if err != nil { + t.Error("Parser failed for fine syntax") + } + + _, err = ParseEngine("hello = (3) + (4 + (5 * 6 / (7))) * (9 - (6))", false) + if err != nil { + t.Error("Parser failed for fine syntax") + } + + + // TestParenthesisFail + _, err = ParseEngine("hello = ()", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = 2 + 3 + ()", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("() = a + 2", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("(hello) = a + 2", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = (()(((()", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = (2 + 3 + (a + 6)", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = )", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = )(", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = (a + ) 2", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = a (+) 2", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } + + _, err = ParseEngine("hello = (a + 2)(b + 3)", false) + if err == nil { + t.Error("Parser not failing for bad syntax") + } +} + func TestAST(t *testing.T) { astNode, _ := ParseEngine("hello = 123 - 22", false) tokenList := astNode.Traverse(astNode)