From d768346178b17520ca2c780aa9f189e366088aee Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Mon, 17 Apr 2023 02:25:26 +0200 Subject: [PATCH] finished parser --- include/scirpt/ast.h | 65 +++- include/scirpt/token.h | 3 + scirpt/ast.c | 40 +++ scirpt/lexer.c | 25 +- scirpt/lexer.h | 1 + scirpt/main.c | 5 +- scirpt/parser.c | 673 ++++++++++++++++++++++++++++++++++++++++- scirpt/parser.h | 18 ++ 8 files changed, 815 insertions(+), 15 deletions(-) diff --git a/include/scirpt/ast.h b/include/scirpt/ast.h index ecb0199..ff034dd 100644 --- a/include/scirpt/ast.h +++ b/include/scirpt/ast.h @@ -3,6 +3,7 @@ #include "common/generic_array.h" #include "common/string.h" +#include "common/string_array.h" #include "scirpt/position.h" #include #include @@ -18,13 +19,20 @@ typedef enum { ScirptAstExprTypeBool, ScirptAstExprTypeBlock, ScirptAstExprTypeIf, + ScirptAstExprTypeLoop, + ScirptAstExprTypeWhile, + ScirptAstExprTypeFor, ScirptAstExprTypeMember, ScirptAstExprTypeCall, ScirptAstExprTypeIndex, ScirptAstExprTypeUnary, ScirptAstExprTypeBinary, ScirptAstExprTypeAssign, + ScirptAstExprTypeLambda, + ScirptAstExprTypeFunction, ScirptAstExprTypeLet, + ScirptAstExprTypeReturn, + ScirptAstExprTypeBreak, } ScirptAstExprType; typedef struct ScirptAstExpr ScirptAstExpr; @@ -41,6 +49,21 @@ typedef struct { ScirptAstExpr* falsy; } ScirptAstExprIf; +typedef struct { + ScirptAstExpr* body; +} ScirptAstExprLoop; + +typedef struct { + ScirptAstExpr* condition; + ScirptAstExpr* body; +} ScirptAstExprWhile; + +typedef struct { + HeapString subject; + ScirptAstExpr* value; + ScirptAstExpr* body; +} ScirptAstExprFor; + typedef struct { ScirptAstExpr* subject; HeapString value; @@ -72,12 +95,16 @@ typedef enum { ScirptAstExprBinaryTypeMultiply, ScirptAstExprBinaryTypeDivide, ScirptAstExprBinaryTypeModulo, - ScirptAstExprBinaryTypeEqual, - ScirptAstExprBinaryTypeInequal, + ScirptAstExprBinaryTypeExponent, ScirptAstExprBinaryTypeLt, ScirptAstExprBinaryTypeGt, ScirptAstExprBinaryTypeLtEqual, ScirptAstExprBinaryTypeGtEqual, + ScirptAstExprBinaryTypeIn, + ScirptAstExprBinaryTypeEqual, + ScirptAstExprBinaryTypeInequal, + ScirptAstExprBinaryTypeAnd, + ScirptAstExprBinaryTypeOr, } ScirptAstExprBinaryType; typedef struct { @@ -87,24 +114,45 @@ typedef struct { } ScirptAstExprBinary; typedef enum { - ScirptAstExprAssignTypeAssign, + ScirptAstExprAssignTypeEqual, ScirptAstExprAssignTypeAdd, ScirptAstExprAssignTypeSubtract, ScirptAstExprAssignTypeMultiply, ScirptAstExprAssignTypeDivide, ScirptAstExprAssignTypeModulo, + ScirptAstExprAssignTypeExponent, } ScirptAstExprAssignType; typedef struct { + ScirptAstExprAssignType type; ScirptAstExpr* subject; ScirptAstExpr* value; } ScirptAstExprAssign; +typedef struct { + HeapStringArray params; + ScirptAstExpr* body; +} ScirptAstExprLambda; + +typedef struct { + HeapString subject; + HeapStringArray params; + ScirptAstExpr* body; +} ScirptAstExprFunction; + typedef struct { HeapString subject; ScirptAstExpr* value; } ScirptAstExprLet; +typedef struct { + ScirptAstExpr* value; +} ScirptAstExprReturn; + +typedef struct { + ScirptAstExpr* value; +} ScirptAstExprBreak; + struct ScirptAstExpr { ScirptAstExprType type; ScirptPosition pos; @@ -116,13 +164,20 @@ struct ScirptAstExpr { bool bool_value; ScirptAstExprBlock block; ScirptAstExprIf if_expr; + ScirptAstExprLoop loop; + ScirptAstExprWhile while_expr; + ScirptAstExprFor for_expr; ScirptAstExprMember member; ScirptAstExprCall call; ScirptAstExprIndex index; ScirptAstExprUnary unary; ScirptAstExprBinary binary; - // assign - // let + ScirptAstExprAssign assign; + ScirptAstExprLambda lambda; + ScirptAstExprFunction function; + ScirptAstExprLet let; + ScirptAstExprReturn return_statement; + ScirptAstExprBreak break_statement; }; }; diff --git a/include/scirpt/token.h b/include/scirpt/token.h index 30f8702..b512e03 100644 --- a/include/scirpt/token.h +++ b/include/scirpt/token.h @@ -29,6 +29,8 @@ typedef enum { ScirptTokenTypeMinusEqual, ScirptTokenTypeAsterisk, ScirptTokenTypeAsteriskEqual, + ScirptTokenTypeAsteriskAsterisk, + ScirptTokenTypeAsteriskAsteriskEqual, ScirptTokenTypeSlash, ScirptTokenTypeSlashEqual, ScirptTokenTypePercent, @@ -50,6 +52,7 @@ typedef enum { ScirptTokenTypeLet, ScirptTokenTypeIf, ScirptTokenTypeElse, + ScirptTokenTypeLoop, ScirptTokenTypeWhile, ScirptTokenTypeFor, ScirptTokenTypeIn, diff --git a/scirpt/ast.c b/scirpt/ast.c index 9671ecf..e15ddec 100644 --- a/scirpt/ast.c +++ b/scirpt/ast.c @@ -1,4 +1,6 @@ #include "scirpt/ast.h" +#include "common/string.h" +#include "common/string_array.h" #include #include @@ -34,6 +36,18 @@ void scirpt_ast_expr_delete(ScirptAstExpr* expr) if (expr->if_expr.falsy) scirpt_ast_expr_delete(expr->if_expr.falsy); break; + case ScirptAstExprTypeLoop: + scirpt_ast_expr_delete(expr->loop.body); + break; + case ScirptAstExprTypeWhile: + scirpt_ast_expr_delete(expr->while_expr.condition); + scirpt_ast_expr_delete(expr->while_expr.body); + break; + case ScirptAstExprTypeFor: + heapstring_destroy(&expr->for_expr.subject); + scirpt_ast_expr_delete(expr->for_expr.value); + scirpt_ast_expr_delete(expr->for_expr.body); + break; case ScirptAstExprTypeMember: scirpt_ast_expr_delete(expr->member.subject); heapstring_destroy(&expr->member.value); @@ -49,12 +63,38 @@ void scirpt_ast_expr_delete(ScirptAstExpr* expr) scirpt_ast_expr_delete(expr->index.value); break; case ScirptAstExprTypeUnary: + scirpt_ast_expr_delete(expr->unary.subject); break; case ScirptAstExprTypeBinary: + scirpt_ast_expr_delete(expr->binary.left); + scirpt_ast_expr_delete(expr->binary.right); break; case ScirptAstExprTypeAssign: + scirpt_ast_expr_delete(expr->assign.subject); + scirpt_ast_expr_delete(expr->assign.value); + break; + case ScirptAstExprTypeLambda: + for (size_t i = 0; i < expr->lambda.params.length; ++i) + heapstring_destroy(&expr->lambda.params.data[i]); + heapstring_array_destroy(&expr->lambda.params); + scirpt_ast_expr_delete(expr->lambda.body); + break; + case ScirptAstExprTypeFunction: + heapstring_destroy(&expr->function.subject); + for (size_t i = 0; i < expr->function.params.length; ++i) + heapstring_destroy(&expr->function.params.data[i]); + heapstring_array_destroy(&expr->function.params); + scirpt_ast_expr_delete(expr->function.body); break; case ScirptAstExprTypeLet: + heapstring_destroy(&expr->let.subject); + scirpt_ast_expr_delete(expr->let.value); + break; + case ScirptAstExprTypeReturn: + scirpt_ast_expr_delete(expr->return_statement.value); + break; + case ScirptAstExprTypeBreak: + scirpt_ast_expr_delete(expr->break_statement.value); break; } } diff --git a/scirpt/lexer.c b/scirpt/lexer.c index cd177aa..a5be82c 100644 --- a/scirpt/lexer.c +++ b/scirpt/lexer.c @@ -60,6 +60,7 @@ void scirpt_lexer_create( add_keyword(keywords, "let", TT(Let)); add_keyword(keywords, "if", TT(If)); add_keyword(keywords, "else", TT(Else)); + add_keyword(keywords, "loop", TT(Loop)); add_keyword(keywords, "while", TT(While)); add_keyword(keywords, "for", TT(For)); add_keyword(keywords, "in", TT(In)); @@ -177,9 +178,7 @@ ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer) lexer, TT(Minus), '=', TT(MinusEqual) ); case '*': - return single_or_double_token( - lexer, TT(Asterisk), '=', TT(AsteriskEqual) - ); + return scirpt_lexer_asterisk_token(lexer); case '/': return single_token(lexer, TT(Slash)); case '%': @@ -273,6 +272,26 @@ ScirptToken scirpt_lexer_dot_token(ScirptLexer* lexer) } } +ScirptToken scirpt_lexer_asterisk_token(ScirptLexer* lexer) +{ + ScirptPosition start = pos(lexer); + step(lexer); + if (current_is(lexer, '=')) { + step(lexer); + return token(lexer, TT(AsteriskEqual), start); + } else if (current_is(lexer, '*')) { + step(lexer); + if (current_is(lexer, '=')) { + step(lexer); + return token(lexer, TT(AsteriskAsteriskEqual), start); + } else { + return token(lexer, TT(AsteriskAsterisk), start); + } + } else { + return token(lexer, TT(Asterisk), start); + } +} + ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer) { diff --git a/scirpt/lexer.h b/scirpt/lexer.h index cb14dfa..46057da 100644 --- a/scirpt/lexer.h +++ b/scirpt/lexer.h @@ -27,6 +27,7 @@ ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_dot_token(ScirptLexer* lexer); +ScirptToken scirpt_lexer_asterisk_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer); void scirpt_lexer_step(ScirptLexer* lexer); ScirptPosition scirpt_lexer_pos(const ScirptLexer* lexer); diff --git a/scirpt/main.c b/scirpt/main.c index 50ea603..26177cd 100644 --- a/scirpt/main.c +++ b/scirpt/main.c @@ -9,8 +9,9 @@ int main(void) { - const char* text = "if 123 { \"abc\"; abc()() }"; - printf("= test program = \"\"\"\n%s\n\"\"\"\n", text); + const char* text + = "if 123 { \"abc\"; abc()() }; for a in b { print(123, 123, 123,) }"; + printf("\nprogram = \"\"\"\n%s\n\"\"\"\n", text); { printf("\n- test lexer\n"); diff --git a/scirpt/parser.c b/scirpt/parser.c index 563ecde..fdcf2d8 100644 --- a/scirpt/parser.c +++ b/scirpt/parser.c @@ -1,10 +1,12 @@ #include "scirpt/parser.h" #include "common/string.h" +#include "common/string_array.h" #include "parser.h" #include "scirpt/ast.h" #include "scirpt/lexer.h" #include "scirpt/position.h" #include "scirpt/token.h" +#include #include #include #include @@ -55,6 +57,11 @@ ScirptAstExpr* scirpt_parser_next(ScirptParser* parser) return alloc_expr((ScirptAstExpr) { .type = AET(Eof), }); + } else if (parser->current.type == TT(Semicolon)) { + step(parser); + while (current_is(parser, TT(Semicolon))) + step(parser); + return scirpt_parser_next(parser); } else { return scirpt_parser_parse_statement(parser); } @@ -94,19 +101,291 @@ void scirpt_parser_destroy(ScirptParser* parser) ScirptAstExpr* scirpt_parser_parse_statement(ScirptParser* parser) { - return scirpt_parser_parse_expr(parser); + switch (parser->current.type) { + case TT(If): + return scirpt_parser_parse_if(parser); + case TT(Loop): + return scirpt_parser_parse_loop(parser); + case TT(While): + return scirpt_parser_parse_while(parser); + case TT(For): + return scirpt_parser_parse_for(parser); + case TT(Let): + return scirpt_parser_parse_let(parser); + case TT(Fn): + return scirpt_parser_parse_function(parser); + case TT(Return): + return scirpt_parser_parse_return(parser); + case TT(Break): + return scirpt_parser_parse_break(parser); + default: + return scirpt_parser_parse_assign(parser); + } +} + +static inline ScirptAstExpr* assign( + ScirptAstExprAssignType type, + ScirptAstExpr* subject, + ScirptAstExpr* value, + ScirptPosition pos +) +{ + return alloc_expr((ScirptAstExpr) { + .type = AET(Assign), + .pos = pos, + .assign = (ScirptAstExprAssign) { + .type = type, + .subject = subject, + .value = value, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_assign(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* subject = scirpt_parser_parse_expr(parser); + if (current_is(parser, TT(Equal))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeEqual, subject, value, pos); + } else if (current_is(parser, TT(PlusEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeAdd, subject, value, pos); + } else if (current_is(parser, TT(MinusEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeSubtract, subject, value, pos); + } else if (current_is(parser, TT(AsteriskEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeMultiply, subject, value, pos); + } else if (current_is(parser, TT(SlashEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeDivide, subject, value, pos); + } else if (current_is(parser, TT(PercentEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeModulo, subject, value, pos); + } else if (current_is(parser, TT(AsteriskAsteriskEqual))) { + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return assign(ScirptAstExprAssignTypeExponent, subject, value, pos); + } else { + return subject; + } } ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser) { - return scirpt_parser_parse_member_call_index_expr(parser); + return scirpt_parser_parse_or(parser); +} + +static inline ScirptAstExpr* binary( + ScirptAstExprBinaryType type, + ScirptAstExpr* left, + ScirptAstExpr* right, + ScirptPosition pos +) +{ + return alloc_expr((ScirptAstExpr) { + .type = AET(Binary), + .pos = pos, + .binary = (ScirptAstExprBinary) { + .type = type, + .left = left, + .right = right, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_or(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_and(parser); + while (!done(parser)) { + if (current_is(parser, TT(Or))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_and(parser); + left = binary(ScirptAstExprBinaryTypeOr, left, right, pos); + } else { + break; + } + } + return left; +} + +ScirptAstExpr* scirpt_parser_parse_and(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_equality(parser); + while (!done(parser)) { + if (current_is(parser, TT(And))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_equality(parser); + left = binary(ScirptAstExprBinaryTypeAnd, left, right, pos); + } else { + break; + } + } + return left; +} + +ScirptAstExpr* scirpt_parser_parse_equality(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_comparison(parser); + while (!done(parser)) { + if (current_is(parser, TT(EqualEqual))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_comparison(parser); + left = binary(ScirptAstExprBinaryTypeEqual, left, right, pos); + } else if (current_is(parser, TT(ExclamationEqual))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_comparison(parser); + left = binary(ScirptAstExprBinaryTypeInequal, left, right, pos); + } else { + break; + } + } + return left; +} + +ScirptAstExpr* scirpt_parser_parse_comparison(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_add_subtract(parser); + if (current_is(parser, TT(Lt))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_add_subtract(parser); + return binary(ScirptAstExprBinaryTypeLt, left, right, pos); + } else if (current_is(parser, TT(Gt))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_add_subtract(parser); + return binary(ScirptAstExprBinaryTypeGt, left, right, pos); + } else if (current_is(parser, TT(LtEqual))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_add_subtract(parser); + return binary(ScirptAstExprBinaryTypeLtEqual, left, right, pos); + } else if (current_is(parser, TT(GtEqual))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_add_subtract(parser); + return binary(ScirptAstExprBinaryTypeGtEqual, left, right, pos); + } else if (current_is(parser, TT(In))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_add_subtract(parser); + return binary(ScirptAstExprBinaryTypeIn, left, right, pos); + } else { + return left; + } +} + +ScirptAstExpr* scirpt_parser_parse_add_subtract(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_multiply_divide_modulo(parser); + while (!done(parser)) { + if (current_is(parser, TT(Plus))) { + step(parser); + ScirptAstExpr* right + = scirpt_parser_parse_multiply_divide_modulo(parser); + left = binary(ScirptAstExprBinaryTypeAdd, left, right, pos); + } else if (current_is(parser, TT(Minus))) { + step(parser); + ScirptAstExpr* right + = scirpt_parser_parse_multiply_divide_modulo(parser); + left = binary(ScirptAstExprBinaryTypeSubtract, left, right, pos); + } else { + break; + } + } + return left; +} + +ScirptAstExpr* scirpt_parser_parse_multiply_divide_modulo(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_negate(parser); + while (!done(parser)) { + if (current_is(parser, TT(Asterisk))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_negate(parser); + left = binary(ScirptAstExprBinaryTypeMultiply, left, right, pos); + } else if (current_is(parser, TT(Slash))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_negate(parser); + left = binary(ScirptAstExprBinaryTypeDivide, left, right, pos); + } else if (current_is(parser, TT(Percent))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_negate(parser); + left = binary(ScirptAstExprBinaryTypeModulo, left, right, pos); + } else { + break; + } + } + return left; +} + +static inline ScirptAstExpr* +unary(ScirptAstExprUnaryType type, ScirptAstExpr* subject, ScirptPosition pos) +{ + return alloc_expr((ScirptAstExpr) { + .type = AET(Unary), + .pos = pos, + .unary = (ScirptAstExprUnary) { + .type = type, + .subject = subject, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_negate(ScirptParser* parser) +{ + if (current_is(parser, TT(Minus))) { + ScirptPosition pos = parser->current.pos; + step(parser); + ScirptAstExpr* subject = scirpt_parser_parse_negate(parser); + return unary(ScirptAstExprUnaryTypeNegate, subject, pos); + } else { + return scirpt_parser_parse_exponent(parser); + } +} + +ScirptAstExpr* scirpt_parser_parse_exponent(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + ScirptAstExpr* left = scirpt_parser_parse_unary(parser); + while (!done(parser)) { + if (current_is(parser, TT(AsteriskAsterisk))) { + step(parser); + ScirptAstExpr* right = scirpt_parser_parse_unary(parser); + left = binary(ScirptAstExprBinaryTypeExponent, left, right, pos); + } else { + break; + } + } + return left; +} + +ScirptAstExpr* scirpt_parser_parse_unary(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + if (current_is(parser, TT(Not))) { + step(parser); + ScirptAstExpr* subject = scirpt_parser_parse_unary(parser); + return unary(ScirptAstExprUnaryTypeNot, subject, pos); + } else { + return scirpt_parser_parse_member_call_index_expr(parser); + } } ScirptAstExpr* scirpt_parser_parse_member_call_index_expr(ScirptParser* parser) { ScirptPosition pos = parser->current.pos; ScirptAstExpr* subject = scirpt_parser_parse_operand(parser); - while (true) { + while (!done(parser)) { if (current_is(parser, TT(Dot))) { step(parser); if (!current_is(parser, TT(Id))) { @@ -248,6 +527,14 @@ ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser) return scirpt_parser_parse_block(parser); case TT(If): return scirpt_parser_parse_if(parser); + case TT(Loop): + return scirpt_parser_parse_loop(parser); + case TT(While): + return scirpt_parser_parse_while(parser); + case TT(For): + return scirpt_parser_parse_for(parser); + case TT(Fn): + return scirpt_parser_parse_lambda(parser); case TT(Eof): { error( parser, @@ -295,6 +582,7 @@ ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser) }); } default: { + fprintf(stderr, "unhandled token %d\n", parser->current.type); error( parser, heapstring_from_cstring("expected value"), @@ -374,6 +662,8 @@ ScirptAstExpr* scirpt_parser_parse_string(ScirptParser* parser) static inline bool requires_semicolon(ScirptAstExprType type) { switch (type) { + case AET(Let): + return true; default: return false; } @@ -396,7 +686,9 @@ ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser) if (requires_semicolon(statement->type)) { error( parser, - heapstring_from_cstring("';' required"), + heapstring_from_cstring( + "expected ';', required for statement" + ), parser->current.pos ); } @@ -407,7 +699,9 @@ ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser) error( parser, heapstring_from_cstring("expected '}'"), parser->current.pos ); - // TODO clean up statements + for (size_t i = 0; i < statements.length; ++i) + scirpt_ast_expr_delete(statements.data[i]); + scirpt_ast_expr_array_destroy(&statements); return alloc_expr((ScirptAstExpr) { .type = AET(Error), .pos = pos, @@ -463,6 +757,375 @@ ScirptAstExpr* scirpt_parser_parse_if(ScirptParser* parser) }); } +ScirptAstExpr* scirpt_parser_parse_loop(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + if (!current_is(parser, TT(LBrace))) { + error( + parser, heapstring_from_cstring("expected '{'"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + ScirptAstExpr* body = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(Loop), + .pos = pos, + .loop = (ScirptAstExprLoop) { + .body = body, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_while(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + ScirptAstExpr* condition = scirpt_parser_parse_expr(parser); + if (!current_is(parser, TT(LBrace))) { + error( + parser, heapstring_from_cstring("expected '{'"), parser->current.pos + ); + scirpt_ast_expr_delete(condition); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + ScirptAstExpr* body = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(While), + .pos = pos, + .while_expr = (ScirptAstExprWhile) { + .condition = condition, + .body = body, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_for(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + if (!current_is(parser, TT(Id))) { + error( + parser, heapstring_from_cstring("expected Id"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString subject = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + step(parser); + if (!current_is(parser, TT(In))) { + error( + parser, + heapstring_from_cstring("expected 'in'"), + parser->current.pos + ); + heapstring_destroy(&subject); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + if (!current_is(parser, TT(LBrace))) { + error( + parser, heapstring_from_cstring("expected '{'"), parser->current.pos + ); + heapstring_destroy(&subject); + scirpt_ast_expr_delete(value); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + ScirptAstExpr* body = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(While), + .pos = pos, + .while_expr = (ScirptAstExprWhile) { + .condition = value, + .body = body, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_lambda(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + if (!current_is(parser, TT(LParen))) { + error( + parser, heapstring_from_cstring("expected '('"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + step(parser); + HeapStringArray params; + heapstring_array_construct(¶ms); + if (!done(parser) && parser->current.type == TT(RParen)) { + step(parser); + if (!current_is(parser, TT(Id))) { + error( + parser, + heapstring_from_cstring("expected Id"), + parser->current.pos + ); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString param = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + heapstring_array_append(¶ms, param); + step(parser); + while (current_is(parser, TT(Comma))) { + step(parser); + if (done(parser) || parser->current.type == TT(RParen)) + break; + if (!current_is(parser, TT(Id))) { + error( + parser, + heapstring_from_cstring("expected Id"), + parser->current.pos + ); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString param = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + heapstring_array_append(¶ms, param); + step(parser); + } + } + if (!current_is(parser, TT(RParen))) { + error( + parser, heapstring_from_cstring("expected ')'"), parser->current.pos + ); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + .pos = pos, + }); + } + step(parser); + if (!current_is(parser, TT(LBrace))) { + error( + parser, heapstring_from_cstring("expected '{'"), parser->current.pos + ); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + ScirptAstExpr* body = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(Lambda), + .pos = pos, + .lambda = (ScirptAstExprLambda) { + .params = params, + .body = body, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_function(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + if (!current_is(parser, TT(Id))) { + error( + parser, heapstring_from_cstring("expected Id"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString subject = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + step(parser); + if (!current_is(parser, TT(LParen))) { + error( + parser, heapstring_from_cstring("expected '('"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + step(parser); + HeapStringArray params; + heapstring_array_construct(¶ms); + if (!done(parser) && parser->current.type == TT(RParen)) { + step(parser); + if (!current_is(parser, TT(Id))) { + error( + parser, + heapstring_from_cstring("expected Id"), + parser->current.pos + ); + heapstring_destroy(&subject); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString param = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + heapstring_array_append(¶ms, param); + step(parser); + while (current_is(parser, TT(Comma))) { + step(parser); + if (done(parser) || parser->current.type == TT(RParen)) + break; + if (!current_is(parser, TT(Id))) { + error( + parser, + heapstring_from_cstring("expected Id"), + parser->current.pos + ); + heapstring_destroy(&subject); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString param = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + heapstring_array_append(¶ms, param); + step(parser); + } + } + if (!current_is(parser, TT(RParen))) { + error( + parser, heapstring_from_cstring("expected ')'"), parser->current.pos + ); + heapstring_destroy(&subject); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + .pos = pos, + }); + } + step(parser); + if (!current_is(parser, TT(LBrace))) { + error( + parser, heapstring_from_cstring("expected '{'"), parser->current.pos + ); + heapstring_destroy(&subject); + for (size_t i = 0; i < params.length; ++i) + heapstring_destroy(¶ms.data[i]); + heapstring_array_destroy(¶ms); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + ScirptAstExpr* body = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(Function), + .pos = pos, + .function = (ScirptAstExprFunction) { + .subject = subject, + .params = params, + .body = body, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_let(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + if (!current_is(parser, TT(Id))) { + error( + parser, heapstring_from_cstring("expected Id"), parser->current.pos + ); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + HeapString subject = heapstring_from( + &parser->text[parser->current.pos.index], parser->current.length + ); + step(parser); + if (!current_is(parser, TT(Equal))) { + error( + parser, heapstring_from_cstring("expected '='"), parser->current.pos + ); + heapstring_destroy(&subject); + return alloc_expr((ScirptAstExpr) { + .type = AET(Error), + }); + } + step(parser); + ScirptAstExpr* value = scirpt_parser_parse_expr(parser); + return alloc_expr((ScirptAstExpr) { + .type = AET(Let), + .pos = pos, + .let = (ScirptAstExprLet) { + .subject = subject, + .value = value, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_return(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + ScirptAstExpr* value = NULL; + if (!done(parser) && parser->current.type != TT(Semicolon)) { + value = scirpt_parser_parse_expr(parser); + } + return alloc_expr((ScirptAstExpr) { + .type = AET(Return), + .pos = pos, + .return_statement = (ScirptAstExprReturn) { + .value = value, + }, + }); +} + +ScirptAstExpr* scirpt_parser_parse_break(ScirptParser* parser) +{ + ScirptPosition pos = parser->current.pos; + step(parser); + ScirptAstExpr* value = NULL; + if (!done(parser) && parser->current.type != TT(Semicolon)) { + value = scirpt_parser_parse_expr(parser); + } + return alloc_expr((ScirptAstExpr) { + .type = AET(Break), + .pos = pos, + .break_statement = (ScirptAstExprBreak) { + .value = value, + }, + }); +} + void scirpt_parser_error( ScirptParser* parser, HeapString message, ScirptPosition pos ) diff --git a/scirpt/parser.h b/scirpt/parser.h index a4eb1f1..14a8ba8 100644 --- a/scirpt/parser.h +++ b/scirpt/parser.h @@ -26,13 +26,31 @@ void scirpt_parser_construct( ); void scirpt_parser_destroy(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_statement(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_assign(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_or(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_and(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_equality(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_comparison(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_add_subtract(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_multiply_divide_modulo(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_negate(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_exponent(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_unary(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_member_call_index_expr(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_int_or_float(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_string(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_if(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_loop(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_while(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_for(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_lambda(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_function(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_let(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_return(ScirptParser* parser); +ScirptAstExpr* scirpt_parser_parse_break(ScirptParser* parser); void scirpt_parser_error( ScirptParser* parser, HeapString message, ScirptPosition pos );