Урок 5. Логические выражения, оператор if/else

This commit is contained in:
Victor 2015-05-28 23:00:52 +03:00
parent c842dd0de3
commit 0feac2a331
7 changed files with 152 additions and 8 deletions

View File

@ -3,4 +3,9 @@ word2 = PI + word
str = "a" * 5 + "ba" * 7 + "\n"
print str * "3" * 2
print "word = " + word + "\n"
print "word2 = " + word2
print "word2 = " + word2 + "\n"
print "1" > "abc"
print "\n"
if (1 < 2) print "1 = 1"
else print "1 != 1"
print "\n"

View File

@ -8,6 +8,10 @@ public final class NumberValue implements Value {
private final double value;
public NumberValue(boolean value) {
this.value = value ? 1 : 0;
}
public NumberValue(double value) {
this.value = value;
}

View File

@ -9,12 +9,12 @@ import java.util.List;
*/
public final class Lexer {
private static final String OPERATOR_CHARS = "+-*/()=";
private static final String OPERATOR_CHARS = "+-*/()=<>";
private static final TokenType[] OPERATOR_TOKENS = {
TokenType.PLUS, TokenType.MINUS,
TokenType.STAR, TokenType.SLASH,
TokenType.LPAREN, TokenType.RPAREN,
TokenType.EQ
TokenType.EQ, TokenType.LT, TokenType.GT
};
private final String input;
@ -98,10 +98,13 @@ public final class Lexer {
}
final String word = buffer.toString();
if (word.equals("print")) {
addToken(TokenType.PRINT);
} else {
addToken(TokenType.WORD, word);
switch (word) {
case "print": addToken(TokenType.PRINT); break;
case "if": addToken(TokenType.IF); break;
case "else": addToken(TokenType.ELSE); break;
default:
addToken(TokenType.WORD, word);
break;
}
}

View File

@ -3,8 +3,10 @@ package com.annimon.ownlang.parser;
import com.annimon.ownlang.parser.ast.PrintStatement;
import com.annimon.ownlang.parser.ast.AssignmentStatement;
import com.annimon.ownlang.parser.ast.BinaryExpression;
import com.annimon.ownlang.parser.ast.ConditionalExpression;
import com.annimon.ownlang.parser.ast.VariabletExpression;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.IfStatement;
import com.annimon.ownlang.parser.ast.ValueExpression;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.UnaryExpression;
@ -41,6 +43,9 @@ public final class Parser {
if (match(TokenType.PRINT)) {
return new PrintStatement(expression());
}
if (match(TokenType.IF)) {
return ifElse();
}
return assignmentStatement();
}
@ -55,10 +60,43 @@ public final class Parser {
throw new RuntimeException("Unknown statement");
}
private Statement ifElse() {
final Expression condition = expression();
final Statement ifStatement = statement();
final Statement elseStatement;
if (match(TokenType.ELSE)) {
elseStatement = statement();
} else {
elseStatement = null;
}
return new IfStatement(condition, ifStatement, elseStatement);
}
private Expression expression() {
return additive();
return conditional();
}
private Expression conditional() {
Expression result = additive();
while (true) {
if (match(TokenType.EQ)) {
result = new ConditionalExpression('=', result, additive());
continue;
}
if (match(TokenType.LT)) {
result = new ConditionalExpression('<', result, additive());
continue;
}
if (match(TokenType.GT)) {
result = new ConditionalExpression('>', result, additive());
continue;
}
break;
}
return result;
}
private Expression additive() {

View File

@ -13,12 +13,16 @@ public enum TokenType {
// keyword
PRINT,
IF,
ELSE,
PLUS,
MINUS,
STAR,
SLASH,
EQ,
LT,
GT,
LPAREN, // (
RPAREN, // )

View File

@ -0,0 +1,53 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Value;
/**
*
* @author aNNiMON
*/
public final class ConditionalExpression implements Expression {
private final Expression expr1, expr2;
private final char operation;
public ConditionalExpression(char operation, Expression expr1, Expression expr2) {
this.operation = operation;
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public Value eval() {
final Value value1 = expr1.eval();
final Value value2 = expr2.eval();
if (value1 instanceof StringValue) {
final String string1 = value1.asString();
final String string2 = value2.asString();
switch (operation) {
case '<': return new NumberValue(string1.compareTo(string2) < 0);
case '>': return new NumberValue(string1.compareTo(string2) > 0);
case '=':
default:
return new NumberValue(string1.equals(string2));
}
}
final double number1 = value1.asNumber();
final double number2 = value2.asNumber();
switch (operation) {
case '<': return new NumberValue(number1 < number2);
case '>': return new NumberValue(number1 > number2);
case '=':
default:
return new NumberValue(number1 == number2);
}
}
@Override
public String toString() {
return String.format("[%s %c %s]", expr1, operation, expr2);
}
}

View File

@ -0,0 +1,37 @@
package com.annimon.ownlang.parser.ast;
/**
*
* @author aNNiMON
*/
public final class IfStatement implements Statement {
private final Expression expression;
private final Statement ifStatement, elseStatement;
public IfStatement(Expression expression, Statement ifStatement, Statement elseStatement) {
this.expression = expression;
this.ifStatement = ifStatement;
this.elseStatement = elseStatement;
}
@Override
public void execute() {
final double result = expression.eval().asNumber();
if (result != 0) {
ifStatement.execute();
} else if (elseStatement != null) {
elseStatement.execute();
}
}
@Override
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("if ").append(expression).append(' ').append(ifStatement);
if (elseStatement != null) {
result.append("\nelse ").append(elseStatement);
}
return result.toString();
}
}