/** * @file * * This file is generated by Propane. */ #pragma once #include #include <% if @cpp %> #include <% end %> /************************************************************************** * Public types *************************************************************************/ /* Result codes. */ #define <%= @grammar.prefix.upcase %>SUCCESS 0u #define <%= @grammar.prefix.upcase %>DECODE_ERROR 1u #define <%= @grammar.prefix.upcase %>UNEXPECTED_INPUT 2u #define <%= @grammar.prefix.upcase %>UNEXPECTED_TOKEN 3u #define <%= @grammar.prefix.upcase %>DROP 4u #define <%= @grammar.prefix.upcase %>EOF 5u #define <%= @grammar.prefix.upcase %>USER_TERMINATED 6u /** Token type. */ typedef <%= get_type_for(@grammar.terminate_token_id) %> <%= @grammar.prefix %>token_t; /** Token IDs. */ <% @grammar.tokens.each_with_index do |token, index| %> #define TOKEN_<%= token.code_name %> <%= index %>u <% unless token.id == index %> <% raise "Token ID (#{token.id}) does not match index (#{index}) for token #{token.name}!" %> <% end %> <% end %> #define INVALID_TOKEN_ID <%= @grammar.invalid_token_id %>u #define TERMINATE_TOKEN_ID <%= @grammar.terminate_token_id %>u /** Code point type. */ typedef uint32_t <%= @grammar.prefix %>code_point_t; /** * A structure to keep track of input position. * * This is useful for reporting errors, etc... */ typedef struct { /** Input text row (1-based). */ uint32_t row; /** Input text column (1-based). */ uint32_t col; } <%= @grammar.prefix %>position_t; /** Return whether the position is valid. */ #define <%= @grammar.prefix %>position_valid(p) ((p).row != 0u) /** User header code blocks. */ <%= @grammar.code_blocks.fetch("header", "") %> <% if @grammar.tree %> /** Parser values type. */ typedef <%= @grammar.ptype %> <%= @grammar.prefix %>value_t; <% else %> /** Parser values type(s). */ typedef union { <% @grammar.ptypes.each do |name, typestring| %> <%= typestring %> v_<%= name %>; <% end %> } <%= @grammar.prefix %>value_t; /** Parser value constructor(s). */ <% @grammar.ptypes.each do |name, typestring| %> static inline <%= @grammar.prefix %>value_t <%= @grammar.prefix %>value<%= name == "default" ? "" : "_#{name}" %>(<%= typestring %> v) { return (<%= @grammar.prefix %>value_t){.v_<%= name %> = v}; } <% end %> /** Parser value accessor(s). */ <% @grammar.ptypes.each do |name, typestring| %> static inline <%= typestring %> <%= @grammar.prefix %>value_get<%= name == "default" ? "" : "_#{name}" %>(<%= @grammar.prefix %>value_t const * pvalue) { return pvalue->v_<%= name %>; } <% end %> <% end %> <% if @grammar.tree %> /** Tree node ID type (index into the context node arena). ID 0 is null. */ typedef uint32_t <%= @grammar.prefix %>node_id_t; /** * Tree node record. * * All tree nodes are stored contiguously in the context node arena. Child * links are stored in a shared children array: a node's children * occupy children[child_offset .. child_offset + n_fields]. Token payload * fields (token, pvalue, and any user fields) are only meaningful when * is_token is nonzero. */ typedef struct { <%= @grammar.prefix %>position_t position; <%= @grammar.prefix %>position_t end_position; <%= @grammar.prefix %>node_id_t child_offset; uint16_t n_fields; uint8_t is_token; <%= @grammar.prefix %>token_t token; <%= @grammar.prefix %>value_t pvalue; <%= @grammar.token_user_fields %> } <%= @grammar.prefix %>node_data_t; <% end %> /** Lexed token information. */ typedef struct { /** Text position of first code point in token. */ <%= @grammar.prefix %>position_t position; /** Text position of last code point in token. */ <%= @grammar.prefix %>position_t end_position; /** Number of input bytes used by the token. */ size_t length; /** Token that was lexed. */ <%= @grammar.prefix %>token_t token; /** Parser value associated with the token. */ <%= @grammar.prefix %>value_t pvalue; } <%= @grammar.prefix %>token_info_t; typedef struct <%= @grammar.prefix %>context_s <%= @grammar.prefix %>context_t; <% if @grammar.tree %> <%= c_tree_handle_types_header %> <% end %> /** * Lexer and parser context. * * The user must allocate an instance of this structure and pass it to any * public API function. */ struct <%= @grammar.prefix %>context_s { /* Lexer context data. */ /** Input text. */ uint8_t const * input; /** Input text length. */ size_t input_length; /** Input text index (byte offset). */ size_t input_index; /** Input text position (row/column). */ <%= @grammar.prefix %>position_t text_position; /** Current lexer mode. */ size_t mode; /* Parser context data. */ /** Parse result value. */ <% if @grammar.tree %> <%= @grammar.prefix %>node_id_t parse_result; <% if @cpp %> /** Tree node arena. Node ID 0 is reserved as the null node. */ std::vector<<%= @grammar.prefix %>node_data_t> <%= @grammar.prefix %>tree_nodes; /** Shared tree child links. */ std::vector<<%= @grammar.prefix %>node_id_t> <%= @grammar.prefix %>tree_children; <% else %> /** Tree node arena. Node ID 0 is reserved as the null node. */ <%= @grammar.prefix %>node_data_t * <%= @grammar.prefix %>tree_nodes; size_t <%= @grammar.prefix %>tree_nodes_length; size_t <%= @grammar.prefix %>tree_nodes_capacity; /** Shared tree child links. */ <%= @grammar.prefix %>node_id_t * <%= @grammar.prefix %>tree_children; size_t <%= @grammar.prefix %>tree_children_length; size_t <%= @grammar.prefix %>tree_children_capacity; <% end %> <% else %> <%= @grammar.prefix %>value_t parse_result; <% end %> /** Unexpected token received. */ <%= @grammar.prefix %>token_t token; /** User terminate code. */ size_t user_terminate_code; <%= @grammar.context_user_fields %> }; <% if @grammar.tree %> <%= c_tree_types_header %> <% end %> /************************************************************************** * Public data *************************************************************************/ /** Token names. */ extern const char * <%= @grammar.prefix %>token_names[]; <%= @grammar.prefix %>context_t * <%= @grammar.prefix %>context_new(uint8_t const * input, size_t input_length); void <%= @grammar.prefix %>context_delete(<%= @grammar.prefix %>context_t * context); size_t <%= @grammar.prefix %>decode_code_point(uint8_t const * input, size_t input_length, <%= @grammar.prefix %>code_point_t * out_code_point, uint8_t * out_code_point_length); size_t <%= @grammar.prefix %>lex(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>token_info_t * out_token_info); size_t <%= @grammar.prefix %>parse(<%= @grammar.prefix %>context_t * context); <% @grammar.start_rules.each_with_index do |start_rule, i| %> size_t <%= @grammar.prefix %>parse_<%= start_rule %>(<%= @grammar.prefix %>context_t * context); size_t <%= @grammar.prefix %>parse_inner_<%= start_rule %>(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>token_t const * follow_tokens, size_t n_follow_tokens); <% end %> <% if @grammar.tree %> <%= h_type(@grammar.start_rules[0]) %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); <% @grammar.start_rules.each_with_index do |start_rule, i| %> <%= h_type(start_rule) %> <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context); <% end %> <% else %> <%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); <% @grammar.start_rules.each_with_index do |start_rule, i| %> <%= start_rule_type(i)[1] %> <%= @grammar.prefix %>result_<%= start_rule %>(<%= @grammar.prefix %>context_t * context); <% end %> <% end %> <%= @grammar.prefix %>position_t <%= @grammar.prefix %>position(<%= @grammar.prefix %>context_t * context); void <%= @grammar.prefix %>set_position(<%= @grammar.prefix %>context_t * context, <%= @grammar.prefix %>position_t position); size_t <%= @grammar.prefix %>input_index(<%= @grammar.prefix %>context_t * context); void <%= @grammar.prefix %>set_input_index(<%= @grammar.prefix %>context_t * context, size_t input_index); size_t <%= @grammar.prefix %>user_terminate_code(<%= @grammar.prefix %>context_t * context); <%= @grammar.prefix %>token_t <%= @grammar.prefix %>token(<%= @grammar.prefix %>context_t * context);