Implement reserved operator parsing.
This commit is contained in:
parent
27acfb0be7
commit
c131fbc758
|
@ -14,6 +14,7 @@ enum libab_tree_variant_e {
|
||||||
TREE_ID,
|
TREE_ID,
|
||||||
TREE_NUM,
|
TREE_NUM,
|
||||||
TREE_OP,
|
TREE_OP,
|
||||||
|
TREE_RESERVED_OP,
|
||||||
TREE_UNARY_OP,
|
TREE_UNARY_OP,
|
||||||
TREE_BLOCK,
|
TREE_BLOCK,
|
||||||
TREE_VOID,
|
TREE_VOID,
|
||||||
|
|
|
@ -9,6 +9,7 @@ const char* _debug_node_name(libab_tree_variant var) {
|
||||||
"id",
|
"id",
|
||||||
"num",
|
"num",
|
||||||
"op",
|
"op",
|
||||||
|
"reserved_op",
|
||||||
"unary_op",
|
"unary_op",
|
||||||
"block",
|
"block",
|
||||||
"void",
|
"void",
|
||||||
|
|
47
src/parser.c
47
src/parser.c
|
@ -4,6 +4,7 @@
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "reserved.h"
|
||||||
|
|
||||||
struct parser_state {
|
struct parser_state {
|
||||||
ll_node* current_node;
|
ll_node* current_node;
|
||||||
|
@ -13,6 +14,11 @@ struct parser_state {
|
||||||
libab_table* base_table;
|
libab_table* base_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct operator_data {
|
||||||
|
int associativity;
|
||||||
|
int precedence;
|
||||||
|
};
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
#define PARSE_CHILD(result, state, parse_function, parse_into, into) do {\
|
#define PARSE_CHILD(result, state, parse_function, parse_into, into) do {\
|
||||||
result = parse_function(state, &parse_into);\
|
result = parse_function(state, &parse_into);\
|
||||||
|
@ -703,7 +709,13 @@ libab_result _parser_construct_op(struct parser_state* state, libab_lexer_match*
|
||||||
libab_result result = _parser_construct_node_both(state, match, into);
|
libab_result result = _parser_construct_node_both(state, match, into);
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
(*into)->variant = (match->type == TOKEN_OP_INFIX) ? TREE_OP : TREE_UNARY_OP;
|
if(match->type == TOKEN_OP_INFIX) {
|
||||||
|
(*into)->variant = TREE_OP;
|
||||||
|
} else if(match->type == TOKEN_OP_RESERVED) {
|
||||||
|
(*into)->variant = TREE_RESERVED_OP;
|
||||||
|
} else {
|
||||||
|
(*into)->variant = TREE_UNARY_OP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -728,7 +740,8 @@ libab_result _parser_append_op_node(struct parser_state* state, libab_lexer_matc
|
||||||
int _parser_match_is_op(libab_lexer_match* match) {
|
int _parser_match_is_op(libab_lexer_match* match) {
|
||||||
return match->type == TOKEN_OP_INFIX ||
|
return match->type == TOKEN_OP_INFIX ||
|
||||||
match->type == TOKEN_OP_PREFIX ||
|
match->type == TOKEN_OP_PREFIX ||
|
||||||
match->type == TOKEN_OP_POSTFIX;
|
match->type == TOKEN_OP_POSTFIX ||
|
||||||
|
match->type == TOKEN_OP_RESERVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _parser_pop_brackets(struct parser_state* state, ll* pop_from, ll* push_to, char bracket, int* success) {
|
libab_result _parser_pop_brackets(struct parser_state* state, ll* pop_from, ll* push_to, char bracket, int* success) {
|
||||||
|
@ -765,13 +778,21 @@ int _parser_can_atom_follow(enum parser_expression_type type) {
|
||||||
return !(type == EXPR_CLOSE_PARENTH || type == EXPR_OP_POSTFIX || type == EXPR_ATOM);
|
return !(type == EXPR_CLOSE_PARENTH || type == EXPR_OP_POSTFIX || type == EXPR_ATOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_operator* _parser_find_operator(struct parser_state* state, libab_lexer_match* match) {
|
void _parser_find_operator(struct parser_state* state, libab_lexer_match* match, struct operator_data* data) {
|
||||||
char op_buffer[8];
|
char op_buffer[8];
|
||||||
size_t token_size = match->to - match->from;
|
size_t token_size = match->to - match->from;
|
||||||
size_t buffer_length = (token_size < 7) ? token_size : 7;
|
size_t buffer_length = (token_size < 7) ? token_size : 7;
|
||||||
strncpy(op_buffer, state->string + match->from, buffer_length);
|
strncpy(op_buffer, state->string + match->from, buffer_length);
|
||||||
op_buffer[buffer_length] = '\0';
|
op_buffer[buffer_length] = '\0';
|
||||||
return libab_table_search_operator(state->base_table, op_buffer);
|
if(match->type != TOKEN_OP_RESERVED) {
|
||||||
|
libab_operator* operator = libab_table_search_operator(state->base_table, op_buffer);
|
||||||
|
data->associativity = operator->associativity;
|
||||||
|
data->precedence = operator->precedence;
|
||||||
|
} else {
|
||||||
|
const libab_reserved_operator* operator = libab_find_reserved_operator(op_buffer);
|
||||||
|
data->associativity = operator->associativity;
|
||||||
|
data->precedence = operator->precedence;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _parser_expression_tree(struct parser_state* state, ll* source, libab_tree** into) {
|
libab_result _parser_expression_tree(struct parser_state* state, ll* source, libab_tree** into) {
|
||||||
|
@ -779,7 +800,7 @@ libab_result _parser_expression_tree(struct parser_state* state, ll* source, lib
|
||||||
libab_tree* top = ll_poptail(source);
|
libab_tree* top = ll_poptail(source);
|
||||||
if(top == NULL) {
|
if(top == NULL) {
|
||||||
result = LIBAB_UNEXPECTED;
|
result = LIBAB_UNEXPECTED;
|
||||||
} else if(top->variant == TREE_OP) {
|
} else if(top->variant == TREE_OP || top->variant == TREE_RESERVED_OP) {
|
||||||
libab_tree* left = NULL;
|
libab_tree* left = NULL;
|
||||||
libab_tree* right = NULL;
|
libab_tree* right = NULL;
|
||||||
|
|
||||||
|
@ -828,6 +849,8 @@ libab_result _parser_expression_tree(struct parser_state* state, ll* source, lib
|
||||||
|
|
||||||
libab_result _parse_expression(struct parser_state* state, libab_tree** store_into) {
|
libab_result _parse_expression(struct parser_state* state, libab_tree** store_into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
struct operator_data operator;
|
||||||
|
struct operator_data other_operator;
|
||||||
ll out_stack;
|
ll out_stack;
|
||||||
ll op_stack;
|
ll op_stack;
|
||||||
int pop_success = 0;
|
int pop_success = 0;
|
||||||
|
@ -869,19 +892,19 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
|
||||||
result = _parser_append_op_node(state, new_token, &out_stack);
|
result = _parser_append_op_node(state, new_token, &out_stack);
|
||||||
_parser_state_step(state);
|
_parser_state_step(state);
|
||||||
new_type = EXPR_OP_POSTFIX;
|
new_type = EXPR_OP_POSTFIX;
|
||||||
} else if(new_token->type == TOKEN_OP_INFIX) {
|
} else if(new_token->type == TOKEN_OP_INFIX || new_token->type == TOKEN_OP_RESERVED) {
|
||||||
libab_operator* operator = _parser_find_operator(state, new_token);
|
_parser_find_operator(state, new_token, &operator);
|
||||||
_parser_state_step(state);
|
_parser_state_step(state);
|
||||||
|
|
||||||
while(result == LIBAB_SUCCESS && op_stack.tail &&
|
while(result == LIBAB_SUCCESS && op_stack.tail &&
|
||||||
_parser_match_is_op(op_stack.tail->data)) {
|
_parser_match_is_op(op_stack.tail->data)) {
|
||||||
libab_operator* other_operator = _parser_find_operator(state, op_stack.tail->data);
|
_parser_find_operator(state, op_stack.tail->data, &other_operator);
|
||||||
|
|
||||||
if(new_token->type == TOKEN_OP_PREFIX ||
|
if(new_token->type == TOKEN_OP_PREFIX ||
|
||||||
(operator->associativity == -1 &&
|
(operator.associativity == -1 &&
|
||||||
operator->precedence <= other_operator->precedence) ||
|
operator.precedence <= other_operator.precedence) ||
|
||||||
(operator->associativity == 1 &&
|
(operator.associativity == 1 &&
|
||||||
operator->precedence < other_operator->precedence)) {
|
operator.precedence < other_operator.precedence)) {
|
||||||
libab_lexer_match* match = ll_poptail(&op_stack);
|
libab_lexer_match* match = ll_poptail(&op_stack);
|
||||||
result = _parser_append_op_node(state, match, &out_stack);
|
result = _parser_append_op_node(state, match, &out_stack);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,13 +6,14 @@ int libab_tree_has_vector(libab_tree_variant variant) {
|
||||||
variant == TREE_UNARY_OP || variant == TREE_BLOCK ||
|
variant == TREE_UNARY_OP || variant == TREE_BLOCK ||
|
||||||
variant == TREE_IF || variant == TREE_CALL || variant == TREE_WHILE ||
|
variant == TREE_IF || variant == TREE_CALL || variant == TREE_WHILE ||
|
||||||
variant == TREE_DOWHILE || variant == TREE_FUN ||
|
variant == TREE_DOWHILE || variant == TREE_FUN ||
|
||||||
variant == TREE_RETURN;
|
variant == TREE_RETURN || variant == TREE_RESERVED_OP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libab_tree_has_string(libab_tree_variant variant) {
|
int libab_tree_has_string(libab_tree_variant variant) {
|
||||||
return variant == TREE_ID || variant == TREE_NUM ||
|
return variant == TREE_ID || variant == TREE_NUM ||
|
||||||
variant == TREE_OP || variant == TREE_UNARY_OP ||
|
variant == TREE_OP || variant == TREE_UNARY_OP ||
|
||||||
variant == TREE_FUN || variant == TREE_FUN_PARAM;
|
variant == TREE_FUN || variant == TREE_FUN_PARAM ||
|
||||||
|
variant == TREE_RESERVED_OP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libab_tree_has_type(libab_tree_variant variant) {
|
int libab_tree_has_type(libab_tree_variant variant) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user