188 lines
5.5 KiB
Plaintext
188 lines
5.5 KiB
Plaintext
/**
|
|
* @file
|
|
*
|
|
* This file is generated by Propane.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
/**************************************************************************
|
|
* 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);
|