Урок 3. Оператор присвоения, переменные

This commit is contained in:
Victor 2015-05-20 14:59:16 +03:00
parent e4a4fb7a92
commit 8a440f00d8
9 changed files with 124 additions and 47 deletions

View File

@ -1,9 +1,10 @@
package com.annimon.ownlang;
import com.annimon.ownlang.lib.Variables;
import com.annimon.ownlang.parser.Lexer;
import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.Statement;
import java.util.List;
/**
@ -12,17 +13,22 @@ import java.util.List;
public final class Main {
public static void main(String[] args) {
final String input1 = "2 + 2";
final String input1 = "word = 2 + 2\nword2 = PI + word";
// final String input2 = "(GOLDEN_RATIO + 2) * #f";
final String input2 = "GOLDEN_RATIO";
final List<Token> tokens = new Lexer(input2).tokenize();
final List<Token> tokens = new Lexer(input1).tokenize();
for (Token token : tokens) {
System.out.println(token);
}
final List<Expression> expressions = new Parser(tokens).parse();
for (Expression expr : expressions) {
System.out.println(expr + " = " + expr.eval());
}
final List<Statement> statements = new Parser(tokens).parse();
for (Statement statement : statements) {
System.out.println(statement);
}
for (Statement statement : statements) {
statement.execute();
}
System.out.printf("%s = %f\n", "word", Variables.get("word"));
System.out.printf("%s = %f\n", "word2", Variables.get("word2"));
}
}

View File

@ -1,30 +0,0 @@
package com.annimon.ownlang.lib;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author aNNiMON
*/
public final class Constants {
private static final Map<String, Double> constants;
static {
constants = new HashMap<>();
constants.put("PI", Math.PI);
constants.put("ПИ", Math.PI);
constants.put("E", Math.E);
constants.put("GOLDEN_RATIO", 1.618);
}
public static boolean isExists(String key) {
return constants.containsKey(key);
}
public static double get(String key) {
if (!isExists(key)) return 0;
return constants.get(key);
}
}

View File

@ -0,0 +1,34 @@
package com.annimon.ownlang.lib;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author aNNiMON
*/
public final class Variables {
private static final Map<String, Double> variables;
static {
variables = new HashMap<>();
variables.put("PI", Math.PI);
variables.put("ПИ", Math.PI);
variables.put("E", Math.E);
variables.put("GOLDEN_RATIO", 1.618);
}
public static boolean isExists(String key) {
return variables.containsKey(key);
}
public static double get(String key) {
if (!isExists(key)) return 0;
return variables.get(key);
}
public static void set(String key, double value) {
variables.put(key, value);
}
}

View File

@ -9,11 +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
};
private final String input;

View File

@ -1,9 +1,11 @@
package com.annimon.ownlang.parser;
import com.annimon.ownlang.parser.ast.AssignmentStatement;
import com.annimon.ownlang.parser.ast.BinaryExpression;
import com.annimon.ownlang.parser.ast.ConstantExpression;
import com.annimon.ownlang.parser.ast.VariabletExpression;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.NumberExpression;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.UnaryExpression;
import java.util.ArrayList;
import java.util.List;
@ -26,14 +28,31 @@ public final class Parser {
size = tokens.size();
}
public List<Expression> parse() {
final List<Expression> result = new ArrayList<>();
public List<Statement> parse() {
final List<Statement> result = new ArrayList<>();
while (!match(TokenType.EOF)) {
result.add(expression());
result.add(statement());
}
return result;
}
private Statement statement() {
return assignmentStatement();
}
private Statement assignmentStatement() {
// WORD EQ
final Token current = get(0);
if (match(TokenType.WORD) && get(0).getType() == TokenType.EQ) {
final String variable = current.getText();
consume(TokenType.EQ);
return new AssignmentStatement(variable, expression());
}
throw new RuntimeException("Unknown statement");
}
private Expression expression() {
return additive();
}
@ -94,7 +113,7 @@ public final class Parser {
return new NumberExpression(Long.parseLong(current.getText(), 16));
}
if (match(TokenType.WORD)) {
return new ConstantExpression(current.getText());
return new VariabletExpression(current.getText());
}
if (match(TokenType.LPAREN)) {
Expression result = expression();
@ -104,6 +123,13 @@ public final class Parser {
throw new RuntimeException("Unknown expression");
}
private Token consume(TokenType type) {
final Token current = get(0);
if (type != current.getType()) throw new RuntimeException("Token " + current + " doesn't match " + type);
pos++;
return current;
}
private boolean match(TokenType type) {
final Token current = get(0);
if (type != current.getType()) return false;

View File

@ -14,6 +14,7 @@ public enum TokenType {
MINUS,
STAR,
SLASH,
EQ,
LPAREN, // (
RPAREN, // )

View File

@ -0,0 +1,29 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Variables;
/**
*
* @author aNNiMON
*/
public final class AssignmentStatement implements Statement {
private final String variable;
private final Expression expression;
public AssignmentStatement(String variable, Expression expression) {
this.variable = variable;
this.expression = expression;
}
@Override
public void execute() {
final double result = expression.eval();
Variables.set(variable, result);
}
@Override
public String toString() {
return String.format("%s = %s", variable, expression);
}
}

View File

@ -0,0 +1,10 @@
package com.annimon.ownlang.parser.ast;
/**
*
* @author aNNiMON
*/
public interface Statement {
void execute();
}

View File

@ -1,23 +1,23 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Constants;
import com.annimon.ownlang.lib.Variables;
/**
*
* @author aNNiMON
*/
public final class ConstantExpression implements Expression {
public final class VariabletExpression implements Expression {
private final String name;
public ConstantExpression(String name) {
public VariabletExpression(String name) {
this.name = name;
}
@Override
public double eval() {
if (!Constants.isExists(name)) throw new RuntimeException("Constant does not exists");
return Constants.get(name);
if (!Variables.isExists(name)) throw new RuntimeException("Constant does not exists");
return Variables.get(name);
}
@Override