From 53658b6c1504087e41a7954ba2ae64c4b0270648 Mon Sep 17 00:00:00 2001 From: Puneet Date: Thu, 16 Nov 2017 00:00:01 +0530 Subject: [PATCH 1/2] Parenthesis Test --- example/main.go | 4 +-- grammar.txt | 2 +- parser_test.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/example/main.go b/example/main.go index d63d910..6cc502d 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 = a (+) 2", *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_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) From ae85b687ffb35992445d7062f7fba7478bafa9de Mon Sep 17 00:00:00 2001 From: Puneet Date: Thu, 16 Nov 2017 22:48:24 +0530 Subject: [PATCH 2/2] Expression RHS evaluation --- example/main.go | 2 +- parser.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/example/main.go b/example/main.go index 6cc502d..5b7365c 100644 --- a/example/main.go +++ b/example/main.go @@ -14,5 +14,5 @@ import ( func main() { boolPtr := flag.Bool("log", true, "Set it to true to log the details.") flag.Parse() - gpython.ParseEngine("hello = a (+) 2", *boolPtr) + gpython.ParseEngine("hello = 2 * (3 - 5)", *boolPtr) } 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 }