Statements and State 8
This commit is contained in:
parent
f4338ba51f
commit
e749367886
7 changed files with 250 additions and 69 deletions
|
|
@ -7,21 +7,21 @@ import jlox.tokentype;
|
|||
import jlox.util;
|
||||
import jlox.expr;
|
||||
import jlox.main;
|
||||
import jlox.stmt;
|
||||
|
||||
class Parser{
|
||||
private Token[] tokens;
|
||||
private int current = 0;
|
||||
|
||||
mixin defaultCtor;
|
||||
Expr parse(){
|
||||
try {
|
||||
return expression();
|
||||
} catch (ParseError error) {
|
||||
return null;
|
||||
}
|
||||
Stmt[] parse(){
|
||||
Stmt[] statements;
|
||||
while(!isAtEnd)
|
||||
statements ~= declaration();
|
||||
return statements;
|
||||
}
|
||||
|
||||
private bool isAtEnd() => peek().type == EOF;
|
||||
private bool isAtEnd() => peek().type == TokenType.EOF;
|
||||
private Token peek() => tokens[current];
|
||||
private Token previous() => tokens[current-1];
|
||||
private bool check(TokenType type){
|
||||
|
|
@ -30,7 +30,7 @@ class Parser{
|
|||
return peek().type == type;
|
||||
}
|
||||
private Token advance(){
|
||||
if(!isAtEnd())
|
||||
if(!isAtEnd)
|
||||
current++;
|
||||
return previous();
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ class Parser{
|
|||
}
|
||||
private void synchronize(){
|
||||
advance();
|
||||
with(TokenType) while(!isAtEnd()){
|
||||
with(TokenType) while(!isAtEnd){
|
||||
if(previous().type == SEMICOLON)
|
||||
return;
|
||||
switch(peek().type){
|
||||
|
|
@ -73,15 +73,49 @@ class Parser{
|
|||
case RETURN:
|
||||
return;
|
||||
default:
|
||||
assert(0);
|
||||
/* assert(0); */
|
||||
}
|
||||
advance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Stmt printStatement(){
|
||||
Expr value = expression();
|
||||
consume(TokenType.SEMICOLON, "Expect ';' after value.");
|
||||
return new Stmt.Print(value);
|
||||
}
|
||||
private Stmt expressionStatement(){
|
||||
Expr expr = expression();
|
||||
consume(TokenType.SEMICOLON, "Expect ';' after expression.");
|
||||
return new Stmt.Expression(expr);
|
||||
}
|
||||
private Stmt statement(){
|
||||
if(match(TokenType.LEFT_BRACE))
|
||||
return new Stmt.Block(block());
|
||||
if(match(TokenType.PRINT))
|
||||
return printStatement();
|
||||
return expressionStatement();
|
||||
}
|
||||
private Stmt[] block(){
|
||||
Stmt[] statements;
|
||||
while(!check(TokenType.RIGHT_BRACE) && !isAtEnd)
|
||||
statements ~= declaration();
|
||||
consume(TokenType.RIGHT_BRACE, "Expect '}' after block.");
|
||||
return statements;
|
||||
}
|
||||
private Expr expression(){
|
||||
return equality();
|
||||
return assignment();
|
||||
}
|
||||
private Expr assignment(){
|
||||
Expr expr = equality();
|
||||
if(match(TokenType.EQUAL)){
|
||||
Token equals = previous();
|
||||
Expr value = assignment();
|
||||
if(auto v = cast(Expr.Variable)expr)
|
||||
return new Expr.Assign(v.name, value);
|
||||
error(equals, "Invalid assignment target.");
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
private Expr equality(){
|
||||
Expr expr = comparison();
|
||||
|
|
@ -128,12 +162,14 @@ class Parser{
|
|||
return primary();
|
||||
}
|
||||
private Expr primary(){
|
||||
if(match(TokenType.IDENTIFIER))
|
||||
return new Expr.Variable(previous());
|
||||
if(match(TokenType.FALSE))
|
||||
return new Expr.Literal(false);
|
||||
return new Expr.Literal(TValue.bln(false));
|
||||
if(match(TokenType.TRUE))
|
||||
return new Expr.Literal(true);
|
||||
return new Expr.Literal(TValue.bln(true));
|
||||
if(match(TokenType.NIL))
|
||||
return new Expr.Literal(null);
|
||||
return new Expr.Literal(TValue.nil(0));
|
||||
if(match(TokenType.NUMBER, TokenType.STRING))
|
||||
return new Expr.Literal(previous().literal);
|
||||
if(match(TokenType.LEFT_PAREN)){
|
||||
|
|
@ -142,7 +178,23 @@ class Parser{
|
|||
return new Expr.Grouping(expr);
|
||||
}
|
||||
throw error(peek(), "Expect expression.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
private Stmt varDeclaration(){
|
||||
Token name = consume(TokenType.IDENTIFIER, "Expect variable name.");
|
||||
Expr initializer = null;
|
||||
if(match(TokenType.EQUAL))
|
||||
initializer = expression();
|
||||
consume(TokenType.SEMICOLON, "Expect ';' after variable declaration.");
|
||||
return new Stmt.Var(name, initializer);
|
||||
}
|
||||
private Stmt declaration(){
|
||||
try {
|
||||
if(match(TokenType.VAR))
|
||||
return varDeclaration();
|
||||
return statement();
|
||||
} catch(ParseError error){
|
||||
synchronize();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue