#include "ctx.h" #include "interface.h" #include "lex.h" #include "msg.h" #include #define report_error(...) fprintf(stderr, __VA_ARGS__) static bool peek_keyword(struct lex *lex, enum token_keyword kw) { struct token *tok = lex_peek(lex); return (tok && tok->tok_type == TOK_KEYWORD && tok->tok_kw == kw); } static bool parse_keyword(struct lex *lex, enum token_keyword kw) { struct token *tok = lex_peek(lex); if (!tok || tok->tok_type != TOK_KEYWORD || tok->tok_kw != kw) { return false; } lex_advance(lex); return true; } static bool parse_symbol(struct lex *lex, enum token_symbol sym) { struct token *tok = lex_peek(lex); if (!tok || tok->tok_type != TOK_SYMBOL || tok->tok_sym != sym) { return false; } lex_advance(lex); return true; } static bool parse_word(struct lex *lex, char **out) { struct token *tok = lex_peek(lex); if (!tok || tok->tok_type != TOK_WORD) { return false; } *out = tok->tok_str; tok->tok_str = NULL; lex_advance(lex); return true; } static bool parse_int(struct lex *lex, long long *out) { struct token *tok = lex_peek(lex); if (!tok || tok->tok_type != TOK_INT) { return false; } *out = tok->tok_int; lex_advance(lex); return true; } struct msg_definition *parse_msg_definition(struct ctx *ctx, struct lex *lex) { struct msg_definition *msg = NULL; if (!parse_keyword(lex, KW_FUNC)) { report_error("expected `func` keyword\n"); goto fail; } char *msg_name = NULL; if (!parse_word(lex, &msg_name)) { report_error("expected function identifier\n"); goto fail; } long long msg_id = 0; if (!parse_symbol(lex, SYM_LEFT_BRACKET)) { report_error("expected `[` after function identifier\n"); goto fail; } if (!parse_int(lex, &msg_id)) { report_error("expected function id number after `[`\n"); goto fail; } if (!parse_symbol(lex, SYM_RIGHT_BRACKET)) { report_error("expected `]` after function id number\n"); goto fail; } msg = msg_definition_create(msg_name, msg_id); free(msg_name); if (!parse_symbol(lex, SYM_LEFT_PAREN)) { report_error( "expected `(` after function id number specifier\n"); goto fail; } size_t i = 0; bool ok = true; while (ok) { if (parse_symbol(lex, SYM_RIGHT_PAREN)) { break; } if (i > 0 && !parse_symbol(lex, SYM_COMMA)) { report_error( "expected `,` after function " "parameter\n"); ok = false; break; } char *param_name; if (!parse_word(lex, ¶m_name)) { report_error("expected function parameter name\n"); ok = false; break; } if (!parse_symbol(lex, SYM_COLON)) { report_error( "expected `:` after function parameter " "name\n"); ok = false; break; } char *type_name; if (!parse_word(lex, &type_name)) { report_error("expected function parameter type\n"); ok = false; break; } const struct type *type = ctx_get_type(ctx, type_name); if (!type) { report_error( "function parameter has unknown type " "'%s'\n", type_name); free(type_name); ok = false; break; } free(type_name); bool duplicate = msg_definition_has_param(msg, param_name) || msg_definition_has_result(msg, param_name); if (duplicate) { free(param_name); report_error( "function has multiple " "parameters/results with " "name '%s'\n", param_name); ok = false; break; } msg_definition_add_param(msg, type, param_name); free(param_name); i++; } if (!ok) { goto fail; } if (!parse_symbol(lex, SYM_HYPHEN_RIGHT_ANGLE)) { report_error( "expected `->` after function parameter " "list\n"); goto fail; } if (!parse_symbol(lex, SYM_LEFT_PAREN)) { report_error("expected `(` for function results list\n"); goto fail; } i = 0; while (ok) { if (parse_symbol(lex, SYM_RIGHT_PAREN)) { break; } if (i > 0 && !parse_symbol(lex, SYM_COMMA)) { report_error( "expected `,` or `)` after function " "result\n"); ok = false; break; } char *result_name; if (!parse_word(lex, &result_name)) { report_error("expected function parameter name\n"); ok = false; break; } if (!parse_symbol(lex, SYM_COLON)) { report_error( "expected `:` after function result " "name\n"); ok = false; break; } char *type_name; if (!parse_word(lex, &type_name)) { report_error("expected function result type\n"); ok = false; break; } const struct type *type = ctx_get_type(ctx, type_name); if (!type) { report_error( "function result has unknown type " "'%s'\n", type_name); free(type_name); ok = false; break; } free(type_name); bool duplicate = msg_definition_has_param(msg, result_name) || msg_definition_has_result(msg, result_name); if (duplicate) { report_error( "function has multiple " "parameters/results with " "name '%s'\n", result_name); free(result_name); ok = false; break; } msg_definition_add_result(msg, type, result_name); free(result_name); i++; } if (!parse_symbol(lex, SYM_SEMICOLON)) { report_error("expected `;` after function definition\n"); goto fail; } return msg; fail: if (msg) { msg_definition_destroy(msg); } return NULL; } struct interface_definition *parse_interface_definition( struct ctx *ctx, struct lex *lex) { struct interface_definition *iface = NULL; if (!parse_keyword(lex, KW_INTERFACE)) { report_error("expected `interface` keyword"); goto fail; } char *if_name = NULL; if (!parse_word(lex, &if_name)) { report_error("expected interface name"); goto fail; } long long if_id = 0; if (!parse_int(lex, &if_id)) { report_error("expected interface id number"); goto fail; } if (!parse_symbol(lex, SYM_SEMICOLON)) { report_error("expected `;` after interface definition"); goto fail; } iface = interface_definition_create(if_name, if_id); free(if_name); if (!iface) { goto fail; } bool ok = true; while (ok) { if (!lex_peek(lex) && lex_get_status(lex) == ERR_EOF) { break; } if (peek_keyword(lex, KW_FUNC)) { struct msg_definition *msg = parse_msg_definition(ctx, lex); if (!msg) { ok = false; break; } if (interface_definition_has_msg( iface, msg->msg_name)) { msg_definition_destroy(msg); ok = false; break; } interface_definition_add_msg(iface, msg); continue; } report_error("expected eof or function definition\n"); ok = false; break; } if (!ok) { goto fail; } return iface; fail: if (iface) { interface_definition_destroy(iface); } return NULL; }