Parsing Expressions 6

This commit is contained in:
nazrin 2025-05-31 15:20:43 +00:00
parent 2de4381fae
commit d937226553
5 changed files with 177 additions and 6 deletions

148
src/jlox/parser.d Normal file
View file

@ -0,0 +1,148 @@
module jlox.parser;
import std.stdio;
import jlox.token;
import jlox.tokentype;
import jlox.util;
import jlox.expr;
import jlox.main : loxError = error;
class Parser{
private Token[] tokens;
private int current = 0;
mixin defaultCtor;
Expr parse(){
try {
return expression();
} catch (ParseError error) {
return null;
}
}
private bool isAtEnd() => peek().type == EOF;
private Token peek() => tokens[current];
private Token previous() => tokens[current-1];
private bool check(TokenType type){
if(isAtEnd)
return false;
return peek().type == type;
}
private Token advance(){
if(!isAtEnd())
current++;
return previous();
}
private bool match(TokenType[] types...){
foreach(TokenType type; types){
if(check(type)){
advance();
return true;
}
}
return false;
}
private Token consume(TokenType type, string message){
if(check(type))
return advance();
throw error(peek(), message);
}
private static class ParseError : Exception {
this(string s){
super(s);
}
}
private ParseError error(Token token, string message){
loxError(token, message);
return new ParseError("hello");
}
private void synchronize(){
advance();
with(TokenType) while(!isAtEnd()){
if(previous().type == SEMICOLON)
return;
switch(peek().type){
case CLASS:
case FUN:
case VAR:
case FOR:
case IF:
case WHILE:
case PRINT:
case RETURN:
return;
default:
assert(0);
}
advance();
}
}
private Expr expression(){
return equality();
}
private Expr equality(){
Expr expr = comparison();
while(match(TokenType.BANG_EQUAL, TokenType.EQUAL_EQUAL)){
Token operator = previous();
Expr right = comparison();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr comparison(){
Expr expr = term();
while(match(TokenType.GREATER, TokenType.GREATER_EQUAL, TokenType.LESS, TokenType.LESS_EQUAL)){
Token operator = previous();
Expr right = term();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr term(){
Expr expr = factor();
while(match(TokenType.MINUS, TokenType.PLUS)){
Token operator = previous();
Expr right = factor();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr factor(){
Expr expr = unary();
while(match(TokenType.SLASH, TokenType.STAR)){
Token operator = previous();
Expr right = unary();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr unary(){
if(match(TokenType.BANG, TokenType.MINUS)){
Token operator = previous();
Expr right = unary();
return new Expr.Unary(operator, right);
}
return primary();
}
private Expr primary(){
if(match(TokenType.FALSE))
return new Expr.Literal(false);
if(match(TokenType.TRUE))
return new Expr.Literal(true);
if(match(TokenType.NIL))
return new Expr.Literal(null);
if(match(TokenType.NUMBER, TokenType.STRING))
return new Expr.Literal(previous().literal);
if(match(TokenType.LEFT_PAREN)){
Expr expr = expression();
consume(TokenType.RIGHT_PAREN, "Expect ')' after expression.");
return new Expr.Grouping(expr);
}
throw error(peek(), "Expect expression.");
assert(0);
}
}