255 lines
8.3 KiB
Plaintext
255 lines
8.3 KiB
Plaintext
/**
|
|
* @file
|
|
*
|
|
* This file is generated by Propane.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
<% if @cpp %>
|
|
#include <vector>
|
|
<% 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);
|