mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Урок 7. Блок операторов, циклы
This commit is contained in:
parent
b7522f6459
commit
cf98f623b6
13
program.txt
13
program.txt
@ -9,5 +9,16 @@ print "\n"
|
|||||||
if (1 <= 2) print "1 = 1"
|
if (1 <= 2) print "1 = 1"
|
||||||
else print "1 != 1"
|
else print "1 != 1"
|
||||||
print "\n"
|
print "\n"
|
||||||
if (40 < 50 && 50 > 60) print "true"
|
if (40 < 50 || 50 > 60) {
|
||||||
|
print "true1\n"
|
||||||
|
print "true2\n"
|
||||||
|
i = 0
|
||||||
|
while (i < 10) {
|
||||||
|
print "i = " + i + "\n"
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
for i = 0, i < 10, i = i + 1 {
|
||||||
|
print "i = " + i + "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
else print "false"
|
else print "false"
|
@ -22,12 +22,8 @@ public final class Main {
|
|||||||
System.out.println(token);
|
System.out.println(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Statement> statements = new Parser(tokens).parse();
|
final Statement program = new Parser(tokens).parse();
|
||||||
for (Statement statement : statements) {
|
System.out.println(program.toString());
|
||||||
System.out.println(statement);
|
program.execute();
|
||||||
}
|
|
||||||
for (Statement statement : statements) {
|
|
||||||
statement.execute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public final class Lexer {
|
public final class Lexer {
|
||||||
|
|
||||||
private static final String OPERATOR_CHARS = "+-*/()=<>!&|";
|
private static final String OPERATOR_CHARS = "+-*/(){}=<>!&|,";
|
||||||
|
|
||||||
private static final Map<String, TokenType> OPERATORS;
|
private static final Map<String, TokenType> OPERATORS;
|
||||||
static {
|
static {
|
||||||
@ -22,9 +22,12 @@ public final class Lexer {
|
|||||||
OPERATORS.put("/", TokenType.SLASH);
|
OPERATORS.put("/", TokenType.SLASH);
|
||||||
OPERATORS.put("(", TokenType.LPAREN);
|
OPERATORS.put("(", TokenType.LPAREN);
|
||||||
OPERATORS.put(")", TokenType.RPAREN);
|
OPERATORS.put(")", TokenType.RPAREN);
|
||||||
|
OPERATORS.put("{", TokenType.LBRACE);
|
||||||
|
OPERATORS.put("}", TokenType.RBRACE);
|
||||||
OPERATORS.put("=", TokenType.EQ);
|
OPERATORS.put("=", TokenType.EQ);
|
||||||
OPERATORS.put("<", TokenType.LT);
|
OPERATORS.put("<", TokenType.LT);
|
||||||
OPERATORS.put(">", TokenType.GT);
|
OPERATORS.put(">", TokenType.GT);
|
||||||
|
OPERATORS.put(",", TokenType.COMMA);
|
||||||
|
|
||||||
OPERATORS.put("!", TokenType.EXCL);
|
OPERATORS.put("!", TokenType.EXCL);
|
||||||
OPERATORS.put("&", TokenType.AMP);
|
OPERATORS.put("&", TokenType.AMP);
|
||||||
@ -145,6 +148,8 @@ public final class Lexer {
|
|||||||
case "print": addToken(TokenType.PRINT); break;
|
case "print": addToken(TokenType.PRINT); break;
|
||||||
case "if": addToken(TokenType.IF); break;
|
case "if": addToken(TokenType.IF); break;
|
||||||
case "else": addToken(TokenType.ELSE); break;
|
case "else": addToken(TokenType.ELSE); break;
|
||||||
|
case "while": addToken(TokenType.WHILE); break;
|
||||||
|
case "for": addToken(TokenType.FOR); break;
|
||||||
default:
|
default:
|
||||||
addToken(TokenType.WORD, word);
|
addToken(TokenType.WORD, word);
|
||||||
break;
|
break;
|
||||||
|
@ -3,13 +3,16 @@ package com.annimon.ownlang.parser;
|
|||||||
import com.annimon.ownlang.parser.ast.PrintStatement;
|
import com.annimon.ownlang.parser.ast.PrintStatement;
|
||||||
import com.annimon.ownlang.parser.ast.AssignmentStatement;
|
import com.annimon.ownlang.parser.ast.AssignmentStatement;
|
||||||
import com.annimon.ownlang.parser.ast.BinaryExpression;
|
import com.annimon.ownlang.parser.ast.BinaryExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.BlockStatement;
|
||||||
import com.annimon.ownlang.parser.ast.ConditionalExpression;
|
import com.annimon.ownlang.parser.ast.ConditionalExpression;
|
||||||
import com.annimon.ownlang.parser.ast.VariabletExpression;
|
import com.annimon.ownlang.parser.ast.VariabletExpression;
|
||||||
import com.annimon.ownlang.parser.ast.Expression;
|
import com.annimon.ownlang.parser.ast.Expression;
|
||||||
|
import com.annimon.ownlang.parser.ast.ForStatement;
|
||||||
import com.annimon.ownlang.parser.ast.IfStatement;
|
import com.annimon.ownlang.parser.ast.IfStatement;
|
||||||
import com.annimon.ownlang.parser.ast.ValueExpression;
|
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||||
import com.annimon.ownlang.parser.ast.Statement;
|
import com.annimon.ownlang.parser.ast.Statement;
|
||||||
import com.annimon.ownlang.parser.ast.UnaryExpression;
|
import com.annimon.ownlang.parser.ast.UnaryExpression;
|
||||||
|
import com.annimon.ownlang.parser.ast.WhileStatement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -31,14 +34,28 @@ public final class Parser {
|
|||||||
size = tokens.size();
|
size = tokens.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Statement> parse() {
|
public Statement parse() {
|
||||||
final List<Statement> result = new ArrayList<>();
|
final BlockStatement result = new BlockStatement();
|
||||||
while (!match(TokenType.EOF)) {
|
while (!match(TokenType.EOF)) {
|
||||||
result.add(statement());
|
result.add(statement());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Statement block() {
|
||||||
|
final BlockStatement block = new BlockStatement();
|
||||||
|
consume(TokenType.LBRACE);
|
||||||
|
while (!match(TokenType.RBRACE)) {
|
||||||
|
block.add(statement());
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Statement statementOrBlock() {
|
||||||
|
if (get(0).getType() == TokenType.LBRACE) return block();
|
||||||
|
return statement();
|
||||||
|
}
|
||||||
|
|
||||||
private Statement statement() {
|
private Statement statement() {
|
||||||
if (match(TokenType.PRINT)) {
|
if (match(TokenType.PRINT)) {
|
||||||
return new PrintStatement(expression());
|
return new PrintStatement(expression());
|
||||||
@ -46,6 +63,12 @@ public final class Parser {
|
|||||||
if (match(TokenType.IF)) {
|
if (match(TokenType.IF)) {
|
||||||
return ifElse();
|
return ifElse();
|
||||||
}
|
}
|
||||||
|
if (match(TokenType.WHILE)) {
|
||||||
|
return whileStatement();
|
||||||
|
}
|
||||||
|
if (match(TokenType.FOR)) {
|
||||||
|
return forStatement();
|
||||||
|
}
|
||||||
return assignmentStatement();
|
return assignmentStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,16 +85,32 @@ public final class Parser {
|
|||||||
|
|
||||||
private Statement ifElse() {
|
private Statement ifElse() {
|
||||||
final Expression condition = expression();
|
final Expression condition = expression();
|
||||||
final Statement ifStatement = statement();
|
final Statement ifStatement = statementOrBlock();
|
||||||
final Statement elseStatement;
|
final Statement elseStatement;
|
||||||
if (match(TokenType.ELSE)) {
|
if (match(TokenType.ELSE)) {
|
||||||
elseStatement = statement();
|
elseStatement = statementOrBlock();
|
||||||
} else {
|
} else {
|
||||||
elseStatement = null;
|
elseStatement = null;
|
||||||
}
|
}
|
||||||
return new IfStatement(condition, ifStatement, elseStatement);
|
return new IfStatement(condition, ifStatement, elseStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Statement whileStatement() {
|
||||||
|
final Expression condition = expression();
|
||||||
|
final Statement statement = statementOrBlock();
|
||||||
|
return new WhileStatement(condition, statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Statement forStatement() {
|
||||||
|
final Statement initialization = assignmentStatement();
|
||||||
|
consume(TokenType.COMMA);
|
||||||
|
final Expression termination = expression();
|
||||||
|
consume(TokenType.COMMA);
|
||||||
|
final Statement increment = assignmentStatement();
|
||||||
|
final Statement statement = statementOrBlock();
|
||||||
|
return new ForStatement(initialization, termination, increment, statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Expression expression() {
|
private Expression expression() {
|
||||||
return logicalOr();
|
return logicalOr();
|
||||||
|
@ -15,6 +15,8 @@ public enum TokenType {
|
|||||||
PRINT,
|
PRINT,
|
||||||
IF,
|
IF,
|
||||||
ELSE,
|
ELSE,
|
||||||
|
WHILE,
|
||||||
|
FOR,
|
||||||
|
|
||||||
PLUS,
|
PLUS,
|
||||||
MINUS,
|
MINUS,
|
||||||
@ -36,6 +38,9 @@ public enum TokenType {
|
|||||||
|
|
||||||
LPAREN, // (
|
LPAREN, // (
|
||||||
RPAREN, // )
|
RPAREN, // )
|
||||||
|
LBRACE, // {
|
||||||
|
RBRACE, // }
|
||||||
|
COMMA, // ,
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
37
src/com/annimon/ownlang/parser/ast/BlockStatement.java
Normal file
37
src/com/annimon/ownlang/parser/ast/BlockStatement.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package com.annimon.ownlang.parser.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author aNNiMON
|
||||||
|
*/
|
||||||
|
public final class BlockStatement implements Statement {
|
||||||
|
|
||||||
|
private final List<Statement> statements;
|
||||||
|
|
||||||
|
public BlockStatement() {
|
||||||
|
statements = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Statement statement) {
|
||||||
|
statements.add(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
for (Statement statement : statements) {
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder result = new StringBuilder();
|
||||||
|
for (Statement statement : statements) {
|
||||||
|
result.append(statement.toString()).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
32
src/com/annimon/ownlang/parser/ast/ForStatement.java
Normal file
32
src/com/annimon/ownlang/parser/ast/ForStatement.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.annimon.ownlang.parser.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author aNNiMON
|
||||||
|
*/
|
||||||
|
public final class ForStatement implements Statement {
|
||||||
|
|
||||||
|
private final Statement initialization;
|
||||||
|
private final Expression termination;
|
||||||
|
private final Statement increment;
|
||||||
|
private final Statement statement;
|
||||||
|
|
||||||
|
public ForStatement(Statement initialization, Expression termination, Statement increment, Statement block) {
|
||||||
|
this.initialization = initialization;
|
||||||
|
this.termination = termination;
|
||||||
|
this.increment = increment;
|
||||||
|
this.statement = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
for (initialization.execute(); termination.eval().asNumber() != 0; increment.execute()) {
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "for " + initialization + ", " + termination + ", " + increment + " " + statement;
|
||||||
|
}
|
||||||
|
}
|
28
src/com/annimon/ownlang/parser/ast/WhileStatement.java
Normal file
28
src/com/annimon/ownlang/parser/ast/WhileStatement.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package com.annimon.ownlang.parser.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author aNNiMON
|
||||||
|
*/
|
||||||
|
public final class WhileStatement implements Statement {
|
||||||
|
|
||||||
|
private final Expression condition;
|
||||||
|
private final Statement statement;
|
||||||
|
|
||||||
|
public WhileStatement(Expression condition, Statement statement) {
|
||||||
|
this.condition = condition;
|
||||||
|
this.statement = statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
while (condition.eval().asNumber() != 0) {
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "while " + condition + " " + statement;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user