wacc/parser.c
2023-03-06 01:47:12 +01:00

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);
}