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
|
||||
}
|
||||
|
||||
func (as *AstStringer) visitLogicalOr(l *LogicalOr) any {
|
||||
as.str.WriteString("(or ")
|
||||
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 ")
|
||||
func (as *AstStringer) visitLogical(l *Logical) any {
|
||||
as.str.WriteString(fmt.Sprintf("(%s ", l.operator.lexeme))
|
||||
l.left.accept(as)
|
||||
as.str.WriteString(" ")
|
||||
l.right.accept(as)
|
||||
|
|
24
expr.go
24
expr.go
|
@ -6,9 +6,8 @@ type ExprVisitor interface {
|
|||
visitLiteral(l *Literal) any
|
||||
visitGrouping(g *Grouping) any
|
||||
visitVariable(v *Variable) any
|
||||
visitLogicalOr(l *LogicalOr) any
|
||||
visitLogical(l *Logical) any
|
||||
visitAssignment(a *Assign) any
|
||||
visitLogicalAnd(l *LogicalAnd) any
|
||||
}
|
||||
|
||||
type Expr interface {
|
||||
|
@ -44,15 +43,9 @@ type Assign struct {
|
|||
value Expr
|
||||
}
|
||||
|
||||
type LogicalOr struct {
|
||||
type Logical struct {
|
||||
left Expr
|
||||
or Token
|
||||
right Expr
|
||||
}
|
||||
|
||||
type LogicalAnd struct {
|
||||
left Expr
|
||||
and Token
|
||||
operator Token
|
||||
right Expr
|
||||
}
|
||||
|
||||
|
@ -62,8 +55,7 @@ func (b *Binary) expr() {}
|
|||
func (l *Literal) expr() {}
|
||||
func (g *Grouping) expr() {}
|
||||
func (v *Variable) expr() {}
|
||||
func (l *LogicalOr) expr() {}
|
||||
func (l *LogicalAnd) expr() {}
|
||||
func (l *Logical) expr() {}
|
||||
|
||||
func (u *Unary) accept(v ExprVisitor) any {
|
||||
return v.visitUnary(u)
|
||||
|
@ -89,10 +81,6 @@ func (a *Assign) accept(v ExprVisitor) any {
|
|||
return v.visitAssignment(a)
|
||||
}
|
||||
|
||||
func (l *LogicalOr) accept(v ExprVisitor) any {
|
||||
return v.visitLogicalOr(l)
|
||||
}
|
||||
|
||||
func (l *LogicalAnd) accept(v ExprVisitor) any {
|
||||
return v.visitLogicalAnd(l)
|
||||
func (l *Logical) accept(v ExprVisitor) any {
|
||||
return v.visitLogical(l)
|
||||
}
|
||||
|
|
|
@ -55,16 +55,9 @@ func (as *ExprToRPN) visitAssignment(a *Assign) any {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (as *ExprToRPN) visitLogicalOr(lo *LogicalOr) any {
|
||||
func (as *ExprToRPN) visitLogical(lo *Logical) any {
|
||||
lo.left.accept(as)
|
||||
lo.right.accept(as)
|
||||
as.str.WriteString(" or")
|
||||
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 (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
@ -52,7 +51,7 @@ func (gl *Glox) run(source []byte) {
|
|||
|
||||
stmts, _ := newParser(tokens).parse()
|
||||
|
||||
fmt.Println(AstStringer{stmts: stmts})
|
||||
// fmt.Println(AstStringer{stmts: stmts})
|
||||
|
||||
gl.Interpreter.interpret(stmts)
|
||||
}
|
||||
|
|
|
@ -141,12 +141,18 @@ func (i *Interpreter) visitAssignment(a *Assign) any {
|
|||
return val
|
||||
}
|
||||
|
||||
func (i *Interpreter) visitLogicalOr(lo *LogicalOr) any {
|
||||
return isTruthy(i.evaluate(lo.left)) || isTruthy(i.evaluate(lo.right))
|
||||
func (i *Interpreter) visitLogical(lo *Logical) any {
|
||||
|
||||
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 isTruthy(i.evaluate(la.left)) && isTruthy(i.evaluate(la.right))
|
||||
return i.evaluate(lo.right)
|
||||
}
|
||||
|
||||
func (i *Interpreter) visitPrintStmt(p *PrintStmt) {
|
||||
|
|
21
parser.go
21
parser.go
|
@ -151,9 +151,9 @@ func (p *Parser) expression() Expr {
|
|||
return p.assignment()
|
||||
}
|
||||
|
||||
// assignment -> IDENTIFIER "=" assignment | logicalOr
|
||||
// assignment -> IDENTIFIER "=" assignment | or
|
||||
func (p *Parser) assignment() Expr {
|
||||
expr := p.logicalOr()
|
||||
expr := p.or()
|
||||
|
||||
if p.match(EQUAL) {
|
||||
eq := p.previous()
|
||||
|
@ -169,29 +169,28 @@ func (p *Parser) assignment() Expr {
|
|||
return expr
|
||||
}
|
||||
|
||||
// logicalOr -> logicalAnd ( "or" logicalAnd )*
|
||||
func (p *Parser) logicalOr() Expr {
|
||||
left := p.logicalAnd()
|
||||
// or -> and ( "or" and )*
|
||||
func (p *Parser) or() Expr {
|
||||
left := p.and()
|
||||
|
||||
for p.match(OR) {
|
||||
or := p.previous()
|
||||
right := p.logicalAnd()
|
||||
|
||||
left = &LogicalOr{left, or, right}
|
||||
right := p.and()
|
||||
left = &Logical{left, or, right}
|
||||
}
|
||||
|
||||
return left
|
||||
}
|
||||
|
||||
// logicalAnd -> equality ( "and" equality )*
|
||||
func (p *Parser) logicalAnd() Expr {
|
||||
// and -> equality ( "and" equality )*
|
||||
func (p *Parser) and() Expr {
|
||||
left := p.equality()
|
||||
|
||||
for p.match(AND) {
|
||||
or := p.previous()
|
||||
right := p.equality()
|
||||
|
||||
left = &LogicalAnd{left, or, right}
|
||||
left = &Logical{left, or, right}
|
||||
}
|
||||
|
||||
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