Skip to content

Commit

Permalink
Made exponentiation right-assoziative
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaumgarten committed Nov 26, 2020
1 parent a894225 commit 64bf4ff
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 19 deletions.
5 changes: 3 additions & 2 deletions examples/yolol/operations4.yolol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
i="abc" j=i++ k=++i :testi=i=="abc " and j=="abc" and k=="abc "
i="abc" j=i-- k=--i :testd=i=="a" and j=="abc" and k=="a"
i="abc" j=i++ k= ++i :testi=i=="abc " and j=="abc" and k=="abc "
i="abc" j=i-- k= --i :testd=i=="a" and j=="abc" and k=="a"
:testsum="abc"+"xyz"=="abcxyz"
:testsub="abcdecddc"-"cd"=="abcdedc"
:testeq="abc"=="abc" and not ("mno"=="pqr")
Expand All @@ -8,4 +8,5 @@ i="abc" j=i-- k=--i :testd=i=="a" and j=="abc" and k=="a"
:testgte="jkl">="aaa" and not ("aaa">="jkl") and "jkl">="jkl"
:testlt="qqq"<"xyz" and not ("xyz"<"qqq") and ""<"a"
:testlte="qqq"<="xyz" and not ("xyz"<="qqq") and "qqq">="qqq"
:testra=2*3^4==162 and (2*3)^4==1296
:done=1
1 change: 1 addition & 0 deletions examples/yolol/operations4_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ cases:
testgte: 1
testlt: 1
testlte: 1
testra: 1


47 changes: 37 additions & 10 deletions pkg/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,10 @@ func (p *Parser) ParseExpression() ast.Expression {
func (p *Parser) ParseBinaryExpression(idx int) ast.Expression {
p.LogI(idx)

var exp ast.Expression
var exp *ast.BinaryOperation
var ops []string
expectedType := ast.TypeSymbol
leftAssoc := true

switch idx {
case 0:
Expand All @@ -435,31 +436,57 @@ func (p *Parser) ParseBinaryExpression(idx int) ast.Expression {
ops = []string{"+", "-"}
break
case 4:
ops = []string{"*", "/", "%", "^"}
ops = []string{"*", "/", "%"}
break
case 5:
ops = []string{"^"}
leftAssoc = false
break
default:
exp = p.This.ParseUnaryExpression()
return exp
return p.This.ParseUnaryExpression()
}

idx++

exp = p.This.ParseBinaryExpression(idx)
if exp == nil {
leftExp := p.This.ParseBinaryExpression(idx)
if leftExp == nil {
return nil
}

for p.IsCurrentType(expectedType) && p.IsCurrentValueIn(ops) {
binexp := &ast.BinaryOperation{
Operator: p.CurrentToken.Value,
Exp1: exp,
}

p.Advance()
binexp.Exp2 = p.This.ParseBinaryExpression(idx)
if binexp.Exp2 == nil {
rightExp := p.This.ParseBinaryExpression(idx)
if rightExp == nil {
p.ErrorCurrent(fmt.Sprintf("Expected expression on right side of %s", binexp.Operator))
return binexp
}
exp = binexp

if exp == nil {
binexp.Exp1 = leftExp
binexp.Exp2 = rightExp
exp = binexp
continue
}

if leftAssoc {
binexp.Exp1 = exp
binexp.Exp2 = rightExp
exp = binexp
} else {
binexp.Exp1 = exp.Exp2
binexp.Exp2 = rightExp
exp.Exp2 = binexp
}
}

if exp == nil {
return leftExp
}

return exp
}

Expand Down
20 changes: 13 additions & 7 deletions pkg/parser/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ var operatorPriority = map[string]int{
"-": 3,
"*": 4,
"/": 4,
"^": 4,
"%": 4,
"not": 5,
"^": 5,
"not": 6,
}

// end and else are missing here, because unlike other keywords they might require a space after them
Expand Down Expand Up @@ -259,16 +259,22 @@ func insertEscapesIntoString(in string) string {
func (p *Printer) printBinaryOperation(o *ast.BinaryOperation, visitType int) {
lPrio := priorityForExpression(o.Exp1)
rPrio := priorityForExpression(o.Exp2)
_, rBinary := o.Exp2.(*ast.BinaryOperation)
rBinary, rIsBinary := o.Exp2.(*ast.BinaryOperation)
lBinary, lIsBinary := o.Exp1.(*ast.BinaryOperation)
myPrio := priorityForExpression(o)

// check if we need braces because of the right-associativity of the ^-operator
rightAssocL := o.Operator == "^" && lIsBinary && lBinary.Operator == "^"
rightAssocR := o.Operator == "^" && rIsBinary && rBinary.Operator == "^"

switch visitType {
case ast.PreVisit:
if lPrio < myPrio {
if lPrio < myPrio || rightAssocL {
p.Write("(")
}
break
case ast.InterVisit1:
if lPrio < myPrio {
if lPrio < myPrio || rightAssocL {
p.Write(")")
}
op := o.Operator
Expand All @@ -282,12 +288,12 @@ func (p *Printer) printBinaryOperation(o *ast.BinaryOperation, visitType int) {
p.OptionalSpace()
}

if rBinary && rPrio <= myPrio {
if rIsBinary && rPrio <= myPrio && !rightAssocR {
p.Write("(")
}
break
case ast.PostVisit:
if rBinary && rPrio <= myPrio {
if rIsBinary && rPrio <= myPrio && !rightAssocR {
p.Write(")")
}
break
Expand Down

0 comments on commit 64bf4ff

Please sign in to comment.