lang: ast: initial implementation of msg handler and selector parsing
This commit is contained in:
@@ -14,6 +14,55 @@ struct class_parser_state {
|
||||
int s_prev_token;
|
||||
};
|
||||
|
||||
static enum ivy_status parse_dollar(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct class_parser_state *state
|
||||
= parser_get_state(ctx, struct class_parser_state);
|
||||
|
||||
if (state->s_current_area != AREA_BODY) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
parser_push_state(ctx, IVY_AST_PROPERTY);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_plus(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct class_parser_state *state
|
||||
= parser_get_state(ctx, struct class_parser_state);
|
||||
|
||||
if (state->s_current_area != AREA_BODY) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
parser_push_state(ctx, IVY_AST_MSGH);
|
||||
struct parser_state *msgh_state = parser_get_state_generic(ctx);
|
||||
struct ivy_ast_msgh_node *msgh
|
||||
= (struct ivy_ast_msgh_node *)msgh_state->s_node;
|
||||
msgh->n_recipient = IVY_AST_MSGH_CLASS;
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_hyphen(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct class_parser_state *state
|
||||
= parser_get_state(ctx, struct class_parser_state);
|
||||
|
||||
if (state->s_current_area != AREA_BODY) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
parser_push_state(ctx, IVY_AST_MSGH);
|
||||
struct parser_state *msgh_state = parser_get_state_generic(ctx);
|
||||
struct ivy_ast_msgh_node *msgh
|
||||
= (struct ivy_ast_msgh_node *)msgh_state->s_node;
|
||||
msgh->n_recipient = IVY_AST_MSGH_OBJECT;
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct class_parser_state *state
|
||||
@@ -96,7 +145,7 @@ static void print(struct ivy_ast_node *node)
|
||||
c->n_ident->t_str);
|
||||
}
|
||||
|
||||
static void init_state(struct parser_state *sp)
|
||||
static void init_state(struct ivy_parser *ctx, struct parser_state *sp)
|
||||
{
|
||||
struct class_parser_state *state = (struct class_parser_state *)sp;
|
||||
state->s_prev_token = IVY_KW_CLASS;
|
||||
@@ -109,6 +158,11 @@ struct ast_node_type class_node_ops = {
|
||||
.n_init_state = init_state,
|
||||
.n_state_size = sizeof(struct class_parser_state),
|
||||
.n_node_size = sizeof(struct ivy_ast_class_node),
|
||||
.n_symbol_parsers = {
|
||||
[IVY_SYM_DOLLAR] = parse_dollar,
|
||||
[IVY_SYM_HYPHEN] = parse_hyphen,
|
||||
[IVY_SYM_PLUS] = parse_plus,
|
||||
},
|
||||
.n_token_parsers = {
|
||||
[IVY_TOK_IDENT] = parse_ident,
|
||||
[IVY_TOK_LINEFEED] = parse_linefeed,
|
||||
|
||||
@@ -94,7 +94,7 @@ struct parser_state *parser_push_state(
|
||||
state->s_node = ast_node_create_with_size(type, node_type->n_node_size);
|
||||
|
||||
if (node_type->n_init_state) {
|
||||
node_type->n_init_state(state);
|
||||
node_type->n_init_state(parser, state);
|
||||
}
|
||||
|
||||
b_queue_push_back(&parser->p_state, &state->s_entry);
|
||||
@@ -134,7 +134,7 @@ struct ivy_ast_node *ivy_parser_dequeue_node(struct ivy_parser *parser)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_first(&parser->p_state);
|
||||
struct parser_state *state = b_unbox(struct parser_state, entry, s_entry);
|
||||
|
||||
|
||||
if (!state) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -146,10 +146,10 @@ struct ivy_ast_node *ivy_parser_dequeue_node(struct ivy_parser *parser)
|
||||
struct ivy_ast_unit_node *unit = (struct ivy_ast_unit_node *)state->s_node;
|
||||
|
||||
entry = b_queue_pop_front(&unit->n_children);
|
||||
|
||||
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return b_unbox(struct ivy_ast_node, entry, n_entry);
|
||||
}
|
||||
}
|
||||
|
||||
75
lang/ast/msgh.c
Normal file
75
lang/ast/msgh.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "ctx.h"
|
||||
#include "ivy/status.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <blue/object/string.h>
|
||||
#include <ivy/lang/lex.h>
|
||||
|
||||
struct msgh_parser_state {
|
||||
struct parser_state s_base;
|
||||
bool s_oneline;
|
||||
|
||||
enum {
|
||||
AREA_SELECTOR,
|
||||
AREA_BODY,
|
||||
} s_current_area;
|
||||
|
||||
unsigned int s_i;
|
||||
unsigned int s_prev;
|
||||
};
|
||||
|
||||
static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct msgh_parser_state *state
|
||||
= parser_get_state(ctx, struct msgh_parser_state);
|
||||
|
||||
struct ivy_ast_msgh_node *msgh
|
||||
= (struct ivy_ast_msgh_node *)state->s_base.s_node;
|
||||
|
||||
if (state->s_current_area == AREA_BODY) {
|
||||
/* TODO expression parsing */
|
||||
return IVY_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (state->s_prev == IVY_SYM_HYPHEN) {
|
||||
/* message name */
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status add_child(
|
||||
struct ivy_ast_node *parent, struct ivy_ast_node *child)
|
||||
{
|
||||
struct ivy_ast_msgh_node *msgh = (struct ivy_ast_msgh_node *)parent;
|
||||
|
||||
if (child->n_type == IVY_AST_SELECTOR && !msgh->n_sel) {
|
||||
msgh->n_sel = (struct ivy_ast_selector_node *)child;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
b_queue_push_back(&msgh->n_body, &child->n_entry);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static void init_state(struct ivy_parser *ctx, struct parser_state *sp)
|
||||
{
|
||||
struct msgh_parser_state *state = (struct msgh_parser_state *)sp;
|
||||
state->s_oneline = false;
|
||||
state->s_i = 0;
|
||||
state->s_current_area = AREA_SELECTOR;
|
||||
state->s_prev = IVY_SYM_HYPHEN;
|
||||
|
||||
parser_push_state(ctx, IVY_AST_SELECTOR);
|
||||
}
|
||||
|
||||
struct ast_node_type msgh_node_ops = {
|
||||
.n_add_child = add_child,
|
||||
.n_init_state = init_state,
|
||||
.n_state_size = sizeof(struct msgh_parser_state),
|
||||
.n_node_size = sizeof(struct ivy_ast_msgh_node),
|
||||
.n_token_parsers = {
|
||||
[IVY_TOK_IDENT] = parse_ident,
|
||||
},
|
||||
};
|
||||
@@ -16,8 +16,9 @@ struct ast_node_type {
|
||||
enum ivy_status (*n_add_child)(
|
||||
struct ivy_ast_node *, struct ivy_ast_node *);
|
||||
void (*n_print)(struct ivy_ast_node *);
|
||||
void (*n_init_state)(struct parser_state *);
|
||||
void (*n_collect_children)(struct ivy_ast_node *, struct ivy_ast_node_iterator *);
|
||||
void (*n_init_state)(struct ivy_parser *, struct parser_state *);
|
||||
void (*n_collect_children)(
|
||||
struct ivy_ast_node *, struct ivy_ast_node_iterator *);
|
||||
|
||||
size_t n_state_size;
|
||||
size_t n_node_size;
|
||||
|
||||
0
lang/ast/property.c
Normal file
0
lang/ast/property.c
Normal file
147
lang/ast/selector.c
Normal file
147
lang/ast/selector.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "ctx.h"
|
||||
#include "ivy/status.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <blue/object/string.h>
|
||||
#include <ivy/lang/lex.h>
|
||||
|
||||
struct selector_parser_state {
|
||||
struct parser_state s_base;
|
||||
unsigned int s_prev;
|
||||
};
|
||||
|
||||
static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (state->s_prev == 0) {
|
||||
/* message name */
|
||||
sel->n_msg_name = tok;
|
||||
state->s_prev = IVY_TOK_IDENT;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
if (state->s_prev == IVY_TOK_LABEL) {
|
||||
/* internal parameter name */
|
||||
b_queue_push_back(&sel->n_arg_names, &tok->t_entry);
|
||||
state->s_prev = IVY_TOK_IDENT;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_label(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (state->s_prev != IVY_TOK_IDENT && state->s_prev != IVY_SYM_LEFT_PAREN) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
b_queue_push_back(&sel->n_arg_labels, &tok->t_entry);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_linefeed(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (!b_queue_empty(&sel->n_arg_labels)
|
||||
&& state->s_prev != IVY_SYM_RIGHT_PAREN) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (state->s_prev != IVY_TOK_IDENT) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_left_paren(
|
||||
struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (state->s_prev != IVY_TOK_IDENT || !b_queue_empty(&sel->n_arg_labels)) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_right_paren(
|
||||
struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (state->s_prev != IVY_TOK_IDENT || !b_queue_empty(&sel->n_arg_labels)) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status parse_pipe(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||
{
|
||||
struct selector_parser_state *state
|
||||
= parser_get_state(ctx, struct selector_parser_state);
|
||||
|
||||
struct ivy_ast_selector_node *sel
|
||||
= (struct ivy_ast_selector_node *)state->s_base.s_node;
|
||||
|
||||
if (!b_queue_empty(&sel->n_arg_labels)
|
||||
&& state->s_prev != IVY_SYM_RIGHT_PAREN) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
if (state->s_prev != IVY_TOK_IDENT) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static void init_state(struct ivy_parser *ctx, struct parser_state *sp)
|
||||
{
|
||||
struct selector_parser_state *state = (struct selector_parser_state *)sp;
|
||||
state->s_prev = 0;
|
||||
}
|
||||
|
||||
struct ast_node_type msgh_node_ops = {
|
||||
.n_init_state = init_state,
|
||||
.n_state_size = sizeof(struct selector_parser_state),
|
||||
.n_node_size = sizeof(struct ivy_ast_selector_node),
|
||||
.n_token_parsers = {
|
||||
[IVY_TOK_IDENT] = parse_ident,
|
||||
[IVY_TOK_LABEL] = parse_label,
|
||||
},
|
||||
.n_symbol_parsers = {
|
||||
[IVY_SYM_LEFT_PAREN] = parse_left_paren,
|
||||
[IVY_SYM_RIGHT_PAREN] = parse_right_paren,
|
||||
[IVY_SYM_PIPE] = parse_pipe,
|
||||
},
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "ctx.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <blue/object/string.h>
|
||||
#include <ivy/lang/lex.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ctx.h"
|
||||
#include "node.h"
|
||||
|
||||
struct unit_import_parser_state {
|
||||
struct parser_state s_base;
|
||||
int s_prev_token;
|
||||
@@ -28,7 +28,8 @@ static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok
|
||||
struct unit_import_parser_state *state
|
||||
= parser_get_state(ctx, struct unit_import_parser_state);
|
||||
|
||||
struct ivy_ast_unit_import_node *node = (struct ivy_ast_unit_import_node *)(state->s_base.s_node);
|
||||
struct ivy_ast_unit_import_node *node
|
||||
= (struct ivy_ast_unit_import_node *)(state->s_base.s_node);
|
||||
|
||||
if (state->s_prev_token == IVY_TOK_IDENT) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
@@ -61,12 +62,14 @@ static enum ivy_status add_child(
|
||||
|
||||
static void print(struct ivy_ast_node *node)
|
||||
{
|
||||
struct ivy_ast_unit_import_node *unit_import = (struct ivy_ast_unit_import_node *)node;
|
||||
struct ivy_ast_unit_import_node *unit_import
|
||||
= (struct ivy_ast_unit_import_node *)node;
|
||||
b_string *str = b_string_create();
|
||||
|
||||
b_queue_iterator it = {0};
|
||||
b_queue_foreach (&it, &unit_import->n_ident) {
|
||||
struct ivy_token *tok = b_unbox(struct ivy_token, it.entry, t_entry);
|
||||
struct ivy_token *tok
|
||||
= b_unbox(struct ivy_token, it.entry, t_entry);
|
||||
|
||||
if (b_string_get_size(str, B_STRLEN_NORMAL) > 0) {
|
||||
b_string_append_cstr(str, ".");
|
||||
@@ -75,11 +78,12 @@ static void print(struct ivy_ast_node *node)
|
||||
b_string_append_cstr(str, tok->t_str);
|
||||
}
|
||||
|
||||
printf("%s(%s)\n", ivy_ast_node_type_to_string(node->n_type), b_string_ptr(str));
|
||||
printf("%s(%s)\n", ivy_ast_node_type_to_string(node->n_type),
|
||||
b_string_ptr(str));
|
||||
b_string_release(str);
|
||||
}
|
||||
|
||||
static void init_state(struct parser_state *sp)
|
||||
static void init_state(struct ivy_parser *ctx, struct parser_state *sp)
|
||||
{
|
||||
struct unit_import_parser_state *state
|
||||
= (struct unit_import_parser_state *)sp;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "ctx.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <blue/object/string.h>
|
||||
#include <ivy/lang/lex.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ctx.h"
|
||||
#include "node.h"
|
||||
|
||||
struct unit_package_parser_state {
|
||||
struct parser_state s_base;
|
||||
int s_prev_token;
|
||||
@@ -28,7 +28,8 @@ static enum ivy_status parse_ident(struct ivy_parser *ctx, struct ivy_token *tok
|
||||
struct unit_package_parser_state *state
|
||||
= parser_get_state(ctx, struct unit_package_parser_state);
|
||||
|
||||
struct ivy_ast_unit_package_node *node = (struct ivy_ast_unit_package_node *)(state->s_base.s_node);
|
||||
struct ivy_ast_unit_package_node *node
|
||||
= (struct ivy_ast_unit_package_node *)(state->s_base.s_node);
|
||||
|
||||
if (state->s_prev_token == IVY_TOK_IDENT) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
@@ -61,12 +62,14 @@ static enum ivy_status add_child(
|
||||
|
||||
static void print(struct ivy_ast_node *node)
|
||||
{
|
||||
struct ivy_ast_unit_package_node *unit_package = (struct ivy_ast_unit_package_node *)node;
|
||||
struct ivy_ast_unit_package_node *unit_package
|
||||
= (struct ivy_ast_unit_package_node *)node;
|
||||
b_string *str = b_string_create();
|
||||
|
||||
b_queue_iterator it = {0};
|
||||
b_queue_foreach (&it, &unit_package->n_ident) {
|
||||
struct ivy_token *tok = b_unbox(struct ivy_token, it.entry, t_entry);
|
||||
struct ivy_token *tok
|
||||
= b_unbox(struct ivy_token, it.entry, t_entry);
|
||||
|
||||
if (b_string_get_size(str, B_STRLEN_NORMAL) > 0) {
|
||||
b_string_append_cstr(str, ".");
|
||||
@@ -75,11 +78,12 @@ static void print(struct ivy_ast_node *node)
|
||||
b_string_append_cstr(str, tok->t_str);
|
||||
}
|
||||
|
||||
printf("%s(%s)\n", ivy_ast_node_type_to_string(node->n_type), b_string_ptr(str));
|
||||
printf("%s(%s)\n", ivy_ast_node_type_to_string(node->n_type),
|
||||
b_string_ptr(str));
|
||||
b_string_release(str);
|
||||
}
|
||||
|
||||
static void init_state(struct parser_state *sp)
|
||||
static void init_state(struct ivy_parser *ctx, struct parser_state *sp)
|
||||
{
|
||||
struct unit_package_parser_state *state
|
||||
= (struct unit_package_parser_state *)sp;
|
||||
|
||||
Reference in New Issue
Block a user