finished parser
This commit is contained in:
parent
7fb9cef134
commit
d768346178
@ -3,6 +3,7 @@
|
||||
|
||||
#include "common/generic_array.h"
|
||||
#include "common/string.h"
|
||||
#include "common/string_array.h"
|
||||
#include "scirpt/position.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
40
scirpt/ast.c
40
scirpt/ast.c
@ -1,4 +1,6 @@
|
||||
#include "scirpt/ast.h"
|
||||
#include "common/string.h"
|
||||
#include "common/string_array.h"
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
673
scirpt/parser.c
673
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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user