diff --git a/src/com/annimon/ownlang/parser/Lexer.java b/src/com/annimon/ownlang/parser/Lexer.java index cb29678..62b4da0 100644 --- a/src/com/annimon/ownlang/parser/Lexer.java +++ b/src/com/annimon/ownlang/parser/Lexer.java @@ -11,7 +11,7 @@ import java.util.Map; */ public final class Lexer { - private static final String OPERATOR_CHARS = "+-*/%()[]{}=<>!&|,^~"; + private static final String OPERATOR_CHARS = "+-*/%()[]{}=<>!&|,^~?:"; private static final Map OPERATORS; static { @@ -33,6 +33,8 @@ public final class Lexer { OPERATORS.put(",", TokenType.COMMA); OPERATORS.put("^", TokenType.CARET); OPERATORS.put("~", TokenType.TILDE); + OPERATORS.put("?", TokenType.QUESTION); + OPERATORS.put(":", TokenType.COLON); OPERATORS.put("!", TokenType.EXCL); OPERATORS.put("&", TokenType.AMP); diff --git a/src/com/annimon/ownlang/parser/Parser.java b/src/com/annimon/ownlang/parser/Parser.java index 1ef8cb9..3e45c6c 100644 --- a/src/com/annimon/ownlang/parser/Parser.java +++ b/src/com/annimon/ownlang/parser/Parser.java @@ -176,7 +176,20 @@ public final class Parser { } private Expression expression() { - return logicalOr(); + return ternary(); + } + + private Expression ternary() { + Expression result = logicalOr(); + + if (match(TokenType.QUESTION)) { + final Expression trueExpr = expression(); + consume(TokenType.COLON); + final Expression falseExpr = expression(); + return new TernaryExpression(result, trueExpr, falseExpr); + } + + return result; } private Expression logicalOr() { diff --git a/src/com/annimon/ownlang/parser/TokenType.java b/src/com/annimon/ownlang/parser/TokenType.java index f5a76ab..7d35816 100644 --- a/src/com/annimon/ownlang/parser/TokenType.java +++ b/src/com/annimon/ownlang/parser/TokenType.java @@ -49,6 +49,9 @@ public enum TokenType { AMP, // & AMPAMP, // && + QUESTION, // ? + COLON, // : + LPAREN, // ( RPAREN, // ) LBRACKET, // [ diff --git a/src/com/annimon/ownlang/parser/ast/TernaryExpression.java b/src/com/annimon/ownlang/parser/ast/TernaryExpression.java new file mode 100644 index 0000000..6d7bcce --- /dev/null +++ b/src/com/annimon/ownlang/parser/ast/TernaryExpression.java @@ -0,0 +1,38 @@ +package com.annimon.ownlang.parser.ast; + +import com.annimon.ownlang.lib.Value; + +/** + * + * @author aNNiMON + */ +public final class TernaryExpression implements Expression { + + public final Expression condition; + public final Expression trueExpr, falseExpr; + + public TernaryExpression(Expression condition, Expression trueExpr, Expression falseExpr) { + this.condition = condition; + this.trueExpr = trueExpr; + this.falseExpr = falseExpr; + } + + @Override + public Value eval() { + if (condition.eval().asNumber() != 0) { + return trueExpr.eval(); + } else { + return falseExpr.eval(); + } + } + + @Override + public void accept(Visitor visitor) { + visitor.visit(this); + } + + @Override + public String toString() { + return String.format("%s ? %s : %s", condition, trueExpr, falseExpr); + } +} diff --git a/src/com/annimon/ownlang/parser/ast/Visitor.java b/src/com/annimon/ownlang/parser/ast/Visitor.java index c9c8851..82aa15f 100644 --- a/src/com/annimon/ownlang/parser/ast/Visitor.java +++ b/src/com/annimon/ownlang/parser/ast/Visitor.java @@ -23,6 +23,7 @@ public interface Visitor { void visit(IfStatement s); void visit(PrintStatement s); void visit(ReturnStatement s); + void visit(TernaryExpression s); void visit(UnaryExpression s); void visit(ValueExpression s); void visit(VariableExpression s); diff --git a/src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java b/src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java index 98f8735..37dd5b4 100644 --- a/src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java +++ b/src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java @@ -110,6 +110,13 @@ public abstract class AbstractVisitor implements Visitor { s.expression.accept(this); } + @Override + public void visit(TernaryExpression s) { + s.condition.accept(this); + s.trueExpr.accept(this); + s.falseExpr.accept(this); + } + @Override public void visit(UnaryExpression s) { s.expr1.accept(this);