35 Commits
Author SHA1 Message Date
josh cb914e8bb0 v4.5.0 2026-06-29 23:49:01 -04:00
josh ece95dd7e0 Fix propane.vim keyword detection 2026-06-29 23:48:43 -04:00
josh 232af68081 Attempt to autodetect target language (D/C++) in extra/vim/syntax/propane.vim 2026-06-29 23:02:57 -04:00
josh 23834bef82 Update keyword list in extra/vim/syntax/propane.vim 2026-06-29 23:02:05 -04:00
josh 7b698d7b31 Add noline grammar statement to skip emitting #line directives 2026-06-29 22:41:07 -04:00
josh 45843da0df Fix #line reset directives 2026-06-29 22:21:45 -04:00
josh f27a8688f7 Add CHANGELOG for v4.4.0 2026-06-29 22:15:01 -04:00
josh c459507612 v4.4.0 2026-06-22 23:46:32 -04:00
josh feacbc907d Update gems 2026-06-22 23:46:06 -04:00
josh 5ac3ad1655 Add p_value_get() / p_value_get_XXX() accessors
Allow user code to access specific pvalue values, especially when
multiple ptypes are in use.
2026-06-22 22:12:29 -04:00
josh b641c64425 v4.3.0 2026-05-22 18:16:29 -07:00
josh 5245302f49 Update CHANGELOG for v4.3.0 2026-05-22 18:11:58 -07:00
josh 7a140623ff Use #line for user code blocks to report input grammar position for errors 2026-05-21 16:24:25 -07:00
josh 42035c3a55 Update gems 2026-05-06 08:40:37 -04:00
josh d97f0f8f49 v4.2.0 2026-04-10 18:57:49 -04:00
josh 98e2beb425 Update CHANGELOG for v4.2.0 2026-04-10 18:57:01 -04:00
josh 30565545ee Update gems 2026-04-10 18:52:41 -04:00
josh cd75077959 Update copyright years 2026-04-10 16:36:55 -04:00
josh 51b09a5799 Support custom lex function 2026-04-10 16:36:16 -04:00
josh e992e6344a Update CHANGELOG for v4.1.0 2026-02-28 22:40:55 -05:00
josh a05a55ceb8 v4.1.0 2026-02-28 22:38:40 -05:00
josh e9ecf33f58 Run valgrind on D targets in addition to C and C++ 2026-02-28 21:50:13 -05:00
josh dd687d0299 Add p_context_delete() and p_tree_delete() for D targets 2026-02-28 21:12:35 -05:00
josh d440d0442d Expand token_user_fields unit test 2026-02-22 09:38:42 -05:00
josh f9b4563f94 v4.0.0 2026-02-21 22:43:47 -05:00
josh 334990840e Update README and CHANGELOG for v4.0.0 2026-02-21 22:19:54 -05:00
josh f584389a29 Reorganize Propane Grammar File user guide section 2026-02-21 22:06:09 -05:00
josh de3fb0d120 Combine free_token_user_fields and free_token_node statements 2026-02-21 21:37:23 -05:00
josh d4ad67c23d Allow user to specify custom token node fields 2026-02-21 21:06:40 -05:00
josh ff61dd05d9 Rename p_free_tree() to p_tree_delete() 2026-02-17 19:24:50 -05:00
josh 6fd5186159 Replace p_context_init() with p_context_new()/p_context_delete() 2026-02-17 18:40:33 -05:00
josh 9f2fe6f84b Add token_node and token_user_fields grammar statements 2026-02-14 21:00:53 -05:00
josh 78adf86103 Allow user-defined context fields 2026-02-13 23:53:18 -05:00
josh f4bc719aed Allow drop patterns to execute lexer user code blocks 2026-02-13 20:45:08 -05:00
josh 43c0f50874 Fix UPGRADING.md link in CHANGELOG.md 2026-02-11 00:34:32 -05:00
93 changed files with 2193 additions and 927 deletions

No files matched your search

+57 -2
View File
@@ -1,3 +1,58 @@
## v4.5.0
### New Features
- Add `noline` grammar statement to skip emitting `#line` directives
- Attempt to autodetect target language (D/C++) in extra/vim/syntax/propane.vim
### Fixes
- Fix #line reset directives
- Update keyword list in extra/vim/syntax/propane.vim
- Fix propane.vim keyword detection
## v4.4.0
### New Features
- Add p_value_get() / p_value_get_XXX() accessors
## v4.3.0
### New Features
- Use #line for user code blocks to report input grammar position for errors.
## v4.2.0
### New Features
- Add support for a custom lex function.
## v4.1.0
### New Features
- Add `p_context_delete()` and `p_tree_delete()` for D targets.
## v4.0.0
### New Features
- Add `context_user_fields` statement to allow custom context user fields.
- Add `token_user_fields` statement to allow custom token user fields.
- Add `on_token_node` statement to allow custom code when constructing token nodes.
- Add `free_token_node` statement to allow custom code when freeing token nodes.
- Add `p_context_delete()`.
- Allow `drop` patterns to execute lexer user code blocks.
### Breaking Changes
- Replace `p_context_init()` with `p_context_new()` and `p_context_delete()`.
- Renamed `p_free_tree()` to `p_tree_delete()`.
- The `free_token_node` statement now takes a user code block instead of a
function name parameter.
## v3.0.0 ## v3.0.0
### New Features ### New Features
@@ -12,9 +67,9 @@
- Document `p_lex()` and `p_token_info_t` in user guide (#37) - Document `p_lex()` and `p_token_info_t` in user guide (#37)
### Breaking changes ### Breaking Changes
- Rename AST generation mode to tree generation mode (see [UPGRADING.md]()) - Rename AST generation mode to tree generation mode (see [UPGRADING.md](UPGRADING.md))
## v2.3.0 ## v2.3.0
+5 -5
View File
@@ -5,11 +5,11 @@ GEM
date (3.5.1) date (3.5.1)
diff-lcs (1.6.2) diff-lcs (1.6.2)
docile (1.4.1) docile (1.4.1)
erb (6.0.1) erb (6.0.4)
psych (5.3.1) psych (5.4.0)
date date
stringio stringio
rake (13.3.1) rake (13.4.2)
rdoc (7.2.0) rdoc (7.2.0)
erb erb
psych (>= 4.0.0) psych (>= 4.0.0)
@@ -24,7 +24,7 @@ GEM
rspec-expectations (3.13.5) rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-mocks (3.13.7) rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-support (3.13.7) rspec-support (3.13.7)
@@ -51,4 +51,4 @@ DEPENDENCIES
syntax syntax
BUNDLED WITH BUNDLED WITH
2.3.7 4.0.14
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2010-2024 Josh Holtrop Copyright (c) 2010-2026 Josh Holtrop
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+15 -1
View File
@@ -1,6 +1,20 @@
## v4.0.0
### API Changes
- Replace any calls to `p_context_init()` with `p_context_new()`.
- Replace any references to the address of a statically allocated context
structure with the pointer returned from `p_context_init()` (e.g. `&context`
-> `context`).
- Add a call to `p_context_delete()` (for C or C++) after lexing/parsing to
reclaim context memory.
- Rename `p_free_tree()` calls to `p_tree_delete()`.
- Change `free_token_node` statement calls from taking a function name argument
to taking a user code block.
## v3.0.0 ## v3.0.0
### Grammar changes ### Grammar Changes
- Rename `ast;` statement to `tree;`. - Rename `ast;` statement to `tree;`.
- Rename `ast_prefix;` statement to `tree_prefix;`. - Rename `ast_prefix;` statement to `tree_prefix;`.
+57 -25
View File
@@ -43,30 +43,52 @@ const char * <%= @grammar.prefix %>token_names[] = {
*************************************************************************/ *************************************************************************/
/** /**
* Initialize lexer/parser context structure. * Allocate and initialize lexer/parser context structure.
*
* Deinitialize and deallocate with <%= @grammar.prefix %>context_delete().
* *
* @param[out] context
* Lexer/parser context structure.
* @param input * @param input
* Text input. * Text input.
* @param input_length * @param input_length
* Text input length. * Text input length.
*
* @return Context structure for lexer/parser.
*/ */
void <%= @grammar.prefix %>context_init(<%= @grammar.prefix %>context_t * context, uint8_t const * input, size_t input_length) <%= @grammar.prefix %>context_t * <%= @grammar.prefix %>context_new(uint8_t const * input, size_t input_length)
{ {
/* New default-initialized context structure. */ <% if @cpp %>
<%= @grammar.prefix %>context_t newcontext; <%= @grammar.prefix %>context_t * context = new <%= @grammar.prefix %>context_t();
memset(&newcontext, 0, sizeof(newcontext)); <% else %>
<%= @grammar.prefix %>context_t * context = (<%= @grammar.prefix %>context_t *)calloc(1, sizeof(<%= @grammar.prefix %>context_t));
<% end %>
/* Lexer initialization. */ /* Lexer initialization. */
newcontext.input = input; context->input = input;
newcontext.input_length = input_length; context->input_length = input_length;
newcontext.text_position.row = 1u; context->text_position.row = 1u;
newcontext.text_position.col = 1u; context->text_position.col = 1u;
newcontext.mode = <%= @lexer.mode_id("default") %>; context->mode = <%= @lexer.mode_id("default") %>;
/* Copy to the user's context structure. */ return context;
*context = newcontext; }
/**
* Deinitialize and deallocate lexer/parser context structure.
*
* For C++, destructors will be called for any context user fields. However, if
* pointers are used to store allocated resources, the user should free them
* before calling this function.
*
* @param context
* Lexer/parser context structure allocated with <%= @grammar.prefix %>context_new().
*/
void <%= @grammar.prefix %>context_delete(<%= @grammar.prefix %>context_t * context)
{
<% if @cpp %>
delete context;
<% else %>
free(context);
<% end %>
} }
/************************************************************************** /**************************************************************************
@@ -694,6 +716,7 @@ typedef struct
<% end %> <% end %>
} state_value_t; } state_value_t;
<% if @grammar.tree %>
/** Common tree node structure. */ /** Common tree node structure. */
typedef struct TreeNode_s typedef struct TreeNode_s
{ {
@@ -703,6 +726,7 @@ typedef struct TreeNode_s
uint8_t is_token; uint8_t is_token;
struct TreeNode_s * fields[]; struct TreeNode_s * fields[];
} TreeNode; } TreeNode;
<% end %>
/** Parser shift table. */ /** Parser shift table. */
static const shift_t parser_shift_table[] = { static const shift_t parser_shift_table[] = {
@@ -957,7 +981,7 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
{ {
if (token == INVALID_TOKEN_ID) if (token == INVALID_TOKEN_ID)
{ {
size_t lexer_result = <%= @grammar.prefix %>lex(context, &token_info); size_t lexer_result = <%= lex_fn %>(context, &token_info);
if (lexer_result != P_SUCCESS) if (lexer_result != P_SUCCESS)
{ {
result = lexer_result; result = lexer_result;
@@ -994,13 +1018,18 @@ static size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t start
{ {
/* We shifted a token, mark it consumed. */ /* We shifted a token, mark it consumed. */
<% if @grammar.tree %> <% if @grammar.tree %>
<% if @cpp %>
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = new <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>();
<% else %>
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = (<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *)malloc(sizeof(<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>)); <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = (<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *)malloc(sizeof(<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>));
<% end %>
token_tree_node->position = token_info.position; token_tree_node->position = token_info.position;
token_tree_node->end_position = token_info.end_position; token_tree_node->end_position = token_info.end_position;
token_tree_node->n_fields = 0u; token_tree_node->n_fields = 0u;
token_tree_node->is_token = 1u; token_tree_node->is_token = 1u;
token_tree_node->token = token; token_tree_node->token = token;
token_tree_node->pvalue = token_info.pvalue; token_tree_node->pvalue = token_info.pvalue;
<%= expand_code(@grammar.on_token_node, false, nil, nil) %>
state_values_stack_index(&statevalues, -1)->tree_node = token_tree_node; state_values_stack_index(&statevalues, -1)->tree_node = token_tree_node;
<% else %> <% else %>
state_values_stack_index(&statevalues, -1)->pvalue = token_info.pvalue; state_values_stack_index(&statevalues, -1)->pvalue = token_info.pvalue;
@@ -1186,14 +1215,17 @@ size_t <%= @grammar.prefix %>user_terminate_code(<%= @grammar.prefix %>context_t
} }
<% if @grammar.tree %> <% if @grammar.tree %>
static void free_tree_node(TreeNode * node) static void tree_delete(TreeNode * node)
{ {
if (node->is_token) if (node->is_token)
{ {
<% if @grammar.free_token_node %> <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = (<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *)node;
<%= @grammar.free_token_node %>((<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> *) node); <%= expand_code(@grammar.free_token_node, false, nil, nil) %>
<% if @cpp %>
delete token_tree_node;
<% else %>
free(token_tree_node);
<% end %> <% end %>
/* TODO: free value_t */
} }
else if (node->n_fields > 0u) else if (node->n_fields > 0u)
{ {
@@ -1201,28 +1233,28 @@ static void free_tree_node(TreeNode * node)
{ {
if (node->fields[i] != NULL) if (node->fields[i] != NULL)
{ {
free_tree_node(node->fields[i]); tree_delete(node->fields[i]);
}
} }
} }
free(node); free(node);
}
} }
/** /**
* Free all tree node memory. * Free all tree node memory.
*/ */
void <%= @grammar.prefix %>free_tree(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree) void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree)
{ {
free_tree_node((TreeNode *)tree); tree_delete((TreeNode *)tree);
} }
<% @grammar.start_rules.each_with_index do |start_rule, i| %> <% @grammar.start_rules.each_with_index do |start_rule, i| %>
/** /**
* Free all tree node memory. * Free all tree node memory.
*/ */
void <%= @grammar.prefix %>free_tree_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree) void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree)
{ {
free_tree_node((TreeNode *)tree); tree_delete((TreeNode *)tree);
} }
<% end %> <% end %>
<% end %> <% end %>
+84 -14
View File
@@ -9,7 +9,7 @@ module <%= @grammar.modulename %>;
<% end %> <% end %>
import core.memory; import core.memory;
import core.stdc.stdlib : malloc; import core.stdc.stdlib : malloc, free;
/************************************************************************** /**************************************************************************
* User code blocks * User code blocks
@@ -86,6 +86,22 @@ public union <%= @grammar.prefix %>value_t
<%= typestring %> v_<%= name %>; <%= typestring %> v_<%= name %>;
<% end %> <% end %>
} }
/** Parser value constructor(s). */
<% @grammar.ptypes.each do |name, typestring| %>
public <%= @grammar.prefix %>value_t <%= @grammar.prefix %>value<%= name == "default" ? "" : "_#{name}" %>(T)(T v)
{
return <%= @grammar.prefix %>value_t(v_<%= name %>: v);
}
<% end %>
/** Parser value accessor(s). */
<% @grammar.ptypes.each do |name, typestring| %>
public <%= typestring %> <%= @grammar.prefix %>value_get<%= name == "default" ? "" : "_#{name}" %>(<%= @grammar.prefix %>value_t * pvalue)
{
return pvalue.v_<%= name %>;
}
<% end %>
<% end %> <% end %>
<% if @grammar.tree %> <% if @grammar.tree %>
@@ -94,6 +110,8 @@ private struct TreeNode
{ {
<%= @grammar.prefix %>position_t position; <%= @grammar.prefix %>position_t position;
<%= @grammar.prefix %>position_t end_position; <%= @grammar.prefix %>position_t end_position;
ushort n_fields;
bool is_token;
void *[0] fields; void *[0] fields;
} }
@@ -103,8 +121,11 @@ public struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
/* TreeNode fields must be present in the same order here. */ /* TreeNode fields must be present in the same order here. */
<%= @grammar.prefix %>position_t position; <%= @grammar.prefix %>position_t position;
<%= @grammar.prefix %>position_t end_position; <%= @grammar.prefix %>position_t end_position;
ushort n_fields;
bool is_token;
<%= @grammar.prefix %>token_t token; <%= @grammar.prefix %>token_t token;
<%= @grammar.prefix %>value_t pvalue; <%= @grammar.prefix %>value_t pvalue;
<%= @grammar.token_user_fields %>
} }
<% @parser.rule_sets.each do |name, rule_set| %> <% @parser.rule_sets.each do |name, rule_set| %>
@@ -114,6 +135,8 @@ public struct <%= @grammar.tree_prefix %><%= name %><%= @grammar.tree_suffix %>
{ {
<%= @grammar.prefix %>position_t position; <%= @grammar.prefix %>position_t position;
<%= @grammar.prefix %>position_t end_position; <%= @grammar.prefix %>position_t end_position;
ushort n_fields;
bool is_token;
<% rule_set.tree_fields.each do |fields| %> <% rule_set.tree_fields.each do |fields| %>
union union
{ {
@@ -183,6 +206,8 @@ public struct <%= @grammar.prefix %>context_t
/** User terminate code. */ /** User terminate code. */
size_t user_terminate_code; size_t user_terminate_code;
<%= @grammar.context_user_fields %>
} }
/************************************************************************** /**************************************************************************
@@ -222,26 +247,39 @@ private enum size_t INVALID_ID = cast(size_t)-1;
*************************************************************************/ *************************************************************************/
/** /**
* Initialize lexer/parser context structure. * Allocate and initialize lexer/parser context structure.
*
* Deinitialize and deallocate with <%= @grammar.prefix %>context_delete().
* *
* @param[out] context
* Lexer/parser context structure.
* @param input * @param input
* Text input. * Text input.
* @param input_length
* Text input length.
*
* @return Context structure for lexer/parser.
*/ */
public void <%= @grammar.prefix %>context_init(<%= @grammar.prefix %>context_t * context, string input) <%= @grammar.prefix %>context_t * <%= @grammar.prefix %>context_new(string input)
{ {
/* New default-initialized context structure. */ /* New default-initialized context structure. */
<%= @grammar.prefix %>context_t newcontext; <%= @grammar.prefix %>context_t * context = new <%= @grammar.prefix %>context_t;
/* Lexer initialization. */ /* Lexer initialization. */
newcontext.input = input; context.input = input;
newcontext.text_position.row = 1u; context.text_position.row = 1u;
newcontext.text_position.col = 1u; context.text_position.col = 1u;
newcontext.mode = <%= @lexer.mode_id("default") %>; context.mode = <%= @lexer.mode_id("default") %>;
/* Copy to the user's context structure. */ return context;
*context = newcontext; }
/**
* Deinitialize and deallocate lexer/parser context structure.
*
* @param context
* Lexer/parser context structure allocated with <%= @grammar.prefix %>context_new().
*/
void <%= @grammar.prefix %>context_delete(<%= @grammar.prefix %>context_t * context)
{
} }
/************************************************************************** /**************************************************************************
@@ -1015,7 +1053,7 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
{ {
if (token == INVALID_TOKEN_ID) if (token == INVALID_TOKEN_ID)
{ {
size_t lexer_result = <%= @grammar.prefix %>lex(context, &token_info); size_t lexer_result = <%= lex_fn %>(context, &token_info);
if (lexer_result != P_SUCCESS) if (lexer_result != P_SUCCESS)
{ {
return lexer_result; return lexer_result;
@@ -1049,7 +1087,8 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
{ {
/* We shifted a token, mark it consumed. */ /* We shifted a token, mark it consumed. */
<% if @grammar.tree %> <% if @grammar.tree %>
<%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = new <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>(token_info.position, token_info.end_position, token, token_info.pvalue); <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %> * token_tree_node = new <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>(token_info.position, token_info.end_position, 0u, true, token, token_info.pvalue);
<%= expand_code(@grammar.on_token_node, false, nil, nil) %>
statevalues[$-1].tree_node = token_tree_node; statevalues[$-1].tree_node = token_tree_node;
<% else %> <% else %>
statevalues[$-1].pvalue = token_info.pvalue; statevalues[$-1].pvalue = token_info.pvalue;
@@ -1088,6 +1127,8 @@ private size_t parse_from(<%= @grammar.prefix %>context_t * context, size_t star
GC.addRange(node, node_size); GC.addRange(node, node_size);
node.position = <%= @grammar.prefix %>position_t.INVALID; node.position = <%= @grammar.prefix %>position_t.INVALID;
node.end_position = <%= @grammar.prefix %>position_t.INVALID; node.end_position = <%= @grammar.prefix %>position_t.INVALID;
node.n_fields = cast(ushort)n_fields;
node.is_token = false;
foreach (i; 0..n_fields) foreach (i; 0..n_fields)
{ {
node.fields[i] = null; node.fields[i] = null;
@@ -1195,6 +1236,35 @@ public <%= start_rule_type(i)[1] %> <%= @grammar.prefix %>result_<%= start_rule
<% end %> <% end %>
<% end %> <% end %>
<% if @grammar.tree %>
private void tree_delete(TreeNode * node)
{
if (!node.is_token)
{
for (size_t i = 0u; i < node.n_fields; i++)
{
if (node.fields[i])
{
tree_delete(cast(TreeNode *)node.fields[i]);
}
}
GC.removeRange(node);
free(node);
}
}
void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree)
{
tree_delete(cast(TreeNode *)tree);
}
<% @grammar.start_rules.each_with_index do |start_rule, i| %>
void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree)
{
tree_delete(cast(TreeNode *)tree);
}
<% end %>
<% end %>
/** /**
* Get the current text input position. * Get the current text input position.
* *
+24 -3
View File
@@ -69,6 +69,22 @@ typedef union
<%= typestring %> v_<%= name %>; <%= typestring %> v_<%= name %>;
<% end %> <% end %>
} <%= @grammar.prefix %>value_t; } <%= @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 %> <% end %>
<% if @grammar.tree %> <% if @grammar.tree %>
@@ -80,6 +96,7 @@ typedef struct <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>
<%= @grammar.prefix %>position_t end_position; <%= @grammar.prefix %>position_t end_position;
uint16_t n_fields; uint16_t n_fields;
uint8_t is_token; uint8_t is_token;
<%= @grammar.token_user_fields %>
<%= @grammar.prefix %>token_t token; <%= @grammar.prefix %>token_t token;
<%= @grammar.prefix %>value_t pvalue; <%= @grammar.prefix %>value_t pvalue;
} <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>; } <%= @grammar.tree_prefix %>Token<%= @grammar.tree_suffix %>;
@@ -172,6 +189,8 @@ typedef struct
/** User terminate code. */ /** User terminate code. */
size_t user_terminate_code; size_t user_terminate_code;
<%= @grammar.context_user_fields %>
} <%= @grammar.prefix %>context_t; } <%= @grammar.prefix %>context_t;
/************************************************************************** /**************************************************************************
@@ -181,7 +200,9 @@ typedef struct
/** Token names. */ /** Token names. */
extern const char * <%= @grammar.prefix %>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); <%= @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, 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); <%= @grammar.prefix %>code_point_t * out_code_point, uint8_t * out_code_point_length);
@@ -206,9 +227,9 @@ size_t <%= @grammar.prefix %>parse_<%= start_rule %>(<%= @grammar.prefix %>conte
<% end %> <% end %>
<% if @grammar.tree %> <% if @grammar.tree %>
void <%= @grammar.prefix %>free_tree(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree); void <%= @grammar.prefix %>tree_delete(<%= @grammar.tree_prefix %><%= @grammar.start_rules[0] %><%= @grammar.tree_suffix %> * tree);
<% @grammar.start_rules.each_with_index do |start_rule, i| %> <% @grammar.start_rules.each_with_index do |start_rule, i| %>
void <%= @grammar.prefix %>free_tree_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree); void <%= @grammar.prefix %>tree_delete_<%= start_rule %>(<%= @grammar.tree_prefix %><%= start_rule %><%= @grammar.tree_suffix %> * tree);
<% end %> <% end %>
<% end %> <% end %>
+550 -291
View File
File diff suppressed because it is too large. Load diff
+12 -1
View File
@@ -8,7 +8,11 @@ if exists("b:current_syntax")
endif endif
if !exists("b:propane_subtype") if !exists("b:propane_subtype")
if search('\<import\s\+\%(std\|core\)\.', 'nw') > 0
let b:propane_subtype = "d" let b:propane_subtype = "d"
else
let b:propane_subtype = "cpp"
endif
endif endif
exe "syn include @propaneTarget syntax/".b:propane_subtype.".vim" exe "syn include @propaneTarget syntax/".b:propane_subtype.".vim"
@@ -20,12 +24,19 @@ syn match propaneOperator "->"
syn match propaneFieldAlias ":[a-zA-Z0-9_]\+" contains=propaneFieldOperator syn match propaneFieldAlias ":[a-zA-Z0-9_]\+" contains=propaneFieldOperator
syn match propaneFieldOperator ":" contained syn match propaneFieldOperator ":" contained
syn match propaneOperator "?" syn match propaneOperator "?"
syn keyword propaneKeyword drop free_token_node module prefix ptype start token tokenid tree tree_prefix tree_suffix " Keywords that introduce a user-defined name. The name is consumed by
" propaneName via nextgroup so a name matching a keyword (e.g. 'token start')
" is not highlighted as a keyword. These must be a match (not syn keyword)
" because a syn keyword always wins over a contained nextgroup match.
syn match propaneNameDecl "\<\%(tokenid\|token\|lex_fn\|module\|start\|tree_prefix\|tree_suffix\)\>" nextgroup=propaneName skipwhite
syn match propaneName "\<\h\w*\>" contained
syn match propaneKeyword "\<\%(context_user_fields\|drop\|free_token_node\|noline\|on_token_node\|prefix\|ptype\|token_user_fields\|tree\)\>"
syn region propaneRegex start="/" end="/" skip="\v\\\\|\\/" syn region propaneRegex start="/" end="/" skip="\v\\\\|\\/"
hi def link propaneComment Comment hi def link propaneComment Comment
hi def link propaneKeyword Keyword hi def link propaneKeyword Keyword
hi def link propaneNameDecl Keyword
hi def link propaneRegex String hi def link propaneRegex String
hi def link propaneOperator Operator hi def link propaneOperator Operator
hi def link propaneFieldOperator Operator hi def link propaneFieldOperator Operator
+1 -1
View File
@@ -33,7 +33,7 @@ class Propane
def run(input_file, output_file, log_file, options) def run(input_file, output_file, log_file, options)
begin begin
grammar = Grammar.new(File.read(input_file)) grammar = Grammar.new(File.read(input_file), input_file)
generator = Generator.new(grammar, output_file, log_file, options) generator = Generator.new(grammar, output_file, log_file, options)
generator.generate generator.generate
rescue Error => e rescue Error => e
+39 -2
View File
@@ -13,8 +13,13 @@ class Propane
@language = @language =
if output_file.end_with?(".d") if output_file.end_with?(".d")
"d" "d"
else elsif output_file.end_with?(".c")
"c" "c"
elsif output_file =~ %r{\.(cc|cpp|cxx)$}
@cpp = true
"c"
else
raise Error.new("Could not determine target language from output file name (#{output_file})")
end end
@options = options @options = options
process_grammar! process_grammar!
@@ -33,7 +38,13 @@ class Propane
output_file = @output_file output_file = @output_file
end end
erb = ERB.new(template, trim_mode: "<>") erb = ERB.new(template, trim_mode: "<>")
result = erb.result(binding.clone) result = erb.result(binding.clone).lines.each_with_index.map do |line, i|
if line == "#linereset\n"
%[#line #{i + 2} "#{output_file}"\n]
else
line
end
end.join
File.open(output_file, "wb") do |fh| File.open(output_file, "wb") do |fh|
fh.write(result) fh.write(result)
end end
@@ -265,6 +276,24 @@ class Propane
"context.user_terminate_code = (#{user_terminate_code}); return #{retval};" "context.user_terminate_code = (#{user_terminate_code}); return #{retval};"
end end
end end
code = code.gsub(/\$\{context\.(\w+)\}/) do |match|
fieldname = $1
case @language
when "c"
"context->#{fieldname}"
when "d"
"context.#{fieldname}"
end
end
code = code.gsub(/\$\{token\.(\w+)\}/) do |match|
fieldname = $1
case @language
when "c"
"token_tree_node->#{fieldname}"
when "d"
"token_tree_node.#{fieldname}"
end
end
if parser if parser
code = code.gsub(/\$\$/) do |match| code = code.gsub(/\$\$/) do |match|
case @language case @language
@@ -331,6 +360,14 @@ class Propane
code code
end end
# Get the lex function to use.
#
# @return [String]
# Lex function to use.
def lex_fn
@grammar.lex_fn || "#{@grammar.prefix}lex"
end
# Get the parser value type for the start rule. # Get the parser value type for the start rule.
# #
# @return [Array<String>] # @return [Array<String>]
+88 -15
View File
@@ -5,6 +5,8 @@ class Propane
# Reserve identifiers beginning with a double-underscore for internal use. # Reserve identifiers beginning with a double-underscore for internal use.
IDENTIFIER_REGEX = /(?:[a-zA-Z]|_[a-zA-Z0-9])[a-zA-Z_0-9]*/ IDENTIFIER_REGEX = /(?:[a-zA-Z]|_[a-zA-Z0-9])[a-zA-Z_0-9]*/
attr_reader :context_user_fields
attr_reader :lex_fn
attr_reader :tree attr_reader :tree
attr_reader :tree_prefix attr_reader :tree_prefix
attr_reader :tree_suffix attr_reader :tree_suffix
@@ -17,8 +19,11 @@ class Propane
attr_reader :code_blocks attr_reader :code_blocks
attr_reader :ptypes attr_reader :ptypes
attr_reader :prefix attr_reader :prefix
attr_reader :on_token_node
attr_reader :token_user_fields
def initialize(input) def initialize(input, filename)
@filename = filename
@patterns = [] @patterns = []
@start_rules = [] @start_rules = []
@tokens = [] @tokens = []
@@ -33,7 +38,10 @@ class Propane
@tree = false @tree = false
@tree_prefix = "" @tree_prefix = ""
@tree_suffix = "" @tree_suffix = ""
@free_token_node = nil @free_token_node = ""
@context_user_fields = nil
@on_token_node = ""
@token_user_fields = nil
parse_grammar! parse_grammar!
@start_rules << "Start" if @start_rules.empty? @start_rules << "Start" if @start_rules.empty?
end end
@@ -62,11 +70,15 @@ class Propane
if parse_white_space! if parse_white_space!
elsif parse_comment_line! elsif parse_comment_line!
elsif @modeline.nil? && parse_mode_label! elsif @modeline.nil? && parse_mode_label!
elsif parse_context_user_fields_statement!
elsif parse_lex_fn!
elsif parse_tree_statement! elsif parse_tree_statement!
elsif parse_tree_prefix_statement! elsif parse_tree_prefix_statement!
elsif parse_tree_suffix_statement! elsif parse_tree_suffix_statement!
elsif parse_free_token_node_statement! elsif parse_free_token_node_statement!
elsif parse_module_statement! elsif parse_module_statement!
elsif parse_on_token_node_statement!
elsif parse_token_user_fields_statement!
elsif parse_ptype_statement! elsif parse_ptype_statement!
elsif parse_pattern_statement! elsif parse_pattern_statement!
elsif parse_start_statement! elsif parse_start_statement!
@@ -76,6 +88,7 @@ class Propane
elsif parse_rule_statement! elsif parse_rule_statement!
elsif parse_code_block_statement! elsif parse_code_block_statement!
elsif parse_prefix_statement! elsif parse_prefix_statement!
elsif parse_noline_statement!
else else
if @input.size > 25 if @input.size > 25
@input = @input.slice(0..20) + "..." @input = @input.slice(0..20) + "..."
@@ -98,6 +111,22 @@ class Propane
consume!(/#.*\n/) consume!(/#.*\n/)
end end
def parse_context_user_fields_statement!
if md = consume!(/context_user_fields\b\s*/)
unless code = parse_code_block!
raise Error.new("Line #{@line_number}: expected code block")
end
@context_user_fields ||= ""
@context_user_fields += code
end
end
def parse_lex_fn!
if md = consume!(/lex_fn\b\s*(\w+)\s*;/)
@lex_fn = md[1]
end
end
def parse_tree_statement! def parse_tree_statement!
if consume!(/tree\s*;/) if consume!(/tree\s*;/)
@tree = true @tree = true
@@ -116,12 +145,6 @@ class Propane
end end
end end
def parse_free_token_node_statement!
if md = consume!(/free_token_node\s+(\w+)\s*;/)
@free_token_node = md[1]
end
end
def parse_module_statement! def parse_module_statement!
if consume!(/module\s+/) if consume!(/module\s+/)
md = consume!(/([\w.]+)\s*/, "expected module name") md = consume!(/([\w.]+)\s*/, "expected module name")
@@ -132,6 +155,34 @@ class Propane
end end
end end
def parse_on_token_node_statement!
if md = consume!(/on_token_node\b\s*/)
unless code = parse_code_block!
raise Error.new("Line #{@line_number}: expected code block")
end
@on_token_node += code
end
end
def parse_token_user_fields_statement!
if md = consume!(/token_user_fields\b\s*/)
unless code = parse_code_block!
raise Error.new("Line #{@line_number}: expected code block")
end
@token_user_fields ||= ""
@token_user_fields += code
end
end
def parse_free_token_node_statement!
if md = consume!(/free_token_node\b\s*/)
unless code = parse_code_block!
raise Error.new("Line #{@line_number}: expected code block")
end
@free_token_node += code
end
end
def parse_ptype_statement! def parse_ptype_statement!
if consume!(/ptype\s+/) if consume!(/ptype\s+/)
name = "default" name = "default"
@@ -195,8 +246,10 @@ class Propane
raise Error.new("Line #{@line_number}: expected pattern to follow `drop'") raise Error.new("Line #{@line_number}: expected pattern to follow `drop'")
end end
consume!(/\s+/) consume!(/\s+/)
consume!(/;/, "expected `;'") unless code = parse_code_block!
@patterns << Pattern.new(pattern: pattern, line_number: @line_number, modes: get_modes_from_modeline) consume!(/;/, "expected `;' or code block")
end
@patterns << Pattern.new(pattern: pattern, line_number: @line_number, code: code, modes: get_modes_from_modeline)
@modeline = nil @modeline = nil
true true
end end
@@ -253,8 +306,14 @@ class Propane
def parse_code_block_statement! def parse_code_block_statement!
if md = consume!(/<<([a-z]*)(.*?)>>\n/m) if md = consume!(/<<([a-z]*)(.*?)>>\n/m)
name, code = md[1..2] name, code = md[1..2]
code.sub!(/\A\n/, "") code = code.chomp
code += "\n" unless code.end_with?("\n") unless @noline
if code.start_with?("\n")
code = %[#line #{@line_number + 1} "#{@filename}"#{code}\n#linereset\n]
else
code = %[#line #{@line_number} "#{@filename}"\n#{code}\n#linereset\n]
end
end
if @code_blocks[name] if @code_blocks[name]
@code_blocks[name] += code @code_blocks[name] += code
else else
@@ -272,6 +331,13 @@ class Propane
end end
end end
def parse_noline_statement!
if md = consume!(/noline\s*;/)
@noline = true
true
end
end
def parse_pattern! def parse_pattern!
if md = consume!(%r{/}) if md = consume!(%r{/})
pattern = "" pattern = ""
@@ -285,6 +351,8 @@ class Propane
end end
elsif md = consume!(%r{(.)}) elsif md = consume!(%r{(.)})
pattern += md[1] pattern += md[1]
elsif @input == "" || @input.start_with?("\n")
raise Error.new("Line #{@line_number}: Unterminated pattern; expected `/`")
end end
end end
pattern pattern
@@ -293,9 +361,14 @@ class Propane
def parse_code_block! def parse_code_block!
if md = consume!(/<<(.*?)>>\n/m) if md = consume!(/<<(.*?)>>\n/m)
code = md[1] code = md[1].chomp
code.sub!(/\A\n/, "") unless @noline
code += "\n" unless code.end_with?("\n") if code.start_with?("\n")
code = %[#line #{@line_number + 1} "#{@filename}"#{code}\n#linereset\n]
else
code = %[#line #{@line_number} "#{@filename}"\n#{code}\n#linereset\n]
end
end
code code
end end
end end
+1 -1
View File
@@ -1,3 +1,3 @@
class Propane class Propane
VERSION = "3.0.0" VERSION = "4.5.0"
end end
+44 -9
View File
@@ -28,7 +28,7 @@ B -> <<
b = 0; b = 0;
>> >>
EOF EOF
grammar = Grammar.new(input) grammar = Grammar.new(input, "test.propane")
expect(grammar.modulename).to eq "a.b" expect(grammar.modulename).to eq "a.b"
expect(grammar.ptype).to eq "XYZ *" expect(grammar.ptype).to eq "XYZ *"
expect(grammar.ptypes).to eq("default" => "XYZ *") expect(grammar.ptypes).to eq("default" => "XYZ *")
@@ -62,7 +62,7 @@ EOF
expect(o).to_not be_nil expect(o).to_not be_nil
expect(o.pattern).to eq "token_with_code" expect(o.pattern).to eq "token_with_code"
expect(o.line_number).to eq 11 expect(o.line_number).to eq 11
expect(o.code).to eq "Code for the token\n" expect(o.code).to eq %[#line 12 "test.propane"\nCode for the token\n#linereset\n]
o = grammar.tokens.find {|token| token.name == "token_with_no_pattern"} o = grammar.tokens.find {|token| token.name == "token_with_no_pattern"}
expect(o).to_not be_nil expect(o).to_not be_nil
@@ -83,7 +83,7 @@ EOF
expect(o.name).to eq "A" expect(o.name).to eq "A"
expect(o.components).to eq %w[B] expect(o.components).to eq %w[B]
expect(o.line_number).to eq 19 expect(o.line_number).to eq 19
expect(o.code).to eq " a = 42;\n" expect(o.code).to eq %[#line 20 "test.propane"\n a = 42;\n#linereset\n]
o = grammar.rules[1] o = grammar.rules[1]
expect(o.name).to eq "B" expect(o.name).to eq "B"
@@ -95,7 +95,7 @@ EOF
expect(o.name).to eq "B" expect(o.name).to eq "B"
expect(o.components).to eq [] expect(o.components).to eq []
expect(o.line_number).to eq 23 expect(o.line_number).to eq 23
expect(o.code).to eq " b = 0;\n" expect(o.code).to eq %[#line 24 "test.propane"\n b = 0;\n#linereset\n]
end end
it "parses code segments with semicolons" do it "parses code segments with semicolons" do
@@ -113,7 +113,7 @@ tokenid token_with_no_pattern;
prefix myparser_; prefix myparser_;
EOF EOF
grammar = Grammar.new(input) grammar = Grammar.new(input, "test.propane")
expect(grammar.prefix).to eq "myparser_" expect(grammar.prefix).to eq "myparser_"
o = grammar.tokens.find {|token| token.name == "code1"} o = grammar.tokens.find {|token| token.name == "code1"}
@@ -122,7 +122,7 @@ EOF
o = grammar.patterns.find {|pattern| pattern.token == o} o = grammar.patterns.find {|pattern| pattern.token == o}
expect(o).to_not be_nil expect(o).to_not be_nil
expect(o.code).to eq " a = b;\n return c;\n" expect(o.code).to eq %[#line 2 "test.propane"\n a = b;\n return c;\n#linereset\n]
o = grammar.tokens.find {|token| token.name == "code2"} o = grammar.tokens.find {|token| token.name == "code2"}
expect(o).to_not be_nil expect(o).to_not be_nil
@@ -130,7 +130,42 @@ EOF
o = grammar.patterns.find {|pattern| pattern.token == o} o = grammar.patterns.find {|pattern| pattern.token == o}
expect(o).to_not be_nil expect(o).to_not be_nil
expect(o.code).to eq %[ writeln("Hello there");\n] expect(o.code).to eq %[#line 7 "test.propane"\n writeln("Hello there");\n#linereset\n]
end
it "does not emit #line directives with noline statement" do
input = <<EOF
noline;
token code1 <<
a = b;
return c;
>>
token code2 <<
writeln("Hello there");
>>
tokenid token_with_no_pattern;
prefix myparser_;
EOF
grammar = Grammar.new(input, "test.propane")
expect(grammar.prefix).to eq "myparser_"
o = grammar.tokens.find {|token| token.name == "code1"}
expect(o).to_not be_nil
o = grammar.patterns.find {|pattern| pattern.token == o}
expect(o).to_not be_nil
expect(o.code).to eq %[\n a = b;\n return c;]
o = grammar.tokens.find {|token| token.name == "code2"}
expect(o).to_not be_nil
o = grammar.patterns.find {|pattern| pattern.token == o}
expect(o).to_not be_nil
expect(o.code).to eq %[\n writeln("Hello there");]
end end
it "supports mode labels" do it "supports mode labels" do
@@ -144,7 +179,7 @@ m2: /bar/ <<
drop /q/; drop /q/;
m3: drop /r/; m3: drop /r/;
EOF EOF
grammar = Grammar.new(input) grammar = Grammar.new(input, "test.propane")
o = grammar.tokens.find {|token| token.name == "a"} o = grammar.tokens.find {|token| token.name == "a"}
expect(o).to_not be_nil expect(o).to_not be_nil
@@ -197,7 +232,7 @@ tokenid int(integer);
Start (node) -> R; Start (node) -> R;
R -> abc int; R -> abc int;
EOF EOF
grammar = Grammar.new(input) grammar = Grammar.new(input, "test.propane")
o = grammar.tokens.find {|token| token.name == "abc"} o = grammar.tokens.find {|token| token.name == "abc"}
expect(o).to_not be_nil expect(o).to_not be_nil
+1 -1
View File
@@ -51,7 +51,7 @@ class TestLexer
end end
def run(grammar, input) def run(grammar, input)
grammar = Propane::Grammar.new(grammar) grammar = Propane::Grammar.new(grammar, "test.propane")
token_dfa = Propane::Lexer::DFA.new(grammar.patterns) token_dfa = Propane::Lexer::DFA.new(grammar.patterns)
test_lexer = TestLexer.new(token_dfa) test_lexer = TestLexer.new(token_dfa)
test_lexer.lex(input) test_lexer.lex(input)
+316 -12
View File
@@ -14,6 +14,7 @@ describe Propane do
end end
def run_propane(options = {}) def run_propane(options = {})
options[:language] ||= "d"
@statics[:build_test_id] ||= 0 @statics[:build_test_id] ||= 0
@statics[:build_test_id] += 1 @statics[:build_test_id] += 1
if ENV["dist_specs"] if ENV["dist_specs"]
@@ -94,17 +95,15 @@ EOF
File.binwrite("spec/run/.stdout", stdout) File.binwrite("spec/run/.stdout", stdout)
stderr.sub!(/^.*modules passed unittests\n/, "") stderr.sub!(/^.*modules passed unittests\n/, "")
results = Results.new(stdout, stderr, status) results = Results.new(stdout, stderr, status)
if %w[c cpp].include?(options[:language])
stdout, stderr, status = Open3.capture3("valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose spec/run/testparser") stdout, stderr, status = Open3.capture3("valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose spec/run/testparser")
vgout = stdout + stderr vgout = stdout + stderr
File.binwrite("spec/run/.vgout", vgout) File.binwrite("spec/run/.vgout", vgout)
vgout.scan(/lost: (\d+) bytes/) do |match| vgout.scan(/(?:definitely|indirectly) lost: (\d+) bytes/) do |match|
bytes = $1.to_i bytes = $1.to_i
if bytes > 0 if bytes > 0
raise "Valgrind detected memory leak" raise "Valgrind detected memory leak"
end end
end end
end
results results
end end
@@ -1430,6 +1429,9 @@ EOF
expect(results.stdout).to match /first is foo1.*second is bar2/m expect(results.stdout).to match /first is foo1.*second is bar2/m
end end
# D garbage collector was freeing memory for nodes when it should not
# have been. This was due to pointers being in the TreeNode that was
# allocated by C malloc() function instead of allocated using D.
it "does not free memory allocated for tree nodes" do it "does not free memory allocated for tree nodes" do
ext = language == "cpp" ? "c" : language ext = language == "cpp" ? "c" : language
write_grammar(File.read("spec/tree_node_memory_remains.#{ext}.propane")) write_grammar(File.read("spec/tree_node_memory_remains.#{ext}.propane"))
@@ -1484,14 +1486,10 @@ EOF
if %w[c cpp].include?(language) if %w[c cpp].include?(language)
it "allows a user function to free token node memory in tree mode" do it "allows a user function to free token node memory in tree mode" do
write_grammar <<EOF write_grammar <<EOF
<<
static void free_token(Token * token)
{
free(token->pvalue);
}
>>
tree; tree;
free_token_node free_token; free_token_node <<
free(${token.pvalue});
>>
ptype int *; ptype int *;
token a << token a <<
$$ = (int *)malloc(sizeof(int)); $$ = (int *)malloc(sizeof(int));
@@ -1504,12 +1502,318 @@ token b <<
Start -> a:a b:b; Start -> a:a b:b;
EOF EOF
run_propane(language: language) run_propane(language: language)
compile("spec/test_free_tree_token_node_memory.#{language}", language: language) compile("spec/test_tree_delete_token_node_memory.#{language}", language: language)
results = run_test(language: language)
expect(results.stderr).to eq ""
expect(results.status).to eq 0
end
end
it "executes code blocks associated with drop statements" do
if language == "d"
write_grammar <<EOF
<<
import std.stdio;
>>
drop /\\s+/;
drop /#(.*)\\n/ <<
stderr.write("comment: ", match);
>>
token a;
Start -> a;
EOF
else
write_grammar <<EOF
<<
#include <stdio.h>
#include <string.h>
>>
drop /\\s+/;
drop /#(.*)\\n/ <<
fprintf(stderr, "comment: %.*s", (int)match_length, match);
>>
token a;
Start -> a;
EOF
end
run_propane(language: language)
compile("spec/test_drop_code_block.#{language}", language: language)
results = run_test(language: language)
expect(results.stderr).to match %r{comment: # comment 1\n.*comment: # comment 2}m
expect(results.status).to eq 0
end
it "allows user-defined context fields" do
if language == "d"
write_grammar <<EOF
context_user_fields <<
string comments;
uint acount;
>>
drop /\\s+/;
drop /#(.*)\\n/ <<
${context.comments} ~= match;
>>
token a <<
${context.acount}++;
>>
Start -> As;
As -> ;
As -> a As;
EOF
else
write_grammar <<EOF
<<
#include <string.h>
#include <stdlib.h>
>>
context_user_fields <<
char * comments;
unsigned int acount;
>>
drop /\\s+/;
drop /#(.*)\\n/ <<
size_t cur_len = 0u;
if (${context.comments} != NULL)
cur_len = strlen(${context.comments});
char * commentsnew = (char *)malloc(cur_len + match_length + 1);
if (${context.comments} != NULL)
memcpy(commentsnew, ${context.comments}, cur_len);
memcpy(&commentsnew[cur_len], match, match_length);
commentsnew[cur_len + match_length] = '\\0';
if (${context.comments} != NULL)
{
free(${context.comments});
}
${context.comments} = commentsnew;
>>
token a <<
${context.acount}++;
>>
Start -> As;
As -> ;
As -> a As;
EOF
end
run_propane(language: language)
compile("spec/test_user_context_fields.#{language}", language: language)
results = run_test(language: language)
expect(results.stderr).to include %r{comments: # comment 1\n# comment 2}
expect(results.stderr).to include %r{acount: 11\n}
expect(results.status).to eq 0
end
it "allows custom token user fields" do
if language == "d"
write_grammar <<EOF
context_user_fields <<
string comments;
>>
token_user_fields <<
string comments;
>>
on_token_node <<
${token.comments} = ${context.comments};
${context.comments} = "";
>>
tree;
drop /\\s+/;
drop /#(.*)\\n/ <<
${context.comments} ~= match;
>>
token id /\\w+/;
Start -> IDs;
IDs -> ;
IDs -> id:id IDs;
EOF
elsif language == "c"
write_grammar <<EOF
<<
#include <string.h>
#include <stdlib.h>
>>
context_user_fields <<
char * comments;
>>
token_user_fields <<
char * comments;
>>
free_token_node <<
free(${token.comments});
>>
on_token_node <<
${token.comments} = ${context.comments};
${context.comments} = (char *)malloc(1);
${context.comments}[0] = '\\0';
>>
tree;
drop /\\s+/;
drop /#(.*)\\n/ <<
size_t cur_len = 0u;
if (${context.comments} != NULL)
cur_len = strlen(${context.comments});
char * commentsnew = (char *)malloc(cur_len + match_length + 1);
if (${context.comments} != NULL)
memcpy(commentsnew, ${context.comments}, cur_len);
memcpy(&commentsnew[cur_len], match, match_length);
commentsnew[cur_len + match_length] = '\\0';
if (${context.comments} != NULL)
{
free(${context.comments});
}
${context.comments} = commentsnew;
>>
token id /\\w+/;
Start -> IDs;
IDs -> ;
IDs -> id:id IDs;
EOF
else # C++
write_grammar <<EOF
<<header
#include <string>
>>
context_user_fields <<
std::string comments;
>>
token_user_fields <<
std::string comments;
>>
on_token_node <<
${token.comments} = ${context.comments};
${context.comments} = "";
>>
tree;
drop /\\s+/;
drop /#(.*)\\n/ <<
${context.comments} += std::string((const char *)match, match_length);
>>
token id /\\w+/;
Start -> IDs;
IDs -> ;
IDs -> id:id IDs;
EOF
end
run_propane(language: language)
compile("spec/test_token_user_fields.#{language}", language: language)
results = run_test(language: language)
expect(results.status).to eq 0
end
it "allows a custom lex function" do
if language == "d"
write_grammar <<EOF
<<
private size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
{
static size_t count;
size_t result = P_SUCCESS;
if (count > 0)
{
out_token_info.token = TOKEN_a;
out_token_info.pvalue = p_value(count);
count--;
}
else
{
result = p_lex(context, out_token_info);
if (out_token_info.token == TOKEN_c)
{
count = 3;
}
}
return result;
}
>>
ptype size_t;
lex_fn mylexfn;
token a << $$ = 7; >>
token b << $$ = 8; >>
token c << $$ = 9; >>
Start -> << $$ = 0; >>
Start -> Start ID << $$ = ($1 << 4) | $2; >>
ID -> a << $$ = $1; >>
ID -> b << $$ = $1; >>
ID -> c << $$ = $1; >>
EOF
else
write_grammar <<EOF
<<
static size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
{
static size_t count;
size_t result = P_SUCCESS;
if (count > 0)
{
out_token_info->token = TOKEN_a;
out_token_info->pvalue = p_value(count);
count--;
}
else
{
result = p_lex(context, out_token_info);
if (out_token_info->token == TOKEN_c)
{
count = 3;
}
}
return result;
}
>>
ptype size_t;
lex_fn mylexfn;
token a << $$ = 7; >>
token b << $$ = 8; >>
token c << $$ = 9; >>
Start -> << $$ = 0; >>
Start -> Start ID << $$ = ($1 << 4) | $2; >>
ID -> a << $$ = $1; >>
ID -> b << $$ = $1; >>
ID -> c << $$ = $1; >>
EOF
end
run_propane(language: language)
compile("spec/test_custom_lex_fn.#{language}", language: language)
results = run_test(language: language)
expect(results.status).to eq 0
end
it "provides accessor functions to extract user values from a parser value" do
if language == "d"
write_grammar <<EOF
ptype int;
ptype float = float;
ptype string = string;
drop /\\s+/;
token num /\\d+/ << $$ = 42; >>
token flt (float) /f/ << $$ = 1.5; >>
token str (string) /s/ << $$ = "hello"; >>
Start -> num flt str;
EOF
else
write_grammar <<EOF
ptype int;
ptype float = float;
ptype string = char *;
drop /\\s+/;
token num /\\d+/ << $$ = 42; >>
token flt (float) /f/ << $$ = 1.5; >>
token str (string) /s/ << $$ = (char *)"hello"; >>
Start -> num flt str;
EOF
end
run_propane(language: language)
compile("spec/test_value_accessors.#{language}", language: language)
results = run_test(language: language) results = run_test(language: language)
expect(results.stderr).to eq "" expect(results.stderr).to eq ""
expect(results.status).to eq 0 expect(results.status).to eq 0
end end
end end
end end
end
end end
+17 -13
View File
@@ -5,25 +5,29 @@
int main() int main()
{ {
char const * input = "1 + 2 * 3 + 4"; char const * input = "1 + 2 * 3 + 4";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(11, p_result(&context)); assert_eq(11, p_result(context));
p_context_delete(context);
input = "1 * 2 ** 4 * 3"; input = "1 * 2 ** 4 * 3";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(48, p_result(&context)); assert_eq(48, p_result(context));
p_context_delete(context);
input = "(1 + 2) * 3 + 4"; input = "(1 + 2) * 3 + 4";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(13, p_result(&context)); assert_eq(13, p_result(context));
p_context_delete(context);
input = "(2 * 2) ** 3 + 4 + 5"; input = "(2 * 2) ** 3 + 4 + 5";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(73, p_result(&context)); assert_eq(73, p_result(context));
p_context_delete(context);
return 0; return 0;
} }
+13 -13
View File
@@ -10,23 +10,23 @@ int main()
unittest unittest
{ {
string input = "1 + 2 * 3 + 4"; string input = "1 + 2 * 3 + 4";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(11, p_result(&context)); assert_eq(11, p_result(context));
input = "1 * 2 ** 4 * 3"; input = "1 * 2 ** 4 * 3";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(48, p_result(&context)); assert_eq(48, p_result(context));
input = "(1 + 2) * 3 + 4"; input = "(1 + 2) * 3 + 4";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(13, p_result(&context)); assert_eq(13, p_result(context));
input = "(2 * 2) ** 3 + 4 + 5"; input = "(2 * 2) ** 3 + 4 + 5";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(73, p_result(&context)); assert_eq(73, p_result(context));
} }
+15
View File
@@ -0,0 +1,15 @@
#include "testparser.h"
#include "testutils.h"
#include <string.h>
int main()
{
char const * input = "cbacba";
p_context_t * context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(context));
size_t result = p_result(context);
assert_eq(0x932187932187, result);
p_context_delete(context);
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
import testparser;
import std.stdio;
import testutils;
int main()
{
return 0;
}
unittest
{
string input = "cbacba";
p_context_t * context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(context));
size_t result = p_result(context);
assert_eq(0x932187932187, result);
p_context_delete(context);
}
+15
View File
@@ -0,0 +1,15 @@
#include "testparser.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main()
{
char const * input = " # comment 1\n# comment 2\na\n";
p_context_t * context;
context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0;
}
+16
View File
@@ -0,0 +1,16 @@
import testparser;
import std.stdio;
import testutils;
int main()
{
return 0;
}
unittest
{
string input = " # comment 1\n# comment 2\na\n";
p_context_t * context;
context = p_context_new(input);
assert(p_parse(context) == P_SUCCESS);
}
+26 -21
View File
@@ -5,38 +5,43 @@
int main() int main()
{ {
char const * input = "a 42"; char const * input = "a 42";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "a\n123\na a"; input = "a\n123\na a";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context).row == 3); assert(p_position(context).row == 3);
assert(p_position(&context).col == 4); assert(p_position(context).col == 4);
assert(p_token(&context) == TOKEN_a); assert(p_token(context) == TOKEN_a);
p_context_delete(context);
input = "12"; input = "12";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context).row == 1); assert(p_position(context).row == 1);
assert(p_position(&context).col == 1); assert(p_position(context).col == 1);
assert(p_token(&context) == TOKEN_num); assert(p_token(context) == TOKEN_num);
p_context_delete(context);
input = "a 12\n\nab"; input = "a 12\n\nab";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_UNEXPECTED_INPUT); assert(p_parse(context) == P_UNEXPECTED_INPUT);
assert(p_position(&context).row == 3); assert(p_position(context).row == 3);
assert(p_position(&context).col == 2); assert(p_position(context).col == 2);
p_context_delete(context);
input = "a 12\n\na\n\n77\na \xAA"; input = "a 12\n\na\n\n77\na \xAA";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_DECODE_ERROR); assert(p_parse(context) == P_DECODE_ERROR);
assert(p_position(&context).row == 6); assert(p_position(context).row == 6);
assert(p_position(&context).col == 5); assert(p_position(context).col == 5);
assert(strcmp(p_token_names[TOKEN_a], "a") == 0); assert(strcmp(p_token_names[TOKEN_a], "a") == 0);
assert(strcmp(p_token_names[TOKEN_num], "num") == 0); assert(strcmp(p_token_names[TOKEN_num], "num") == 0);
p_context_delete(context);
return 0; return 0;
} }
+17 -17
View File
@@ -9,31 +9,31 @@ int main()
unittest unittest
{ {
string input = "a 42"; string input = "a 42";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "a\n123\na a"; input = "a\n123\na a";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(3, 4)); assert(p_position(context) == p_position_t(3, 4));
assert(p_token(&context) == TOKEN_a); assert(p_token(context) == TOKEN_a);
input = "12"; input = "12";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(1, 1)); assert(p_position(context) == p_position_t(1, 1));
assert(p_token(&context) == TOKEN_num); assert(p_token(context) == TOKEN_num);
input = "a 12\n\nab"; input = "a 12\n\nab";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_UNEXPECTED_INPUT); assert(p_parse(context) == P_UNEXPECTED_INPUT);
assert(p_position(&context) == p_position_t(3, 2)); assert(p_position(context) == p_position_t(3, 2));
input = "a 12\n\na\n\n77\na \xAA"; input = "a 12\n\na\n\n77\na \xAA";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_DECODE_ERROR); assert(p_parse(context) == P_DECODE_ERROR);
assert(p_position(&context) == p_position_t(6, 5)); assert(p_position(context) == p_position_t(6, 5));
assert(p_token_names[TOKEN_a] == "a"); assert(p_token_names[TOKEN_a] == "a");
assert(p_token_names[TOKEN_num] == "num"); assert(p_token_names[TOKEN_num] == "num");
+4 -3
View File
@@ -6,8 +6,9 @@
int main() int main()
{ {
char const * input = "foo1\nbar2"; char const * input = "foo1\nbar2";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+3 -3
View File
@@ -9,7 +9,7 @@ int main()
unittest unittest
{ {
string input = "foo1\nbar2"; string input = "foo1\nbar2";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+14 -12
View File
@@ -38,73 +38,75 @@ int main()
p_token_info_t token_info; p_token_info_t token_info;
char const * input = "5 + 4 * \n677 + 567"; char const * input = "5 + 4 * \n677 + 567";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 1u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 1u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 1u); assert(token_info.end_position.col == 1u);
assert(token_info.length == 1u); assert(token_info.length == 1u);
assert(token_info.token == TOKEN_int); assert(token_info.token == TOKEN_int);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 1u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 3u); assert(token_info.position.col == 3u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 3u); assert(token_info.end_position.col == 3u);
assert(token_info.length == 1u); assert(token_info.length == 1u);
assert(token_info.token == TOKEN_plus); assert(token_info.token == TOKEN_plus);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 1u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 5u); assert(token_info.position.col == 5u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 5u); assert(token_info.end_position.col == 5u);
assert(token_info.length == 1u); assert(token_info.length == 1u);
assert(token_info.token == TOKEN_int); assert(token_info.token == TOKEN_int);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 1u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 7u); assert(token_info.position.col == 7u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 7u); assert(token_info.end_position.col == 7u);
assert(token_info.length == 1u); assert(token_info.length == 1u);
assert(token_info.token == TOKEN_times); assert(token_info.token == TOKEN_times);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 2u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 1u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 2u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 3u); assert(token_info.end_position.col == 3u);
assert(token_info.length == 3u); assert(token_info.length == 3u);
assert(token_info.token == TOKEN_int); assert(token_info.token == TOKEN_int);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 2u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 5u); assert(token_info.position.col == 5u);
assert(token_info.end_position.row == 2u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 5u); assert(token_info.end_position.col == 5u);
assert(token_info.length == 1u); assert(token_info.length == 1u);
assert(token_info.token == TOKEN_plus); assert(token_info.token == TOKEN_plus);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 2u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 7u); assert(token_info.position.col == 7u);
assert(token_info.end_position.row == 2u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 9u); assert(token_info.end_position.col == 9u);
assert(token_info.length == 3u); assert(token_info.length == 3u);
assert(token_info.token == TOKEN_int); assert(token_info.token == TOKEN_int);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 2u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 10u); assert(token_info.position.col == 10u);
assert(token_info.end_position.row == 2u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 10u); assert(token_info.end_position.col == 10u);
assert(token_info.length == 0u); assert(token_info.length == 0u);
assert(token_info.token == TOKEN___EOF); assert(token_info.token == TOKEN___EOF);
p_context_delete(context);
p_context_init(&context, (uint8_t const *)"", 0u); context = p_context_new((uint8_t const *)"", 0u);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.position.row == 1u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 1u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 1u); assert(token_info.end_position.col == 1u);
assert(token_info.length == 0u); assert(token_info.length == 0u);
assert(token_info.token == TOKEN___EOF); assert(token_info.token == TOKEN___EOF);
p_context_delete(context);
return 0; return 0;
} }
+12 -12
View File
@@ -44,26 +44,26 @@ unittest
{ {
p_token_info_t token_info; p_token_info_t token_info;
string input = "5 + 4 * \n677 + 567"; string input = "5 + 4 * \n677 + 567";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(1, 1), p_position_t(1, 1), 1, TOKEN_int)); assert(token_info == p_token_info_t(p_position_t(1, 1), p_position_t(1, 1), 1, TOKEN_int));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(1, 3), p_position_t(1, 3), 1, TOKEN_plus)); assert(token_info == p_token_info_t(p_position_t(1, 3), p_position_t(1, 3), 1, TOKEN_plus));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(1, 5), p_position_t(1, 5), 1, TOKEN_int)); assert(token_info == p_token_info_t(p_position_t(1, 5), p_position_t(1, 5), 1, TOKEN_int));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(1, 7), p_position_t(1, 7), 1, TOKEN_times)); assert(token_info == p_token_info_t(p_position_t(1, 7), p_position_t(1, 7), 1, TOKEN_times));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(2, 1), p_position_t(2, 3), 3, TOKEN_int)); assert(token_info == p_token_info_t(p_position_t(2, 1), p_position_t(2, 3), 3, TOKEN_int));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(2, 5), p_position_t(2, 5), 1, TOKEN_plus)); assert(token_info == p_token_info_t(p_position_t(2, 5), p_position_t(2, 5), 1, TOKEN_plus));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(2, 7), p_position_t(2, 9), 3, TOKEN_int)); assert(token_info == p_token_info_t(p_position_t(2, 7), p_position_t(2, 9), 3, TOKEN_int));
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(2, 10), p_position_t(2, 10), 0, TOKEN___EOF)); assert(token_info == p_token_info_t(p_position_t(2, 10), p_position_t(2, 10), 0, TOKEN___EOF));
p_context_init(&context, ""); context = p_context_new("");
assert(p_lex(&context, &token_info) == P_SUCCESS); assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info == p_token_info_t(p_position_t(1, 1), p_position_t(1, 1), 0, TOKEN___EOF)); assert(token_info == p_token_info_t(p_position_t(1, 1), p_position_t(1, 1), 0, TOKEN___EOF));
} }
+4 -3
View File
@@ -6,10 +6,11 @@
int main() int main()
{ {
char const * input = "identifier_123"; char const * input = "identifier_123";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass1\n"); printf("pass1\n");
p_context_delete(context);
return 0; return 0;
} }
+3 -3
View File
@@ -9,8 +9,8 @@ int main()
unittest unittest
{ {
string input = `identifier_123`; string input = `identifier_123`;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass1"); writeln("pass1");
} }
+7 -5
View File
@@ -6,15 +6,17 @@
int main() int main()
{ {
char const * input = "abc \"a string\" def"; char const * input = "abc \"a string\" def";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass1\n"); printf("pass1\n");
p_context_delete(context);
input = "abc \"abc def\" def"; input = "abc \"abc def\" def";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass2\n"); printf("pass2\n");
p_context_delete(context);
return 0; return 0;
} }
+5 -5
View File
@@ -9,13 +9,13 @@ int main()
unittest unittest
{ {
string input = `abc "a string" def`; string input = `abc "a string" def`;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass1"); writeln("pass1");
input = `abc "abc def" def`; input = `abc "abc def" def`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass2"); writeln("pass2");
} }
+7 -5
View File
@@ -6,15 +6,17 @@
int main() int main()
{ {
char const * input = "abc.def"; char const * input = "abc.def";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass1\n"); printf("pass1\n");
p_context_delete(context);
input = "abc . abc"; input = "abc . abc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass2\n"); printf("pass2\n");
p_context_delete(context);
return 0; return 0;
} }
+5 -5
View File
@@ -9,13 +9,13 @@ int main()
unittest unittest
{ {
string input = `abc.def`; string input = `abc.def`;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass1"); writeln("pass1");
input = `abc . abc`; input = `abc . abc`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass2"); writeln("pass2");
} }
+9 -7
View File
@@ -5,15 +5,17 @@
int main() int main()
{ {
char const * input = "x"; char const * input = "x";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 1u); assert(p_result(context) == 1u);
p_context_delete(context);
input = "fabulous"; input = "fabulous";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 8u); assert(p_result(context) == 8u);
p_context_delete(context);
return 0; return 0;
} }
+7 -7
View File
@@ -9,13 +9,13 @@ int main()
unittest unittest
{ {
string input = `x`; string input = `x`;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 1u); assert(p_result(context) == 1u);
input = `fabulous`; input = `fabulous`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 8u); assert(p_result(context) == 8u);
} }
+8 -6
View File
@@ -5,14 +5,16 @@
int main() int main()
{ {
char const * input = "x"; char const * input = "x";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_UNEXPECTED_INPUT); assert(p_parse(context) == P_UNEXPECTED_INPUT);
p_context_delete(context);
input = "123"; input = "123";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 123u); assert(p_result(context) == 123u);
p_context_delete(context);
return 0; return 0;
} }
+6 -6
View File
@@ -9,12 +9,12 @@ int main()
unittest unittest
{ {
string input = `x`; string input = `x`;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_UNEXPECTED_INPUT); assert(p_parse(context) == P_UNEXPECTED_INPUT);
input = `123`; input = `123`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 123u); assert(p_result(context) == 123u);
} }
+4 -3
View File
@@ -5,9 +5,10 @@
int main() int main()
{ {
char const * input = "\a\b\t\n\v\f\rt"; char const * input = "\a\b\t\n\v\f\rt";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+3 -3
View File
@@ -9,7 +9,7 @@ int main()
unittest unittest
{ {
string input = "\a\b\t\n\v\f\rt"; string input = "\a\b\t\n\v\f\rt";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+8 -6
View File
@@ -6,14 +6,16 @@
int main() int main()
{ {
char const * input1 = "a\n1"; char const * input1 = "a\n1";
myp1_context_t context1; myp1_context_t * context1;
myp1_context_init(&context1, (uint8_t const *)input1, strlen(input1)); context1 = myp1_context_new((uint8_t const *)input1, strlen(input1));
assert(myp1_parse(&context1) == MYP1_SUCCESS); assert(myp1_parse(context1) == MYP1_SUCCESS);
myp1_context_delete(context1);
char const * input2 = "bcb"; char const * input2 = "bcb";
myp2_context_t context2; myp2_context_t * context2;
myp2_context_init(&context2, (uint8_t const *)input2, strlen(input2)); context2 = myp2_context_new((uint8_t const *)input2, strlen(input2));
assert(myp2_parse(&context2) == MYP2_SUCCESS); assert(myp2_parse(context2) == MYP2_SUCCESS);
myp2_context_delete(context2);
return 0; return 0;
} }
+6 -6
View File
@@ -10,12 +10,12 @@ int main()
unittest unittest
{ {
string input1 = "a\n1"; string input1 = "a\n1";
myp1_context_t context1; myp1_context_t * context1;
myp1_context_init(&context1, input1); context1 = myp1_context_new(input1);
assert(myp1_parse(&context1) == MYP1_SUCCESS); assert(myp1_parse(context1) == MYP1_SUCCESS);
string input2 = "bcb"; string input2 = "bcb";
myp2_context_t context2; myp2_context_t * context2;
myp2_context_init(&context2, input2); context2 = myp2_context_new(input2);
assert(myp2_parse(&context2) == MYP2_SUCCESS); assert(myp2_parse(context2) == MYP2_SUCCESS);
} }
+16 -13
View File
@@ -6,10 +6,10 @@
int main() int main()
{ {
char const * input = "b"; char const * input = "b";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert(start->a == NULL); assert(start->a == NULL);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
assert_eq(TOKEN_b, start->pToken2->token); assert_eq(TOKEN_b, start->pToken2->token);
@@ -17,12 +17,13 @@ int main()
assert(start->pR == NULL); assert(start->pR == NULL);
assert(start->r == NULL); assert(start->r == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "abcd"; input = "abcd";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start->a != NULL); assert(start->a != NULL);
assert_eq(TOKEN_a, start->pToken1->token); assert_eq(TOKEN_a, start->pToken1->token);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
@@ -33,18 +34,20 @@ int main()
assert(start->pR == start->r); assert(start->pR == start->r);
assert_eq(TOKEN_c, start->pR->pToken1->token); assert_eq(TOKEN_c, start->pR->pToken1->token);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "bdc"; input = "bdc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start->a == NULL); assert(start->a == NULL);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
assert(start->r != NULL); assert(start->r != NULL);
assert_eq(TOKEN_d, start->pR->pToken1->token); assert_eq(TOKEN_d, start->pR->pToken1->token);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+15 -10
View File
@@ -10,10 +10,9 @@ int main()
unittest unittest
{ {
string input = "b"; string input = "b";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert(start.pToken1 is null); assert(start.pToken1 is null);
assert(start.pToken2 !is null); assert(start.pToken2 !is null);
assert_eq(TOKEN_b, start.pToken2.token); assert_eq(TOKEN_b, start.pToken2.token);
@@ -21,10 +20,12 @@ unittest
assert(start.pR is null); assert(start.pR is null);
assert(start.r is null); assert(start.r is null);
p_tree_delete(start);
input = "abcd"; input = "abcd";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start.pToken1 != null); assert(start.pToken1 != null);
assert_eq(TOKEN_a, start.pToken1.token); assert_eq(TOKEN_a, start.pToken1.token);
assert(start.pToken2 != null); assert(start.pToken2 != null);
@@ -35,12 +36,16 @@ unittest
assert(start.pR == start.r); assert(start.pR == start.r);
assert_eq(TOKEN_c, start.pR.pToken1.token); assert_eq(TOKEN_c, start.pR.pToken1.token);
p_tree_delete(start);
input = "bdc"; input = "bdc";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start.pToken1 is null); assert(start.pToken1 is null);
assert(start.pToken2 !is null); assert(start.pToken2 !is null);
assert(start.pR !is null); assert(start.pR !is null);
assert_eq(TOKEN_d, start.pR.pToken1.token); assert_eq(TOKEN_d, start.pR.pToken1.token);
p_tree_delete(start);
} }
+10 -7
View File
@@ -5,17 +5,20 @@
int main() int main()
{ {
char const * input = "b"; char const * input = "b";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "abcd"; input = "abcd";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "abdc"; input = "abdc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+7 -7
View File
@@ -9,15 +9,15 @@ int main()
unittest unittest
{ {
string input = "b"; string input = "b";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "abcd"; input = "abcd";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "abdc"; input = "abdc";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+16 -13
View File
@@ -6,22 +6,23 @@
int main() int main()
{ {
char const * input = "b"; char const * input = "b";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert(start->pToken1 == NULL); assert(start->pToken1 == NULL);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
assert_eq(TOKEN_b, start->pToken2->token); assert_eq(TOKEN_b, start->pToken2->token);
assert(start->pR3 == NULL); assert(start->pR3 == NULL);
assert(start->pR == NULL); assert(start->pR == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "abcd"; input = "abcd";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start->pToken1 != NULL); assert(start->pToken1 != NULL);
assert_eq(TOKEN_a, start->pToken1->token); assert_eq(TOKEN_a, start->pToken1->token);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
@@ -30,18 +31,20 @@ int main()
assert(start->pR == start->pR3); assert(start->pR == start->pR3);
assert_eq(TOKEN_c, start->pR->pToken1->token); assert_eq(TOKEN_c, start->pR->pToken1->token);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "bdc"; input = "bdc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start->pToken1 == NULL); assert(start->pToken1 == NULL);
assert(start->pToken2 != NULL); assert(start->pToken2 != NULL);
assert(start->pR != NULL); assert(start->pR != NULL);
assert_eq(TOKEN_d, start->pR->pToken1->token); assert_eq(TOKEN_d, start->pR->pToken1->token);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+15 -10
View File
@@ -10,20 +10,21 @@ int main()
unittest unittest
{ {
string input = "b"; string input = "b";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert(start.pToken1 is null); assert(start.pToken1 is null);
assert(start.pToken2 !is null); assert(start.pToken2 !is null);
assert_eq(TOKEN_b, start.pToken2.token); assert_eq(TOKEN_b, start.pToken2.token);
assert(start.pR3 is null); assert(start.pR3 is null);
assert(start.pR is null); assert(start.pR is null);
p_tree_delete(start);
input = "abcd"; input = "abcd";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start.pToken1 != null); assert(start.pToken1 != null);
assert_eq(TOKEN_a, start.pToken1.token); assert_eq(TOKEN_a, start.pToken1.token);
assert(start.pToken2 != null); assert(start.pToken2 != null);
@@ -32,12 +33,16 @@ unittest
assert(start.pR == start.pR3); assert(start.pR == start.pR3);
assert_eq(TOKEN_c, start.pR.pToken1.token); assert_eq(TOKEN_c, start.pR.pToken1.token);
p_tree_delete(start);
input = "bdc"; input = "bdc";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert(start.pToken1 is null); assert(start.pToken1 is null);
assert(start.pToken2 !is null); assert(start.pToken2 !is null);
assert(start.pR !is null); assert(start.pR !is null);
assert_eq(TOKEN_d, start.pR.pToken1.token); assert_eq(TOKEN_d, start.pR.pToken1.token);
p_tree_delete(start);
} }
+7 -5
View File
@@ -5,13 +5,15 @@
int main() int main()
{ {
char const * input = "aba"; char const * input = "aba";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "abb"; input = "abb";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+5 -5
View File
@@ -9,11 +9,11 @@ int main()
unittest unittest
{ {
string input = "aba"; string input = "aba";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "abb"; input = "abb";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+13 -10
View File
@@ -5,20 +5,23 @@
int main() int main()
{ {
char const * input = "a"; char const * input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context).row == 1); assert(p_position(context).row == 1);
assert(p_position(&context).col == 2); assert(p_position(context).col == 2);
assert(context.token == TOKEN___EOF); assert(context->token == TOKEN___EOF);
p_context_delete(context);
input = "a b"; input = "a b";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "bb"; input = "bb";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+8 -8
View File
@@ -9,17 +9,17 @@ int main()
unittest unittest
{ {
string input = "a"; string input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(1, 2)); assert(p_position(context) == p_position_t(1, 2));
assert(context.token == TOKEN___EOF); assert(context.token == TOKEN___EOF);
input = "a b"; input = "a b";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "bb"; input = "bb";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+4 -3
View File
@@ -5,9 +5,10 @@
int main() int main()
{ {
char const * input = "ab"; char const * input = "ab";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+3 -3
View File
@@ -9,7 +9,7 @@ int main()
unittest unittest
{ {
string input = "ab"; string input = "ab";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+30 -23
View File
@@ -6,51 +6,58 @@
int main() int main()
{ {
char const * input = ""; char const * input = "";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "{}"; input = "{}";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context)->id == JSON_OBJECT); assert(p_result(context)->id == JSON_OBJECT);
p_context_delete(context);
input = "[]"; input = "[]";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context)->id == JSON_ARRAY); assert(p_result(context)->id == JSON_ARRAY);
p_context_delete(context);
input = "-45.6"; input = "-45.6";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context)->id == JSON_NUMBER); assert(p_result(context)->id == JSON_NUMBER);
assert(p_result(&context)->number == -45.6); assert(p_result(context)->number == -45.6);
p_context_delete(context);
input = "2E-2"; input = "2E-2";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context)->id == JSON_NUMBER); assert(p_result(context)->id == JSON_NUMBER);
assert(p_result(&context)->number == 0.02); assert(p_result(context)->number == 0.02);
p_context_delete(context);
input = "{\"hi\":true}"; input = "{\"hi\":true}";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
JSONValue * o = p_result(&context); JSONValue * o = p_result(context);
assert(o->id == JSON_OBJECT); assert(o->id == JSON_OBJECT);
assert_eq(1, o->object.size); assert_eq(1, o->object.size);
assert(strcmp(o->object.entries[0].name, "hi") == 0); assert(strcmp(o->object.entries[0].name, "hi") == 0);
assert(o->object.entries[0].value->id == JSON_TRUE); assert(o->object.entries[0].value->id == JSON_TRUE);
p_context_delete(context);
input = "{\"ff\": false, \"nn\": null}"; input = "{\"ff\": false, \"nn\": null}";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
o = p_result(&context); o = p_result(context);
assert(o->id == JSON_OBJECT); assert(o->id == JSON_OBJECT);
assert_eq(2, o->object.size); assert_eq(2, o->object.size);
assert(strcmp(o->object.entries[0].name, "ff") == 0); assert(strcmp(o->object.entries[0].name, "ff") == 0);
assert(o->object.entries[0].value->id == JSON_FALSE); assert(o->object.entries[0].value->id == JSON_FALSE);
assert(strcmp(o->object.entries[1].name, "nn") == 0); assert(strcmp(o->object.entries[1].name, "nn") == 0);
assert(o->object.entries[1].value->id == JSON_NULL); assert(o->object.entries[1].value->id == JSON_NULL);
p_context_delete(context);
return 0; return 0;
} }
+25 -25
View File
@@ -10,45 +10,45 @@ int main()
unittest unittest
{ {
string input = ``; string input = ``;
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = `{}`; input = `{}`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONObject)p_result(&context)); assert(cast(JSONObject)p_result(context));
input = `[]`; input = `[]`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONArray)p_result(&context)); assert(cast(JSONArray)p_result(context));
input = `-45.6`; input = `-45.6`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONNumber)p_result(&context)); assert(cast(JSONNumber)p_result(context));
assert((cast(JSONNumber)p_result(&context)).value == -45.6); assert((cast(JSONNumber)p_result(context)).value == -45.6);
input = `2E-2`; input = `2E-2`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONNumber)p_result(&context)); assert(cast(JSONNumber)p_result(context));
assert((cast(JSONNumber)p_result(&context)).value == 0.02); assert((cast(JSONNumber)p_result(context)).value == 0.02);
input = `{"hi":true}`; input = `{"hi":true}`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONObject)p_result(&context)); assert(cast(JSONObject)p_result(context));
JSONObject o = cast(JSONObject)p_result(&context); JSONObject o = cast(JSONObject)p_result(context);
assert(o.value["hi"]); assert(o.value["hi"]);
assert(cast(JSONTrue)o.value["hi"]); assert(cast(JSONTrue)o.value["hi"]);
input = `{"ff": false, "nn": null}`; input = `{"ff": false, "nn": null}`;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(cast(JSONObject)p_result(&context)); assert(cast(JSONObject)p_result(context));
o = cast(JSONObject)p_result(&context); o = cast(JSONObject)p_result(context);
assert(o.value["ff"]); assert(o.value["ff"]);
assert(cast(JSONFalse)o.value["ff"]); assert(cast(JSONFalse)o.value["ff"]);
assert(o.value["nn"]); assert(o.value["nn"]);
+13 -10
View File
@@ -5,20 +5,23 @@
int main() int main()
{ {
char const * input = "a"; char const * input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 1u); assert(p_result(context) == 1u);
p_context_delete(context);
input = ""; input = "";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 0u); assert(p_result(context) == 0u);
p_context_delete(context);
input = "aaaaaaaaaaaaaaaa"; input = "aaaaaaaaaaaaaaaa";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 16u); assert(p_result(context) == 16u);
p_context_delete(context);
return 0; return 0;
} }
+10 -10
View File
@@ -9,18 +9,18 @@ int main()
unittest unittest
{ {
string input = "a"; string input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 1u); assert(p_result(context) == 1u);
input = ""; input = "";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 0u); assert(p_result(context) == 0u);
input = "aaaaaaaaaaaaaaaa"; input = "aaaaaaaaaaaaaaaa";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
assert(p_result(&context) == 16u); assert(p_result(context) == 16u);
} }
+7 -5
View File
@@ -6,15 +6,17 @@
int main() int main()
{ {
char const * input = "abcdef"; char const * input = "abcdef";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass1\n"); printf("pass1\n");
p_context_delete(context);
input = "defabcdef"; input = "defabcdef";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass2\n"); printf("pass2\n");
p_context_delete(context);
return 0; return 0;
} }
+5 -5
View File
@@ -9,13 +9,13 @@ int main()
unittest unittest
{ {
string input = "abcdef"; string input = "abcdef";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass1"); writeln("pass1");
input = "defabcdef"; input = "defabcdef";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass2"); writeln("pass2");
} }
+4 -3
View File
@@ -5,9 +5,10 @@
int main() int main()
{ {
char const * input = "defghidef"; char const * input = "defghidef";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
return 0; return 0;
} }
+3 -3
View File
@@ -9,7 +9,7 @@ int main()
unittest unittest
{ {
string input = "defghidef"; string input = "defghidef";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
} }
+6 -5
View File
@@ -6,14 +6,15 @@
int main() int main()
{ {
char const * input = "hi"; char const * input = "hi";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
Top * top = p_result(&context); Top * top = p_result(context);
assert(top->pToken != NULL); assert(top->pToken != NULL);
assert_eq(TOKEN_hi, top->pToken->token); assert_eq(TOKEN_hi, top->pToken->token);
p_free_tree(top); p_tree_delete(top);
p_context_delete(context);
return 0; return 0;
} }
+4 -4
View File
@@ -10,10 +10,10 @@ int main()
unittest unittest
{ {
string input = "hi"; string input = "hi";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
Top * top = p_result(&context); Top * top = p_result(context);
assert(top.pToken !is null); assert(top.pToken !is null);
assert_eq(TOKEN_hi, top.pToken.token); assert_eq(TOKEN_hi, top.pToken.token);
} }
+13 -10
View File
@@ -6,22 +6,25 @@
int main() int main()
{ {
char const * input = "bbbb"; char const * input = "bbbb";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
int result = p_result(&context); int result = p_result(context);
assert_eq(8, result); assert_eq(8, result);
p_context_delete(context);
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse_Bs(&context) == P_SUCCESS); assert(p_parse_Bs(context) == P_SUCCESS);
result = p_result_Bs(&context); result = p_result_Bs(context);
assert_eq(8, result); assert_eq(8, result);
p_context_delete(context);
input = "c"; input = "c";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse_R(&context) == P_SUCCESS); assert(p_parse_R(context) == P_SUCCESS);
result = p_result_R(&context); result = p_result_R(context);
assert_eq(3, result); assert_eq(3, result);
p_context_delete(context);
return 0; return 0;
} }
+10 -10
View File
@@ -10,20 +10,20 @@ int main()
unittest unittest
{ {
string input = "bbbb"; string input = "bbbb";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
int result = p_result(&context); int result = p_result(context);
assert(result == 8); assert(result == 8);
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse_Bs(&context) == P_SUCCESS); assert(p_parse_Bs(context) == P_SUCCESS);
result = p_result_Bs(&context); result = p_result_Bs(context);
assert(result == 8); assert(result == 8);
input = "c"; input = "c";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse_R(&context) == P_SUCCESS); assert(p_parse_R(context) == P_SUCCESS);
result = p_result_R(&context); result = p_result_R(context);
assert(result == 3); assert(result == 3);
} }
+16 -13
View File
@@ -6,32 +6,35 @@
int main() int main()
{ {
char const * input = "bbbb"; char const * input = "bbbb";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert_not_null(start->bs); assert_not_null(start->bs);
assert_not_null(start->bs->b); assert_not_null(start->bs->b);
assert_not_null(start->bs->bs->b); assert_not_null(start->bs->bs->b);
assert_not_null(start->bs->bs->bs->b); assert_not_null(start->bs->bs->bs->b);
assert_not_null(start->bs->bs->bs->bs->b); assert_not_null(start->bs->bs->bs->bs->b);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse_Bs(&context) == P_SUCCESS); assert(p_parse_Bs(context) == P_SUCCESS);
Bs * bs = p_result_Bs(&context); Bs * bs = p_result_Bs(context);
assert_not_null(bs->b); assert_not_null(bs->b);
assert_not_null(bs->bs->b); assert_not_null(bs->bs->b);
assert_not_null(bs->bs->bs->b); assert_not_null(bs->bs->bs->b);
assert_not_null(bs->bs->bs->bs->b); assert_not_null(bs->bs->bs->bs->b);
p_free_tree_Bs(bs); p_tree_delete_Bs(bs);
p_context_delete(context);
input = "c"; input = "c";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse_R(&context) == P_SUCCESS); assert(p_parse_R(context) == P_SUCCESS);
R * r = p_result_R(&context); R * r = p_result_R(context);
assert_not_null(r->c); assert_not_null(r->c);
p_free_tree_R(r); p_tree_delete_R(r);
p_context_delete(context);
return 0; return 0;
} }
+15 -10
View File
@@ -10,27 +10,32 @@ int main()
unittest unittest
{ {
string input = "bbbb"; string input = "bbbb";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert(start.bs); assert(start.bs);
assert(start.bs.b); assert(start.bs.b);
assert(start.bs.bs.b); assert(start.bs.bs.b);
assert(start.bs.bs.bs.b); assert(start.bs.bs.bs.b);
assert(start.bs.bs.bs.bs.b); assert(start.bs.bs.bs.bs.b);
p_context_init(&context, input); p_tree_delete(start);
assert(p_parse_Bs(&context) == P_SUCCESS);
Bs * bs = p_result_Bs(&context); context = p_context_new(input);
assert(p_parse_Bs(context) == P_SUCCESS);
Bs * bs = p_result_Bs(context);
assert(bs.b); assert(bs.b);
assert(bs.bs.b); assert(bs.bs.b);
assert(bs.bs.bs.b); assert(bs.bs.bs.b);
assert(bs.bs.bs.bs.b); assert(bs.bs.bs.bs.b);
p_tree_delete_Bs(bs);
input = "c"; input = "c";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse_R(&context) == P_SUCCESS); assert(p_parse_R(context) == P_SUCCESS);
R * r = p_result_R(&context); R * r = p_result_R(context);
assert(r.c); assert(r.c);
p_tree_delete_R(r);
} }
+46
View File
@@ -0,0 +1,46 @@
#include "testparser.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char const * input =
"# c1\n"
"# c2\n"
"\n"
"first\n"
"\n \n \n"
" # s1\n"
" # s2\n"
"second\n";
p_context_t * context;
context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(context);
assert(start->pIDs);
assert(start->pIDs->id);
#ifdef __cplusplus
assert(start->pIDs->id->comments == "# c1\n# c2\n");
#else
assert(start->pIDs->id->comments);
assert(strcmp(start->pIDs->id->comments, "# c1\n# c2\n") == 0);
#endif
assert(start->pIDs->pIDs);
assert(start->pIDs->pIDs->id);
#ifdef __cplusplus
assert(start->pIDs->pIDs->id->comments == "# s1\n# s2\n");
#else
assert(start->pIDs->pIDs->id->comments);
assert(strcmp(start->pIDs->pIDs->id->comments, "# s1\n# s2\n") == 0);
#endif
#ifndef __cplusplus
free(context->comments);
#endif
p_context_delete(context);
p_tree_delete(start);
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
import testparser;
import std.stdio;
int main()
{
return 0;
}
unittest
{
string input =
"# c1\n" ~
"# c2\n" ~
"\n" ~
"first\n" ~
"\n \n \n" ~
" # s1\n" ~
" # s2\n" ~
"second\n";
p_context_t * context = p_context_new(input);
assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(context);
assert(start.pIDs);
assert(start.pIDs.id);
assert(start.pIDs.id.comments == "# c1\n# c2\n");
assert(start.pIDs.pIDs);
assert(start.pIDs.pIDs.id);
assert(start.pIDs.pIDs.id.comments == "# s1\n# s2\n");
p_tree_delete(start);
}
+16 -13
View File
@@ -6,10 +6,10 @@
int main() int main()
{ {
char const * input = "a, ((b)), b"; char const * input = "a, ((b)), b";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
Start * start = p_result(&context); Start * start = p_result(context);
assert(start->pItems1 != NULL); assert(start->pItems1 != NULL);
assert(start->pItems != NULL); assert(start->pItems != NULL);
Items * items = start->pItems; Items * items = start->pItems;
@@ -33,20 +33,22 @@ int main()
assert_eq(22, itemsmore->pItem->pToken1->pvalue); assert_eq(22, itemsmore->pItem->pToken1->pvalue);
assert(itemsmore->pItemsMore == NULL); assert(itemsmore->pItemsMore == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = ""; input = "";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start->pItems == NULL); assert(start->pItems == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "2 1"; input = "2 1";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start->pItems != NULL); assert(start->pItems != NULL);
assert(start->pItems->pItem != NULL); assert(start->pItems->pItem != NULL);
assert(start->pItems->pItem->pDual != NULL); assert(start->pItems->pItem->pDual != NULL);
@@ -55,7 +57,8 @@ int main()
assert(start->pItems->pItem->pDual->pTwo2 == NULL); assert(start->pItems->pItem->pDual->pTwo2 == NULL);
assert(start->pItems->pItem->pDual->pOne1 == NULL); assert(start->pItems->pItem->pDual->pOne1 == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+15 -10
View File
@@ -10,10 +10,9 @@ int main()
unittest unittest
{ {
string input = "a, ((b)), b"; string input = "a, ((b)), b";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(P_SUCCESS, p_parse(&context)); Start * start = p_result(context);
Start * start = p_result(&context);
assert(start.pItems1 !is null); assert(start.pItems1 !is null);
assert(start.pItems !is null); assert(start.pItems !is null);
Items * items = start.pItems; Items * items = start.pItems;
@@ -37,16 +36,20 @@ unittest
assert_eq(22, itemsmore.pItem.pToken1.pvalue); assert_eq(22, itemsmore.pItem.pToken1.pvalue);
assert(itemsmore.pItemsMore is null); assert(itemsmore.pItemsMore is null);
p_tree_delete(start);
input = ""; input = "";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start.pItems is null); assert(start.pItems is null);
p_tree_delete(start);
input = "2 1"; input = "2 1";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start.pItems !is null); assert(start.pItems !is null);
assert(start.pItems.pItem !is null); assert(start.pItems.pItem !is null);
assert(start.pItems.pItem.pDual !is null); assert(start.pItems.pItem.pDual !is null);
@@ -54,4 +57,6 @@ unittest
assert(start.pItems.pItem.pDual.pOne2 !is null); assert(start.pItems.pItem.pDual.pOne2 !is null);
assert(start.pItems.pItem.pDual.pTwo2 is null); assert(start.pItems.pItem.pDual.pTwo2 is null);
assert(start.pItems.pItem.pDual.pOne1 is null); assert(start.pItems.pItem.pDual.pOne1 is null);
p_tree_delete(start);
} }
@@ -6,14 +6,15 @@
int main() int main()
{ {
char const * input = "ab"; char const * input = "ab";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
Start * start = p_result(&context); Start * start = p_result(context);
assert(start->a != NULL); assert(start->a != NULL);
assert(*start->a->pvalue == 1); assert(*start->a->pvalue == 1);
assert(start->b != NULL); assert(start->b != NULL);
assert(*start->b->pvalue == 2); assert(*start->b->pvalue == 2);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
} }
+6 -5
View File
@@ -6,16 +6,17 @@
int main() int main()
{ {
char const * input = "\na\nb\nc"; char const * input = "\na\nb\nc";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert_eq(TOKEN_a, start->first->pToken->token); assert_eq(TOKEN_a, start->first->pToken->token);
assert_eq(TOKEN_b, start->second->pToken->token); assert_eq(TOKEN_b, start->second->pToken->token);
assert_eq(TOKEN_c, start->third->pToken->token); assert_eq(TOKEN_c, start->third->pToken->token);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+5 -4
View File
@@ -10,12 +10,13 @@ int main()
unittest unittest
{ {
string input = "\na\nb\nc"; string input = "\na\nb\nc";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert_eq(TOKEN_a, start.first.pToken.token); assert_eq(TOKEN_a, start.first.pToken.token);
assert_eq(TOKEN_b, start.second.pToken.token); assert_eq(TOKEN_b, start.second.pToken.token);
assert_eq(TOKEN_c, start.third.pToken.token); assert_eq(TOKEN_c, start.third.pToken.token);
p_tree_delete(start);
} }
+21 -17
View File
@@ -6,10 +6,10 @@
int main() int main()
{ {
char const * input = "\na\n bb ccc"; char const * input = "\na\n bb ccc";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert_eq(2, start->pT1->pToken->position.row); assert_eq(2, start->pT1->pToken->position.row);
assert_eq(1, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
@@ -30,12 +30,13 @@ int main()
assert_eq(3, start->end_position.row); assert_eq(3, start->end_position.row);
assert_eq(8, start->end_position.col); assert_eq(8, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "a\nbb"; input = "a\nbb";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(1, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
@@ -56,12 +57,13 @@ int main()
assert_eq(2, start->end_position.row); assert_eq(2, start->end_position.row);
assert_eq(2, start->end_position.col); assert_eq(2, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "a\nc\nc"; input = "a\nc\nc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(1, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
@@ -82,12 +84,13 @@ int main()
assert_eq(3, start->end_position.row); assert_eq(3, start->end_position.row);
assert_eq(1, start->end_position.col); assert_eq(1, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "a"; input = "a";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(1, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
@@ -104,7 +107,8 @@ int main()
assert_eq(1, start->end_position.row); assert_eq(1, start->end_position.row);
assert_eq(1, start->end_position.col); assert_eq(1, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+20 -13
View File
@@ -10,10 +10,9 @@ int main()
unittest unittest
{ {
string input = "\na\n bb ccc"; string input = "\na\n bb ccc";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert_eq(2, start.pT1.pToken.position.row); assert_eq(2, start.pT1.pToken.position.row);
assert_eq(1, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
@@ -34,10 +33,12 @@ unittest
assert_eq(3, start.end_position.row); assert_eq(3, start.end_position.row);
assert_eq(8, start.end_position.col); assert_eq(8, start.end_position.col);
p_tree_delete(start);
input = "a\nbb"; input = "a\nbb";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(1, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
@@ -58,10 +59,12 @@ unittest
assert_eq(2, start.end_position.row); assert_eq(2, start.end_position.row);
assert_eq(2, start.end_position.col); assert_eq(2, start.end_position.col);
p_tree_delete(start);
input = "a\nc\nc"; input = "a\nc\nc";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(1, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
@@ -82,10 +85,12 @@ unittest
assert_eq(3, start.end_position.row); assert_eq(3, start.end_position.row);
assert_eq(1, start.end_position.col); assert_eq(1, start.end_position.col);
p_tree_delete(start);
input = "a"; input = "a";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(1, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(1, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
@@ -101,4 +106,6 @@ unittest
assert_eq(1, start.position.col); assert_eq(1, start.position.col);
assert_eq(1, start.end_position.row); assert_eq(1, start.end_position.row);
assert_eq(1, start.end_position.col); assert_eq(1, start.end_position.col);
p_tree_delete(start);
} }
+6 -5
View File
@@ -369,11 +369,11 @@ int main(int argc, char * argv[])
{"size_t_to_ulong", TOKEN_ulong}, {"size_t_to_ulong", TOKEN_ulong},
{"main", TOKEN_int}, {"main", TOKEN_int},
}; };
p_context_t context; p_context_t * context;
p_context_init(&context, (const uint8_t *)input, strlen(input)); context = p_context_new((const uint8_t *)input, strlen(input));
size_t result = p_parse(&context); size_t result = p_parse(context);
assert_eq(P_SUCCESS, result); assert_eq(P_SUCCESS, result);
PModule * pmod = p_result(&context); PModule * pmod = p_result(context);
PModuleItems * pmis = pmod->pModuleItems; PModuleItems * pmis = pmod->pModuleItems;
PFunctionDefinition ** pfds; PFunctionDefinition ** pfds;
size_t n_pfds = 0u; size_t n_pfds = 0u;
@@ -412,7 +412,8 @@ int main(int argc, char * argv[])
} }
free(pfds); free(pfds);
p_free_tree(pmod); p_tree_delete(pmod);
p_context_delete(context);
return 0; return 0;
} }
+5 -4
View File
@@ -374,11 +374,11 @@ def main() -> int
Expected("size_t_to_ulong", TOKEN_ulong), Expected("size_t_to_ulong", TOKEN_ulong),
Expected("main", TOKEN_int), Expected("main", TOKEN_int),
]; ];
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
size_t result = p_parse(&context); size_t result = p_parse(context);
assert_eq(P_SUCCESS, result); assert_eq(P_SUCCESS, result);
PModule * pmod = p_result(&context); PModule * pmod = p_result(context);
PModuleItems * pmis = pmod.pModuleItems; PModuleItems * pmis = pmod.pModuleItems;
PFunctionDefinition *[] pfds; PFunctionDefinition *[] pfds;
while (pmis !is null) while (pmis !is null)
@@ -405,4 +405,5 @@ def main() -> int
stderr.writeln("Index ", i, ": expected ", expected[i].name, "/", expected[i].token, ", got ", pfds[i].name.pvalue.s, "/", pfds[i].returntype.pType.pTypeBase.pToken1.token); stderr.writeln("Index ", i, ": expected ", expected[i].name, "/", expected[i].token, ", got ", pfds[i].name.pvalue.s, "/", pfds[i].returntype.pType.pTypeBase.pToken1.token);
} }
} }
p_tree_delete(pmod);
} }
+16 -13
View File
@@ -6,10 +6,10 @@
int main() int main()
{ {
char const * input = "a, ((b)), b"; char const * input = "a, ((b)), b";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
PStartS * start = p_result(&context); PStartS * start = p_result(context);
assert(start->pItems1 != NULL); assert(start->pItems1 != NULL);
assert(start->pItems != NULL); assert(start->pItems != NULL);
PItemsS * items = start->pItems; PItemsS * items = start->pItems;
@@ -33,20 +33,22 @@ int main()
assert_eq(22, itemsmore->pItem->pToken1->pvalue); assert_eq(22, itemsmore->pItem->pToken1->pvalue);
assert(itemsmore->pItemsMore == NULL); assert(itemsmore->pItemsMore == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = ""; input = "";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start->pItems == NULL); assert(start->pItems == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "2 1"; input = "2 1";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start->pItems != NULL); assert(start->pItems != NULL);
assert(start->pItems->pItem != NULL); assert(start->pItems->pItem != NULL);
assert(start->pItems->pItem->pDual != NULL); assert(start->pItems->pItem->pDual != NULL);
@@ -55,7 +57,8 @@ int main()
assert(start->pItems->pItem->pDual->pTwo2 == NULL); assert(start->pItems->pItem->pDual->pTwo2 == NULL);
assert(start->pItems->pItem->pDual->pOne1 == NULL); assert(start->pItems->pItem->pDual->pOne1 == NULL);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+15 -10
View File
@@ -10,10 +10,9 @@ int main()
unittest unittest
{ {
string input = "a, ((b)), b"; string input = "a, ((b)), b";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert_eq(P_SUCCESS, p_parse(context));
assert_eq(P_SUCCESS, p_parse(&context)); PStartS * start = p_result(context);
PStartS * start = p_result(&context);
assert(start.pItems1 !is null); assert(start.pItems1 !is null);
assert(start.pItems !is null); assert(start.pItems !is null);
PItemsS * items = start.pItems; PItemsS * items = start.pItems;
@@ -37,16 +36,20 @@ unittest
assert_eq(22, itemsmore.pItem.pToken1.pvalue); assert_eq(22, itemsmore.pItem.pToken1.pvalue);
assert(itemsmore.pItemsMore is null); assert(itemsmore.pItemsMore is null);
p_tree_delete(start);
input = ""; input = "";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start.pItems is null); assert(start.pItems is null);
p_tree_delete(start);
input = "2 1"; input = "2 1";
p_context_init(&context, input); context = p_context_new(input);
assert_eq(P_SUCCESS, p_parse(&context)); assert_eq(P_SUCCESS, p_parse(context));
start = p_result(&context); start = p_result(context);
assert(start.pItems !is null); assert(start.pItems !is null);
assert(start.pItems.pItem !is null); assert(start.pItems.pItem !is null);
assert(start.pItems.pItem.pDual !is null); assert(start.pItems.pItem.pDual !is null);
@@ -54,4 +57,6 @@ unittest
assert(start.pItems.pItem.pDual.pOne2 !is null); assert(start.pItems.pItem.pDual.pOne2 !is null);
assert(start.pItems.pItem.pDual.pTwo2 is null); assert(start.pItems.pItem.pDual.pTwo2 is null);
assert(start.pItems.pItem.pDual.pOne1 is null); assert(start.pItems.pItem.pDual.pOne1 is null);
p_tree_delete(start);
} }
+11 -9
View File
@@ -6,10 +6,10 @@
int main() int main()
{ {
char const * input = "abbccc"; char const * input = "abbccc";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(context);
assert_eq(1, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(1, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
@@ -43,12 +43,13 @@ int main()
assert_eq(1, start->end_position.row); assert_eq(1, start->end_position.row);
assert_eq(6, start->end_position.col); assert_eq(6, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
input = "\n\n bb\nc\ncc\n\n a"; input = "\n\n bb\nc\ncc\n\n a";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(3, start->pT1->pToken->position.row); assert_eq(3, start->pT1->pToken->position.row);
assert_eq(3, start->pT1->pToken->position.col); assert_eq(3, start->pT1->pToken->position.col);
@@ -82,7 +83,8 @@ int main()
assert_eq(7, start->end_position.row); assert_eq(7, start->end_position.row);
assert_eq(6, start->end_position.col); assert_eq(6, start->end_position.col);
p_free_tree(start); p_tree_delete(start);
p_context_delete(context);
return 0; return 0;
} }
+10 -7
View File
@@ -10,10 +10,9 @@ int main()
unittest unittest
{ {
string input = "abbccc"; string input = "abbccc";
p_context_t context; p_context_t * context = p_context_new(input);
p_context_init(&context, input); assert(p_parse(context) == P_SUCCESS);
assert(p_parse(&context) == P_SUCCESS); Start * start = p_result(context);
Start * start = p_result(&context);
assert_eq(1, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(1, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
@@ -47,10 +46,12 @@ unittest
assert_eq(1, start.end_position.row); assert_eq(1, start.end_position.row);
assert_eq(6, start.end_position.col); assert_eq(6, start.end_position.col);
p_tree_delete(start);
input = "\n\n bb\nc\ncc\n\n a"; input = "\n\n bb\nc\ncc\n\n a";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
start = p_result(&context); start = p_result(context);
assert_eq(3, start.pT1.pToken.position.row); assert_eq(3, start.pT1.pToken.position.row);
assert_eq(3, start.pT1.pToken.position.col); assert_eq(3, start.pT1.pToken.position.col);
@@ -83,4 +84,6 @@ unittest
assert_eq(3, start.position.col); assert_eq(3, start.position.col);
assert_eq(7, start.end_position.row); assert_eq(7, start.end_position.row);
assert_eq(6, start.end_position.col); assert_eq(6, start.end_position.col);
p_tree_delete(start);
} }
+7 -5
View File
@@ -6,15 +6,17 @@
int main() int main()
{ {
char const * input = "abcdef"; char const * input = "abcdef";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass1\n"); printf("pass1\n");
p_context_delete(context);
input = "abcabcdef"; input = "abcabcdef";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
printf("pass2\n"); printf("pass2\n");
p_context_delete(context);
return 0; return 0;
} }
+5 -5
View File
@@ -9,13 +9,13 @@ int main()
unittest unittest
{ {
string input = "abcdef"; string input = "abcdef";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass1"); writeln("pass1");
input = "abcabcdef"; input = "abcabcdef";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
writeln("pass2"); writeln("pass2");
} }
+20
View File
@@ -0,0 +1,20 @@
#include "testparser.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char const * input = "aaa\n\n\na\n # comment 1\na a aa\n\naa\n# comment 2\na\n";
p_context_t * context;
context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(context) == P_SUCCESS);
fprintf(stderr, "comments: %s", context->comments);
fprintf(stderr, "acount: %u\n", context->acount);
free(context->comments);
p_context_delete(context);
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
import testparser;
import std.stdio;
import testutils;
int main()
{
return 0;
}
unittest
{
string input = "aaa\n\n\na\n # comment 1\na a aa\n\naa\n# comment 2\na\n";
p_context_t * context;
context = p_context_new(input);
assert(p_parse(context) == P_SUCCESS);
stderr.writeln("comments: ", context.comments);
stderr.writeln("acount: ", context.acount);
}
+8 -6
View File
@@ -6,14 +6,16 @@
int main() int main()
{ {
char const * input = "aacc"; char const * input = "aacc";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "abc"; input = "abc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_USER_TERMINATED); assert(p_parse(context) == P_USER_TERMINATED);
assert(p_user_terminate_code(&context) == 4200); assert(p_user_terminate_code(context) == 4200);
p_context_delete(context);
return 0; return 0;
} }
+6 -6
View File
@@ -9,12 +9,12 @@ int main()
unittest unittest
{ {
string input = "aacc"; string input = "aacc";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "abc"; input = "abc";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_USER_TERMINATED); assert(p_parse(context) == P_USER_TERMINATED);
assert(p_user_terminate_code(&context) == 4200); assert(p_user_terminate_code(context) == 4200);
} }
+8 -6
View File
@@ -6,14 +6,16 @@
int main() int main()
{ {
char const * input = "a"; char const * input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
p_context_delete(context);
input = "b"; input = "b";
p_context_init(&context, (uint8_t const *)input, strlen(input)); context = p_context_new((uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_USER_TERMINATED); assert(p_parse(context) == P_USER_TERMINATED);
assert(p_user_terminate_code(&context) == 8675309); assert(p_user_terminate_code(context) == 8675309);
p_context_delete(context);
return 0; return 0;
} }
+6 -6
View File
@@ -9,12 +9,12 @@ int main()
unittest unittest
{ {
string input = "a"; string input = "a";
p_context_t context; p_context_t * context;
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(context) == P_SUCCESS);
input = "b"; input = "b";
p_context_init(&context, input); context = p_context_new(input);
assert(p_parse(&context) == P_USER_TERMINATED); assert(p_parse(context) == P_USER_TERMINATED);
assert(p_user_terminate_code(&context) == 8675309); assert(p_user_terminate_code(context) == 8675309);
} }
+29
View File
@@ -0,0 +1,29 @@
#include "testparser.h"
#include <assert.h>
#include <string.h>
int main()
{
p_token_info_t token_info;
char const * input = "42 f s";
p_context_t * context;
context = p_context_new((uint8_t const *)input, strlen(input));
/* Default ptype value extracted with p_value_get(). */
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_num);
assert(p_value_get(&token_info.pvalue) == 42);
/* Named ptype values extracted with p_value_get_XXX(). */
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_flt);
assert(p_value_get_float(&token_info.pvalue) == 1.5);
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_str);
assert(strcmp(p_value_get_string(&token_info.pvalue), "hello") == 0);
p_context_delete(context);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
import testparser;
import std.stdio;
int main()
{
return 0;
}
unittest
{
p_token_info_t token_info;
string input = "42 f s";
p_context_t * context;
context = p_context_new(input);
/* Default ptype value extracted with p_value_get(). */
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_num);
assert(p_value_get(&token_info.pvalue) == 42);
/* Named ptype values extracted with p_value_get_XXX(). */
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_flt);
assert(p_value_get_float(&token_info.pvalue) == 1.5);
assert(p_lex(context, &token_info) == P_SUCCESS);
assert(token_info.token == TOKEN_str);
assert(p_value_get_string(&token_info.pvalue) == "hello");
}