diff --git a/examples/yolol/operations3.yolol b/examples/yolol/operations3.yolol index 41ed170..a792e82 100644 --- a/examples/yolol/operations3.yolol +++ b/examples/yolol/operations3.yolol @@ -16,4 +16,5 @@ k=2 :testamod=:testamod==0 :testmxor=1!=1!=1 :testfloor=100.123/1000*1000==100 -:done = 1 \ No newline at end of file +x=3 y=2 z=1 :testprec=x>y==y>z +:done=1 \ No newline at end of file diff --git a/examples/yolol/operations3_test.yaml b/examples/yolol/operations3_test.yaml index 24aca0e..f3bd563 100644 --- a/examples/yolol/operations3_test.yaml +++ b/examples/yolol/operations3_test.yaml @@ -13,4 +13,5 @@ cases: testadiv: 1 testamod: 1 testmxor: 1 - testfloor: 1 \ No newline at end of file + testfloor: 1 + testprec: 1 \ No newline at end of file diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index b77fe65..788beaf 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -54,10 +54,7 @@ type YololParserFunctions interface { ParseAssignment() ast.Statement ParseIf() ast.Statement ParseExpression() ast.Expression - ParseLogicExpression() ast.Expression - ParseCompareExpression() ast.Expression - ParseSumExpression() ast.Expression - ParseProdExpression() ast.Expression + ParseBinaryExpression(int) ast.Expression ParseUnaryExpression() ast.Expression ParseBracketExpression() ast.Expression ParseSingleExpression() ast.Expression @@ -411,103 +408,53 @@ func (p *Parser) ParseIf() ast.Statement { // ParseExpression parses an expression func (p *Parser) ParseExpression() ast.Expression { p.Log() - return p.This.ParseLogicExpression() + return p.This.ParseBinaryExpression(0) } -// ParseLogicExpression parses a logical expression -func (p *Parser) ParseLogicExpression() ast.Expression { - p.Log() - var exp ast.Expression - - exp = p.This.ParseCompareExpression() - if exp == nil { - return nil - } - logOps := []string{"or", "and"} - - for p.IsCurrentType(ast.TypeKeyword) && p.IsCurrentValueIn(logOps) { - binexp := &ast.BinaryOperation{ - Operator: p.CurrentToken.Value, - Exp1: exp, - } - p.Advance() - binexp.Exp2 = p.This.ParseCompareExpression() - if binexp.Exp2 == nil { - p.ErrorCurrent(fmt.Sprintf("Expected expression on right side of %s", binexp.Operator)) - } - exp = binexp - } - return exp -} - -// ParseCompareExpression parses a compare expression -func (p *Parser) ParseCompareExpression() ast.Expression { - p.Log() - exp := p.This.ParseSumExpression() - if exp == nil { - return nil - } - logOps := []string{"==", "!=", "<=", ">=", "<", ">"} - - for p.IsCurrentType(ast.TypeSymbol) && p.IsCurrentValueIn(logOps) { - binexp := &ast.BinaryOperation{ - Operator: p.CurrentToken.Value, - Exp1: exp, - } - p.Advance() - binexp.Exp2 = p.This.ParseSumExpression() - if binexp.Exp2 == nil { - p.ErrorCurrent(fmt.Sprintf("Expected expression on right side of %s", binexp.Operator)) - } - exp = binexp - } - return exp -} +// ParseBinaryExpression parses a binary expression +// The kind of binary-expression to be parsed is given as idx +func (p *Parser) ParseBinaryExpression(idx int) ast.Expression { + p.LogI(idx) -// ParseSumExpression parses a sum-expression -func (p *Parser) ParseSumExpression() ast.Expression { - p.Log() var exp ast.Expression - - exp = p.This.ParseProdExpression() + var ops []string + expectedType := ast.TypeSymbol + + switch idx { + case 0: + ops = []string{"or", "and"} + expectedType = ast.TypeKeyword + break + case 1: + ops = []string{"==", "!="} + break + case 2: + ops = []string{"<=", ">=", "<", ">"} + break + case 3: + ops = []string{"+", "-"} + break + case 4: + ops = []string{"*", "/", "%", "^"} + break + default: + exp = p.This.ParseUnaryExpression() + return exp + } + + idx++ + + exp = p.This.ParseBinaryExpression(idx) if exp == nil { return nil } - logOps := []string{"+", "-"} - - for p.IsCurrentType(ast.TypeSymbol) && p.IsCurrentValueIn(logOps) { + for p.IsCurrentType(expectedType) && p.IsCurrentValueIn(ops) { binexp := &ast.BinaryOperation{ Operator: p.CurrentToken.Value, Exp1: exp, } p.Advance() - binexp.Exp2 = p.This.ParseProdExpression() - if binexp.Exp2 == nil { - p.ErrorCurrent(fmt.Sprintf("Expected expression on right side of %s", binexp.Operator)) - } - exp = binexp - } - return exp -} - -// ParseProdExpression parses a product expression -func (p *Parser) ParseProdExpression() ast.Expression { - p.Log() - var exp ast.Expression - - exp = p.This.ParseUnaryExpression() - if exp == nil { - return nil - } - logOps := []string{"*", "/", "%", "^"} - - for p.IsCurrentType(ast.TypeSymbol) && p.IsCurrentValueIn(logOps) { - binexp := &ast.BinaryOperation{ - Operator: p.CurrentToken.Value, - Exp1: exp, - } - p.Advance() - binexp.Exp2 = p.This.ParseUnaryExpression() + binexp.Exp2 = p.This.ParseBinaryExpression(idx) if binexp.Exp2 == nil { p.ErrorCurrent(fmt.Sprintf("Expected expression on right side of %s", binexp.Operator)) } @@ -667,3 +614,11 @@ func (p *Parser) Log() { fmt.Println("Called:", callingFunctionName(), "from line", callingLineNumber(), "with", p.CurrentToken.String()) } } + +// Log logs the visiting of a parsing function +func (p *Parser) LogI(arg int) { + if p.DebugLog { + // Print the name of the function + fmt.Println("Called:", callingFunctionName(), "from line", callingLineNumber(), "with", p.CurrentToken.String(), "arg", arg) + } +} diff --git a/pkg/parser/printer.go b/pkg/parser/printer.go index 1554e53..a651f77 100644 --- a/pkg/parser/printer.go +++ b/pkg/parser/printer.go @@ -45,17 +45,17 @@ var operatorPriority = map[string]int{ "and": 0, "==": 1, "!=": 1, - ">=": 1, - "<=": 1, - ">": 1, - "<": 1, - "+": 2, - "-": 2, - "*": 3, - "/": 3, - "^": 3, - "%": 3, - "not": 4, + ">=": 2, + "<=": 2, + ">": 2, + "<": 2, + "+": 3, + "-": 3, + "*": 4, + "/": 4, + "^": 4, + "%": 4, + "not": 5, } // end and else are missing here, because unlike other keywords they might require a space after them