finished parser
This commit is contained in:
parent
7fb9cef134
commit
d768346178
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
40
scirpt/ast.c
40
scirpt/ast.c
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
673
scirpt/parser.c
673
scirpt/parser.c
@ -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(¶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(
|
void scirpt_parser_error(
|
||||||
ScirptParser* parser, HeapString message, ScirptPosition pos
|
ScirptParser* parser, HeapString message, ScirptPosition pos
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user