/** * @file * * This file is generated by Propane. */ #pragma once #include #include /************************************************************************** * 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; /** User header code blocks. */ <%= @grammar.code_blocks.fetch("header", "") %> <% if @grammar.ast %> /** 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; <% end %> <% if @grammar.ast %> /** AST node types. @{ */ typedef struct <%= @grammar.ast_prefix %>Token<%= @grammar.ast_suffix %> { <%= @grammar.prefix %>token_t token; <%= @grammar.prefix %>value_t pvalue; } <%= @grammar.ast_prefix %>Token<%= @grammar.ast_suffix %>; <% @parser.rule_sets.each do |name, rule_set| %> <% next if name.start_with?("$") %> <% next if rule_set.optional? %> struct <%= name %>; <% end %> <% @parser.rule_sets.each do |name, rule_set| %> <% next if name.start_with?("$") %> <% next if rule_set.optional? %> typedef struct <%= @grammar.ast_prefix %><%= name %><%= @grammar.ast_suffix %> { <% rule_set.ast_fields.each do |fields| %> union { <% fields.each do |field_name, type| %> struct <%= type %> * <%= field_name %>; <% end %> }; <% end %> } <%= @grammar.ast_prefix %><%= name %><%= @grammar.ast_suffix %>; <% end %> /** @} */ <% end %> /** * A structure to keep track of parser position. * * This is useful for reporting errors, etc... */ typedef struct { /** Input text row (0-based). */ uint32_t row; /** Input text column (0-based). */ uint32_t col; } <%= @grammar.prefix %>position_t; /** Lexed token information. */ typedef struct { /** Text position where the token was found. */ <%= @grammar.prefix %>position_t 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; /** * Lexer and parser context. * * The user must allocate an instance of this structure and pass it to any * public API function. */ typedef struct { /* 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.ast %> <%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * parse_result; <% 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.prefix %>context_t; /************************************************************************** * Public data *************************************************************************/ /** Token names. */ extern const char * <%= @grammar.prefix %>token_names[]; void <%= @grammar.prefix %>context_init(<%= @grammar.prefix %>context_t * context, uint8_t const * input, size_t input_length); 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); <% if @grammar.ast %> <%= @grammar.ast_prefix %><%= @grammar.start_rule %><%= @grammar.ast_suffix %> * <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); <% else %> <%= start_rule_type[1] %> <%= @grammar.prefix %>result(<%= @grammar.prefix %>context_t * context); <% end %> <%= @grammar.prefix %>position_t <%= @grammar.prefix %>position(<%= @grammar.prefix %>context_t * context); size_t <%= @grammar.prefix %>user_terminate_code(<%= @grammar.prefix %>context_t * context); <%= @grammar.prefix %>token_t <%= @grammar.prefix %>token(<%= @grammar.prefix %>context_t * context);