Урок 7. Блок операторов, циклы

This commit is contained in:
Victor 2015-06-07 16:35:04 +03:00
parent b7522f6459
commit cf98f623b6
8 changed files with 166 additions and 13 deletions

View File

@ -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"

View File

@ -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();
}
} }
} }

View File

@ -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;

View File

@ -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();

View File

@ -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
} }

View 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();
}
}

View 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;
}
}

View 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;
}
}