codebased/scirpt/parser.c
2023-04-13 02:29:49 +02:00

161 lines
3.6 KiB
C

#include "scirpt/parser.h"
#include "parser.h"
#include "scirpt/ast.h"
#include "scirpt/lexer.h"
#include "scirpt/position.h"
#include "scirpt/token.h"
#include "utils/string.h"
#include <stdint.h>
#include <stdlib.h>
#define TT(type) ScirptTokenType##type
static inline ScirptAstExpr* alloc_expr(ScirptAstExpr data)
{
ScirptAstExpr* expr = malloc(sizeof(ScirptAstExpr));
*expr = data;
return expr;
}
static inline void
error(ScirptParser* parser, HeapString message, ScirptPosition pos)
{
scirpt_parser_error(parser, message, pos);
}
static inline ScirptPosition pos(ScirptParser* parser)
{
return parser->current.pos;
}
static inline void step(ScirptParser* parser) { scirpt_parser_step(parser); }
static inline bool current_is(const ScirptParser* parser, ScirptTokenType type)
{
return scirpt_parser_current_is(parser, type);
}
static inline bool done(const ScirptParser* parser)
{
return scirpt_parser_done(parser);
}
ScirptParser*
scirpt_parser_new(const char* text, size_t text_length, ScirptLexer* lexer)
{
ScirptParser* parser = malloc(sizeof(ScirptParser));
scirpt_parser_construct(parser, text, text_length, lexer);
return parser;
}
void scirpt_parser_delete(ScirptParser* parser) { free(parser); }
ScirptAstExpr* scirpt_parser_next_expr(ScirptParser* parser)
{
if (done(parser)) {
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeEof,
});
} else {
return scirpt_parser_parse_expr(parser);
}
}
bool scirpt_parser_ok(const ScirptParser* parser) { return parser->ok; }
const ScirptParserErrorArray* scirpt_parser_errors(const ScirptParser* parser)
{
return &parser->errors;
}
void scirpt_parser_construct(
ScirptParser* parser,
const char* text,
size_t text_length,
ScirptLexer* lexer
)
{
ScirptParserErrorArray errors;
scirpt_parser_error_array_construct(&errors);
*parser = (ScirptParser) {
.text = text,
.text_length = text_length,
.lexer = lexer,
.current = scirpt_lexer_next(lexer),
.errors = errors,
.ok = true,
};
}
void scirpt_parser_destroy(ScirptParser* parser)
{
scirpt_parser_error_array_construct(&parser->errors);
}
ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser)
{
return scirpt_parser_parse_operand(parser);
}
ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser)
{
switch (parser->current.type) {
case ScirptTokenTypeInt: {
HeapString value_string = heapstring_from(
&parser->text[pos(parser).index], parser->current.length
);
int64_t value = atoll(value_string.data);
step(parser);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeInt,
.int_value = value,
});
}
case ScirptTokenTypeEof: {
error(
parser,
heapstring_from_cstring("expected value, got Eof"),
pos(parser)
);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeError,
});
}
default: {
error(
parser, heapstring_from_cstring("expected value"), pos(parser)
);
step(parser);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeError,
});
}
}
}
void scirpt_parser_error(
ScirptParser* parser, HeapString message, ScirptPosition pos
)
{
if (parser->ok)
parser->ok = false;
scirpt_parser_error_array_append(
&parser->errors,
(ScirptParserError) {
.message = message,
.pos = pos,
}
);
}
void scirpt_parser_step(ScirptParser* parser)
{
parser->current = scirpt_lexer_next(parser->lexer);
}
bool scirpt_parser_current_is(const ScirptParser* parser, ScirptTokenType type)
{
return parser->current.type == type;
}
bool scirpt_parser_done(const ScirptParser* parser)
{
return parser->current.type == ScirptTokenTypeEof;
}