mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Урок 5. Логические выражения, оператор if/else
This commit is contained in:
parent
c842dd0de3
commit
0feac2a331
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -13,12 +13,16 @@ public enum TokenType {
|
||||
|
||||
// keyword
|
||||
PRINT,
|
||||
IF,
|
||||
ELSE,
|
||||
|
||||
PLUS,
|
||||
MINUS,
|
||||
STAR,
|
||||
SLASH,
|
||||
EQ,
|
||||
LT,
|
||||
GT,
|
||||
|
||||
LPAREN, // (
|
||||
RPAREN, // )
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
37
src/com/annimon/ownlang/parser/ast/IfStatement.java
Normal file
37
src/com/annimon/ownlang/parser/ast/IfStatement.java
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user