simplify logical operators
This commit is contained in:
parent
5de730af97
commit
8adfb71887
7 changed files with 49 additions and 63 deletions
|
@ -62,17 +62,8 @@ func (as *AstStringer) visitAssignment(a *Assign) any {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *AstStringer) visitLogicalOr(l *LogicalOr) any {
|
func (as *AstStringer) visitLogical(l *Logical) any {
|
||||||
as.str.WriteString("(or ")
|
as.str.WriteString(fmt.Sprintf("(%s ", l.operator.lexeme))
|
||||||
l.left.accept(as)
|
|
||||||
as.str.WriteString(" ")
|
|
||||||
l.right.accept(as)
|
|
||||||
as.str.WriteString(")")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (as *AstStringer) visitLogicalAnd(l *LogicalAnd) any {
|
|
||||||
as.str.WriteString("(and ")
|
|
||||||
l.left.accept(as)
|
l.left.accept(as)
|
||||||
as.str.WriteString(" ")
|
as.str.WriteString(" ")
|
||||||
l.right.accept(as)
|
l.right.accept(as)
|
||||||
|
|
24
expr.go
24
expr.go
|
@ -6,9 +6,8 @@ type ExprVisitor interface {
|
||||||
visitLiteral(l *Literal) any
|
visitLiteral(l *Literal) any
|
||||||
visitGrouping(g *Grouping) any
|
visitGrouping(g *Grouping) any
|
||||||
visitVariable(v *Variable) any
|
visitVariable(v *Variable) any
|
||||||
visitLogicalOr(l *LogicalOr) any
|
visitLogical(l *Logical) any
|
||||||
visitAssignment(a *Assign) any
|
visitAssignment(a *Assign) any
|
||||||
visitLogicalAnd(l *LogicalAnd) any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Expr interface {
|
type Expr interface {
|
||||||
|
@ -44,15 +43,9 @@ type Assign struct {
|
||||||
value Expr
|
value Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogicalOr struct {
|
type Logical struct {
|
||||||
left Expr
|
left Expr
|
||||||
or Token
|
operator Token
|
||||||
right Expr
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogicalAnd struct {
|
|
||||||
left Expr
|
|
||||||
and Token
|
|
||||||
right Expr
|
right Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +55,7 @@ func (b *Binary) expr() {}
|
||||||
func (l *Literal) expr() {}
|
func (l *Literal) expr() {}
|
||||||
func (g *Grouping) expr() {}
|
func (g *Grouping) expr() {}
|
||||||
func (v *Variable) expr() {}
|
func (v *Variable) expr() {}
|
||||||
func (l *LogicalOr) expr() {}
|
func (l *Logical) expr() {}
|
||||||
func (l *LogicalAnd) expr() {}
|
|
||||||
|
|
||||||
func (u *Unary) accept(v ExprVisitor) any {
|
func (u *Unary) accept(v ExprVisitor) any {
|
||||||
return v.visitUnary(u)
|
return v.visitUnary(u)
|
||||||
|
@ -89,10 +81,6 @@ func (a *Assign) accept(v ExprVisitor) any {
|
||||||
return v.visitAssignment(a)
|
return v.visitAssignment(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogicalOr) accept(v ExprVisitor) any {
|
func (l *Logical) accept(v ExprVisitor) any {
|
||||||
return v.visitLogicalOr(l)
|
return v.visitLogical(l)
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogicalAnd) accept(v ExprVisitor) any {
|
|
||||||
return v.visitLogicalAnd(l)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,16 +55,9 @@ func (as *ExprToRPN) visitAssignment(a *Assign) any {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *ExprToRPN) visitLogicalOr(lo *LogicalOr) any {
|
func (as *ExprToRPN) visitLogical(lo *Logical) any {
|
||||||
lo.left.accept(as)
|
lo.left.accept(as)
|
||||||
lo.right.accept(as)
|
lo.right.accept(as)
|
||||||
as.str.WriteString(" or")
|
as.str.WriteString(" or")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *ExprToRPN) visitLogicalAnd(la *LogicalAnd) any {
|
|
||||||
la.left.accept(as)
|
|
||||||
la.right.accept(as)
|
|
||||||
as.str.WriteString(" and")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
3
glox.go
3
glox.go
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
@ -52,7 +51,7 @@ func (gl *Glox) run(source []byte) {
|
||||||
|
|
||||||
stmts, _ := newParser(tokens).parse()
|
stmts, _ := newParser(tokens).parse()
|
||||||
|
|
||||||
fmt.Println(AstStringer{stmts: stmts})
|
// fmt.Println(AstStringer{stmts: stmts})
|
||||||
|
|
||||||
gl.Interpreter.interpret(stmts)
|
gl.Interpreter.interpret(stmts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,12 +141,18 @@ func (i *Interpreter) visitAssignment(a *Assign) any {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Interpreter) visitLogicalOr(lo *LogicalOr) any {
|
func (i *Interpreter) visitLogical(lo *Logical) any {
|
||||||
return isTruthy(i.evaluate(lo.left)) || isTruthy(i.evaluate(lo.right))
|
|
||||||
|
left := i.evaluate(lo.left)
|
||||||
|
|
||||||
|
shortOr := lo.operator.typ == OR && isTruthy(left)
|
||||||
|
shortAnd := lo.operator.typ == AND && !isTruthy(left)
|
||||||
|
|
||||||
|
if shortOr || shortAnd {
|
||||||
|
return left
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Interpreter) visitLogicalAnd(la *LogicalAnd) any {
|
return i.evaluate(lo.right)
|
||||||
return isTruthy(i.evaluate(la.left)) && isTruthy(i.evaluate(la.right))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Interpreter) visitPrintStmt(p *PrintStmt) {
|
func (i *Interpreter) visitPrintStmt(p *PrintStmt) {
|
||||||
|
|
21
parser.go
21
parser.go
|
@ -151,9 +151,9 @@ func (p *Parser) expression() Expr {
|
||||||
return p.assignment()
|
return p.assignment()
|
||||||
}
|
}
|
||||||
|
|
||||||
// assignment -> IDENTIFIER "=" assignment | logicalOr
|
// assignment -> IDENTIFIER "=" assignment | or
|
||||||
func (p *Parser) assignment() Expr {
|
func (p *Parser) assignment() Expr {
|
||||||
expr := p.logicalOr()
|
expr := p.or()
|
||||||
|
|
||||||
if p.match(EQUAL) {
|
if p.match(EQUAL) {
|
||||||
eq := p.previous()
|
eq := p.previous()
|
||||||
|
@ -169,29 +169,28 @@ func (p *Parser) assignment() Expr {
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
// logicalOr -> logicalAnd ( "or" logicalAnd )*
|
// or -> and ( "or" and )*
|
||||||
func (p *Parser) logicalOr() Expr {
|
func (p *Parser) or() Expr {
|
||||||
left := p.logicalAnd()
|
left := p.and()
|
||||||
|
|
||||||
for p.match(OR) {
|
for p.match(OR) {
|
||||||
or := p.previous()
|
or := p.previous()
|
||||||
right := p.logicalAnd()
|
right := p.and()
|
||||||
|
left = &Logical{left, or, right}
|
||||||
left = &LogicalOr{left, or, right}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return left
|
return left
|
||||||
}
|
}
|
||||||
|
|
||||||
// logicalAnd -> equality ( "and" equality )*
|
// and -> equality ( "and" equality )*
|
||||||
func (p *Parser) logicalAnd() Expr {
|
func (p *Parser) and() Expr {
|
||||||
left := p.equality()
|
left := p.equality()
|
||||||
|
|
||||||
for p.match(AND) {
|
for p.match(AND) {
|
||||||
or := p.previous()
|
or := p.previous()
|
||||||
right := p.equality()
|
right := p.equality()
|
||||||
|
|
||||||
left = &LogicalAnd{left, or, right}
|
left = &Logical{left, or, right}
|
||||||
}
|
}
|
||||||
|
|
||||||
return left
|
return left
|
||||||
|
|
10
tests/if.lox
Normal file
10
tests/if.lox
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
var a = 1;
|
||||||
|
var b = 2;
|
||||||
|
|
||||||
|
if (a == b or b - a > 0) print a + b;
|
||||||
|
|
||||||
|
if ( 1 and 2 ) print "and";
|
||||||
|
|
||||||
|
if ( 1 and 2 and 3 and false ) else print "else";
|
||||||
|
|
||||||
|
print nil or "yes";
|
Loading…
Reference in a new issue