115 lines
2.9 KiB
C
115 lines
2.9 KiB
C
#include "parser.h"
|
|
#include "lexer.h"
|
|
#include "utils.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
ParsedExpr* parsed_expr_alloc(const ParsedExpr source)
|
|
{
|
|
ParsedExpr* destination = malloc(sizeof(ParsedExpr));
|
|
*destination = source;
|
|
return destination;
|
|
}
|
|
|
|
void parsed_expr_free(ParsedExpr* expr)
|
|
{
|
|
switch (expr->type) {
|
|
case ParsedExprTypeError:
|
|
free(expr->error.message);
|
|
break;
|
|
case ParsedExprTypeId:
|
|
free(expr->id.value);
|
|
break;
|
|
case ParsedExprTypeInt:
|
|
break;
|
|
default:
|
|
TODO();
|
|
}
|
|
free(expr);
|
|
}
|
|
|
|
ParsedExpr* parsed_error_expr(Position position, const char* message)
|
|
{
|
|
return parsed_expr_alloc((ParsedExpr) {
|
|
.type = ParsedExprTypeError,
|
|
.error = {
|
|
.position = position,
|
|
.message = alloc_cstring(message),
|
|
},
|
|
});
|
|
}
|
|
|
|
void parser_create(Parser* parser, const char* text, Lexer* lexer)
|
|
{
|
|
*parser = (Parser) {
|
|
.text = text,
|
|
.lexer = lexer,
|
|
.current = lexer_next(lexer),
|
|
};
|
|
}
|
|
|
|
ParsedExpr* parser_parse_expression(Parser* parser)
|
|
{
|
|
return parser_parse_operand(parser);
|
|
}
|
|
|
|
ParsedExpr* parser_parse_operand(Parser* parser)
|
|
{
|
|
Token current_token = parser_current(parser);
|
|
if (parser_current_is(parser, TokenTypeId)) {
|
|
AllocatedString string
|
|
= alloc_token_string(parser_current(parser), parser->text);
|
|
return parsed_expr_alloc((ParsedExpr) {
|
|
.type = ParsedExprTypeId,
|
|
.id = {
|
|
.value = string.value,
|
|
.length = string.length,
|
|
},
|
|
});
|
|
} else if (parser_current_is(parser, TokenTypeInt)) {
|
|
char string_value[24] = { 0 };
|
|
strncpy(
|
|
string_value,
|
|
&parser->text[current_token.position.index],
|
|
current_token.length
|
|
);
|
|
int64_t value = strtoll(string_value, NULL, 10);
|
|
return parsed_expr_alloc((ParsedExpr) {
|
|
.type = ParsedExprTypeInt,
|
|
.int_value = value,
|
|
});
|
|
} else {
|
|
parser_step(parser);
|
|
return parsed_expr_alloc((ParsedExpr) {
|
|
.type = ParsedExprTypeError,
|
|
.error = {
|
|
.position = current_token.position,
|
|
.message = alloc_cstring("expected value"),
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
bool parser_current_is(const Parser* parser, TokenType type)
|
|
{
|
|
return !parser_done(parser) && parser_current(parser).type == type;
|
|
}
|
|
|
|
bool parser_done(const Parser* parser)
|
|
{
|
|
return parser->current.type == TokenTypeEof;
|
|
}
|
|
|
|
Token parser_current(const Parser* parser) { return parser->current; }
|
|
|
|
void parser_step(Parser* parser)
|
|
{
|
|
parser->current = lexer_next(parser->lexer);
|
|
}
|
|
|
|
AllocatedString alloc_token_string(Token token, const char* text)
|
|
{
|
|
return alloc_string(&text[token.position.index], token.length);
|
|
}
|