finished parser

This commit is contained in:
SimonFJ20 2023-04-17 02:25:26 +02:00
parent 7fb9cef134
commit d768346178
8 changed files with 815 additions and 15 deletions

View File

@ -3,6 +3,7 @@
#include "common/generic_array.h" #include "common/generic_array.h"
#include "common/string.h" #include "common/string.h"
#include "common/string_array.h"
#include "scirpt/position.h" #include "scirpt/position.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -18,13 +19,20 @@ typedef enum {
ScirptAstExprTypeBool, ScirptAstExprTypeBool,
ScirptAstExprTypeBlock, ScirptAstExprTypeBlock,
ScirptAstExprTypeIf, ScirptAstExprTypeIf,
ScirptAstExprTypeLoop,
ScirptAstExprTypeWhile,
ScirptAstExprTypeFor,
ScirptAstExprTypeMember, ScirptAstExprTypeMember,
ScirptAstExprTypeCall, ScirptAstExprTypeCall,
ScirptAstExprTypeIndex, ScirptAstExprTypeIndex,
ScirptAstExprTypeUnary, ScirptAstExprTypeUnary,
ScirptAstExprTypeBinary, ScirptAstExprTypeBinary,
ScirptAstExprTypeAssign, ScirptAstExprTypeAssign,
ScirptAstExprTypeLambda,
ScirptAstExprTypeFunction,
ScirptAstExprTypeLet, ScirptAstExprTypeLet,
ScirptAstExprTypeReturn,
ScirptAstExprTypeBreak,
} ScirptAstExprType; } ScirptAstExprType;
typedef struct ScirptAstExpr ScirptAstExpr; typedef struct ScirptAstExpr ScirptAstExpr;
@ -41,6 +49,21 @@ typedef struct {
ScirptAstExpr* falsy; ScirptAstExpr* falsy;
} ScirptAstExprIf; } ScirptAstExprIf;
typedef struct {
ScirptAstExpr* body;
} ScirptAstExprLoop;
typedef struct {
ScirptAstExpr* condition;
ScirptAstExpr* body;
} ScirptAstExprWhile;
typedef struct {
HeapString subject;
ScirptAstExpr* value;
ScirptAstExpr* body;
} ScirptAstExprFor;
typedef struct { typedef struct {
ScirptAstExpr* subject; ScirptAstExpr* subject;
HeapString value; HeapString value;
@ -72,12 +95,16 @@ typedef enum {
ScirptAstExprBinaryTypeMultiply, ScirptAstExprBinaryTypeMultiply,
ScirptAstExprBinaryTypeDivide, ScirptAstExprBinaryTypeDivide,
ScirptAstExprBinaryTypeModulo, ScirptAstExprBinaryTypeModulo,
ScirptAstExprBinaryTypeEqual, ScirptAstExprBinaryTypeExponent,
ScirptAstExprBinaryTypeInequal,
ScirptAstExprBinaryTypeLt, ScirptAstExprBinaryTypeLt,
ScirptAstExprBinaryTypeGt, ScirptAstExprBinaryTypeGt,
ScirptAstExprBinaryTypeLtEqual, ScirptAstExprBinaryTypeLtEqual,
ScirptAstExprBinaryTypeGtEqual, ScirptAstExprBinaryTypeGtEqual,
ScirptAstExprBinaryTypeIn,
ScirptAstExprBinaryTypeEqual,
ScirptAstExprBinaryTypeInequal,
ScirptAstExprBinaryTypeAnd,
ScirptAstExprBinaryTypeOr,
} ScirptAstExprBinaryType; } ScirptAstExprBinaryType;
typedef struct { typedef struct {
@ -87,24 +114,45 @@ typedef struct {
} ScirptAstExprBinary; } ScirptAstExprBinary;
typedef enum { typedef enum {
ScirptAstExprAssignTypeAssign, ScirptAstExprAssignTypeEqual,
ScirptAstExprAssignTypeAdd, ScirptAstExprAssignTypeAdd,
ScirptAstExprAssignTypeSubtract, ScirptAstExprAssignTypeSubtract,
ScirptAstExprAssignTypeMultiply, ScirptAstExprAssignTypeMultiply,
ScirptAstExprAssignTypeDivide, ScirptAstExprAssignTypeDivide,
ScirptAstExprAssignTypeModulo, ScirptAstExprAssignTypeModulo,
ScirptAstExprAssignTypeExponent,
} ScirptAstExprAssignType; } ScirptAstExprAssignType;
typedef struct { typedef struct {
ScirptAstExprAssignType type;
ScirptAstExpr* subject; ScirptAstExpr* subject;
ScirptAstExpr* value; ScirptAstExpr* value;
} ScirptAstExprAssign; } ScirptAstExprAssign;
typedef struct {
HeapStringArray params;
ScirptAstExpr* body;
} ScirptAstExprLambda;
typedef struct {
HeapString subject;
HeapStringArray params;
ScirptAstExpr* body;
} ScirptAstExprFunction;
typedef struct { typedef struct {
HeapString subject; HeapString subject;
ScirptAstExpr* value; ScirptAstExpr* value;
} ScirptAstExprLet; } ScirptAstExprLet;
typedef struct {
ScirptAstExpr* value;
} ScirptAstExprReturn;
typedef struct {
ScirptAstExpr* value;
} ScirptAstExprBreak;
struct ScirptAstExpr { struct ScirptAstExpr {
ScirptAstExprType type; ScirptAstExprType type;
ScirptPosition pos; ScirptPosition pos;
@ -116,13 +164,20 @@ struct ScirptAstExpr {
bool bool_value; bool bool_value;
ScirptAstExprBlock block; ScirptAstExprBlock block;
ScirptAstExprIf if_expr; ScirptAstExprIf if_expr;
ScirptAstExprLoop loop;
ScirptAstExprWhile while_expr;
ScirptAstExprFor for_expr;
ScirptAstExprMember member; ScirptAstExprMember member;
ScirptAstExprCall call; ScirptAstExprCall call;
ScirptAstExprIndex index; ScirptAstExprIndex index;
ScirptAstExprUnary unary; ScirptAstExprUnary unary;
ScirptAstExprBinary binary; ScirptAstExprBinary binary;
// assign ScirptAstExprAssign assign;
// let ScirptAstExprLambda lambda;
ScirptAstExprFunction function;
ScirptAstExprLet let;
ScirptAstExprReturn return_statement;
ScirptAstExprBreak break_statement;
}; };
}; };

View File

@ -29,6 +29,8 @@ typedef enum {
ScirptTokenTypeMinusEqual, ScirptTokenTypeMinusEqual,
ScirptTokenTypeAsterisk, ScirptTokenTypeAsterisk,
ScirptTokenTypeAsteriskEqual, ScirptTokenTypeAsteriskEqual,
ScirptTokenTypeAsteriskAsterisk,
ScirptTokenTypeAsteriskAsteriskEqual,
ScirptTokenTypeSlash, ScirptTokenTypeSlash,
ScirptTokenTypeSlashEqual, ScirptTokenTypeSlashEqual,
ScirptTokenTypePercent, ScirptTokenTypePercent,
@ -50,6 +52,7 @@ typedef enum {
ScirptTokenTypeLet, ScirptTokenTypeLet,
ScirptTokenTypeIf, ScirptTokenTypeIf,
ScirptTokenTypeElse, ScirptTokenTypeElse,
ScirptTokenTypeLoop,
ScirptTokenTypeWhile, ScirptTokenTypeWhile,
ScirptTokenTypeFor, ScirptTokenTypeFor,
ScirptTokenTypeIn, ScirptTokenTypeIn,

View File

@ -1,4 +1,6 @@
#include "scirpt/ast.h" #include "scirpt/ast.h"
#include "common/string.h"
#include "common/string_array.h"
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
@ -34,6 +36,18 @@ void scirpt_ast_expr_delete(ScirptAstExpr* expr)
if (expr->if_expr.falsy) if (expr->if_expr.falsy)
scirpt_ast_expr_delete(expr->if_expr.falsy); scirpt_ast_expr_delete(expr->if_expr.falsy);
break; 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: case ScirptAstExprTypeMember:
scirpt_ast_expr_delete(expr->member.subject); scirpt_ast_expr_delete(expr->member.subject);
heapstring_destroy(&expr->member.value); heapstring_destroy(&expr->member.value);
@ -49,12 +63,38 @@ void scirpt_ast_expr_delete(ScirptAstExpr* expr)
scirpt_ast_expr_delete(expr->index.value); scirpt_ast_expr_delete(expr->index.value);
break; break;
case ScirptAstExprTypeUnary: case ScirptAstExprTypeUnary:
scirpt_ast_expr_delete(expr->unary.subject);
break; break;
case ScirptAstExprTypeBinary: case ScirptAstExprTypeBinary:
scirpt_ast_expr_delete(expr->binary.left);
scirpt_ast_expr_delete(expr->binary.right);
break; break;
case ScirptAstExprTypeAssign: 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; break;
case ScirptAstExprTypeLet: 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; break;
} }
} }

View File

@ -60,6 +60,7 @@ void scirpt_lexer_create(
add_keyword(keywords, "let", TT(Let)); add_keyword(keywords, "let", TT(Let));
add_keyword(keywords, "if", TT(If)); add_keyword(keywords, "if", TT(If));
add_keyword(keywords, "else", TT(Else)); add_keyword(keywords, "else", TT(Else));
add_keyword(keywords, "loop", TT(Loop));
add_keyword(keywords, "while", TT(While)); add_keyword(keywords, "while", TT(While));
add_keyword(keywords, "for", TT(For)); add_keyword(keywords, "for", TT(For));
add_keyword(keywords, "in", TT(In)); add_keyword(keywords, "in", TT(In));
@ -177,9 +178,7 @@ ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer)
lexer, TT(Minus), '=', TT(MinusEqual) lexer, TT(Minus), '=', TT(MinusEqual)
); );
case '*': case '*':
return single_or_double_token( return scirpt_lexer_asterisk_token(lexer);
lexer, TT(Asterisk), '=', TT(AsteriskEqual)
);
case '/': case '/':
return single_token(lexer, TT(Slash)); return single_token(lexer, TT(Slash));
case '%': 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) ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer)
{ {

View File

@ -27,6 +27,7 @@ ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_dot_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_dot_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_asterisk_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer); ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer);
void scirpt_lexer_step(ScirptLexer* lexer); void scirpt_lexer_step(ScirptLexer* lexer);
ScirptPosition scirpt_lexer_pos(const ScirptLexer* lexer); ScirptPosition scirpt_lexer_pos(const ScirptLexer* lexer);

View File

@ -9,8 +9,9 @@
int main(void) int main(void)
{ {
const char* text = "if 123 { \"abc\"; abc()() }"; const char* text
printf("= test program = \"\"\"\n%s\n\"\"\"\n", 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"); printf("\n- test lexer\n");

View File

@ -1,10 +1,12 @@
#include "scirpt/parser.h" #include "scirpt/parser.h"
#include "common/string.h" #include "common/string.h"
#include "common/string_array.h"
#include "parser.h" #include "parser.h"
#include "scirpt/ast.h" #include "scirpt/ast.h"
#include "scirpt/lexer.h" #include "scirpt/lexer.h"
#include "scirpt/position.h" #include "scirpt/position.h"
#include "scirpt/token.h" #include "scirpt/token.h"
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -55,6 +57,11 @@ ScirptAstExpr* scirpt_parser_next(ScirptParser* parser)
return alloc_expr((ScirptAstExpr) { return alloc_expr((ScirptAstExpr) {
.type = AET(Eof), .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 { } else {
return scirpt_parser_parse_statement(parser); return scirpt_parser_parse_statement(parser);
} }
@ -94,19 +101,291 @@ void scirpt_parser_destroy(ScirptParser* parser)
ScirptAstExpr* scirpt_parser_parse_statement(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) 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) ScirptAstExpr* scirpt_parser_parse_member_call_index_expr(ScirptParser* parser)
{ {
ScirptPosition pos = parser->current.pos; ScirptPosition pos = parser->current.pos;
ScirptAstExpr* subject = scirpt_parser_parse_operand(parser); ScirptAstExpr* subject = scirpt_parser_parse_operand(parser);
while (true) { while (!done(parser)) {
if (current_is(parser, TT(Dot))) { if (current_is(parser, TT(Dot))) {
step(parser); step(parser);
if (!current_is(parser, TT(Id))) { if (!current_is(parser, TT(Id))) {
@ -248,6 +527,14 @@ ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser)
return scirpt_parser_parse_block(parser); return scirpt_parser_parse_block(parser);
case TT(If): case TT(If):
return scirpt_parser_parse_if(parser); 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): { case TT(Eof): {
error( error(
parser, parser,
@ -295,6 +582,7 @@ ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser)
}); });
} }
default: { default: {
fprintf(stderr, "unhandled token %d\n", parser->current.type);
error( error(
parser, parser,
heapstring_from_cstring("expected value"), heapstring_from_cstring("expected value"),
@ -374,6 +662,8 @@ ScirptAstExpr* scirpt_parser_parse_string(ScirptParser* parser)
static inline bool requires_semicolon(ScirptAstExprType type) static inline bool requires_semicolon(ScirptAstExprType type)
{ {
switch (type) { switch (type) {
case AET(Let):
return true;
default: default:
return false; return false;
} }
@ -396,7 +686,9 @@ ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser)
if (requires_semicolon(statement->type)) { if (requires_semicolon(statement->type)) {
error( error(
parser, parser,
heapstring_from_cstring("';' required"), heapstring_from_cstring(
"expected ';', required for statement"
),
parser->current.pos parser->current.pos
); );
} }
@ -407,7 +699,9 @@ ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser)
error( error(
parser, heapstring_from_cstring("expected '}'"), parser->current.pos 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) { return alloc_expr((ScirptAstExpr) {
.type = AET(Error), .type = AET(Error),
.pos = pos, .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(&params);
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(&params);
return alloc_expr((ScirptAstExpr) {
.type = AET(Error),
});
}
HeapString param = heapstring_from(
&parser->text[parser->current.pos.index], parser->current.length
);
heapstring_array_append(&params, 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(&params.data[i]);
heapstring_array_destroy(&params);
return alloc_expr((ScirptAstExpr) {
.type = AET(Error),
});
}
HeapString param = heapstring_from(
&parser->text[parser->current.pos.index], parser->current.length
);
heapstring_array_append(&params, 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(&params.data[i]);
heapstring_array_destroy(&params);
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(&params.data[i]);
heapstring_array_destroy(&params);
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(&params);
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(&params);
return alloc_expr((ScirptAstExpr) {
.type = AET(Error),
});
}
HeapString param = heapstring_from(
&parser->text[parser->current.pos.index], parser->current.length
);
heapstring_array_append(&params, 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(&params.data[i]);
heapstring_array_destroy(&params);
return alloc_expr((ScirptAstExpr) {
.type = AET(Error),
});
}
HeapString param = heapstring_from(
&parser->text[parser->current.pos.index], parser->current.length
);
heapstring_array_append(&params, 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(&params.data[i]);
heapstring_array_destroy(&params);
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(&params.data[i]);
heapstring_array_destroy(&params);
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( void scirpt_parser_error(
ScirptParser* parser, HeapString message, ScirptPosition pos ScirptParser* parser, HeapString message, ScirptPosition pos
) )

View File

@ -26,13 +26,31 @@ void scirpt_parser_construct(
); );
void scirpt_parser_destroy(ScirptParser* parser); void scirpt_parser_destroy(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_statement(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_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_member_call_index_expr(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_int_or_float(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_int_or_float(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_string(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_string(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser); ScirptAstExpr* scirpt_parser_parse_block(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_if(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( void scirpt_parser_error(
ScirptParser* parser, HeapString message, ScirptPosition pos ScirptParser* parser, HeapString message, ScirptPosition pos
); );