mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Урок 3. Оператор присвоения, переменные
This commit is contained in:
parent
e4a4fb7a92
commit
8a440f00d8
@ -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"));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
34
src/com/annimon/ownlang/lib/Variables.java
Normal file
34
src/com/annimon/ownlang/lib/Variables.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -14,6 +14,7 @@ public enum TokenType {
|
||||
MINUS,
|
||||
STAR,
|
||||
SLASH,
|
||||
EQ,
|
||||
|
||||
LPAREN, // (
|
||||
RPAREN, // )
|
||||
|
29
src/com/annimon/ownlang/parser/ast/AssignmentStatement.java
Normal file
29
src/com/annimon/ownlang/parser/ast/AssignmentStatement.java
Normal 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);
|
||||
}
|
||||
}
|
10
src/com/annimon/ownlang/parser/ast/Statement.java
Normal file
10
src/com/annimon/ownlang/parser/ast/Statement.java
Normal file
@ -0,0 +1,10 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public interface Statement {
|
||||
|
||||
void execute();
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user