12 Commits
23 changed files with 590 additions and 338 deletions

No files matched your search

+28
View File
@@ -1,3 +1,31 @@
## v2.1.1
### Fixes
- Field aliases for AST node fields could alias incorrect field when multiple rule alternatives present for one rule set (#33)
## v2.1.0
### Improvements
- Report rule name and line number for conflicting AST node field positions errors (#32)
## v2.0.0
### Improvements
- Log conflicting rules on reduce/reduce conflict (#31)
- Use 1-based row and column values for position values (#30)
### Fixes
- Fix named optional rules (#29)
### Upgrading
- Adjust all uses of p_position_t row and col values to expect 1-based instead
of 0-based values.
## v1.5.1 ## v1.5.1
### Improvements ### Improvements
+20 -18
View File
@@ -1,34 +1,36 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
diff-lcs (1.5.0) date (3.4.1)
docile (1.4.0) diff-lcs (1.5.1)
psych (5.1.0) docile (1.4.1)
psych (5.2.2)
date
stringio stringio
rake (13.0.6) rake (13.2.1)
rdoc (6.5.0) rdoc (6.10.0)
psych (>= 4.0.0) psych (>= 4.0.0)
redcarpet (3.6.0) redcarpet (3.6.0)
rspec (3.12.0) rspec (3.13.0)
rspec-core (~> 3.12.0) rspec-core (~> 3.13.0)
rspec-expectations (~> 3.12.0) rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.12.0) rspec-mocks (~> 3.13.0)
rspec-core (3.12.2) rspec-core (3.13.2)
rspec-support (~> 3.12.0) rspec-support (~> 3.13.0)
rspec-expectations (3.12.3) rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0) rspec-support (~> 3.13.0)
rspec-mocks (3.12.6) rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0) rspec-support (~> 3.13.0)
rspec-support (3.12.1) rspec-support (3.13.2)
simplecov (0.22.0) simplecov (0.22.0)
docile (~> 1.1) docile (~> 1.1)
simplecov-html (~> 0.11) simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1) simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3) simplecov-html (0.13.1)
simplecov_json_formatter (0.1.4) simplecov_json_formatter (0.1.4)
stringio (3.0.7) stringio (3.1.2)
syntax (1.2.2) syntax (1.2.2)
PLATFORMS PLATFORMS
+4 -2
View File
@@ -60,6 +60,8 @@ void <%= @grammar.prefix %>context_init(<%= @grammar.prefix %>context_t * contex
/* Lexer initialization. */ /* Lexer initialization. */
newcontext.input = input; newcontext.input = input;
newcontext.input_length = input_length; newcontext.input_length = input_length;
newcontext.text_position.row = 1u;
newcontext.text_position.col = 1u;
newcontext.mode = <%= @lexer.mode_id("default") %>; newcontext.mode = <%= @lexer.mode_id("default") %>;
/* Copy to the user's context structure. */ /* Copy to the user's context structure. */
@@ -365,7 +367,7 @@ static size_t find_longest_match(<%= @grammar.prefix %>context_t * context,
if (code_point == '\n') if (code_point == '\n')
{ {
attempt_match.delta_position.row++; attempt_match.delta_position.row++;
attempt_match.delta_position.col = 0u; attempt_match.delta_position.col = 1u;
} }
else else
{ {
@@ -567,7 +569,7 @@ size_t <%= @grammar.prefix %>lex(<%= @grammar.prefix %>context_t * context, <%=
*************************************************************************/ *************************************************************************/
/** Invalid position value. */ /** Invalid position value. */
#define INVALID_POSITION (<%= @grammar.prefix %>position_t){0xFFFFFFFFu, 0xFFFFFFFFu} #define INVALID_POSITION (<%= @grammar.prefix %>position_t){0u, 0u}
/** Reduce ID type. */ /** Reduce ID type. */
typedef <%= get_type_for(@parser.reduce_table.size) %> reduce_id_t; typedef <%= get_type_for(@parser.reduce_table.size) %> reduce_id_t;
+5 -3
View File
@@ -65,12 +65,12 @@ public struct <%= @grammar.prefix %>position_t
uint col; uint col;
/** Invalid position value. */ /** Invalid position value. */
enum INVALID = <%= @grammar.prefix %>position_t(0xFFFF_FFFF, 0xFFFF_FFFF); enum INVALID = <%= @grammar.prefix %>position_t(0u, 0u);
/** Return whether the position is valid. */ /** Return whether the position is valid. */
public @property bool valid() public @property bool valid()
{ {
return row != 0xFFFF_FFFFu; return row != 0u;
} }
} }
@@ -235,6 +235,8 @@ public void <%= @grammar.prefix %>context_init(<%= @grammar.prefix %>context_t *
/* Lexer initialization. */ /* Lexer initialization. */
newcontext.input = input; newcontext.input = input;
newcontext.text_position.row = 1u;
newcontext.text_position.col = 1u;
newcontext.mode = <%= @lexer.mode_id("default") %>; newcontext.mode = <%= @lexer.mode_id("default") %>;
/* Copy to the user's context structure. */ /* Copy to the user's context structure. */
@@ -534,7 +536,7 @@ private size_t find_longest_match(<%= @grammar.prefix %>context_t * context,
if (code_point == '\n') if (code_point == '\n')
{ {
attempt_match.delta_position.row++; attempt_match.delta_position.row++;
attempt_match.delta_position.col = 0u; attempt_match.delta_position.col = 1u;
} }
else else
{ {
+1 -1
View File
@@ -53,7 +53,7 @@ typedef struct
} <%= @grammar.prefix %>position_t; } <%= @grammar.prefix %>position_t;
/** Return whether the position is valid. */ /** Return whether the position is valid. */
#define <%= @grammar.prefix %>position_valid(p) ((p).row != 0xFFFFFFFFu) #define <%= @grammar.prefix %>position_valid(p) ((p).row != 0u)
/** User header code blocks. */ /** User header code blocks. */
<%= @grammar.code_blocks.fetch("header", "") %> <%= @grammar.code_blocks.fetch("header", "") %>
+7 -6
View File
@@ -641,13 +641,14 @@ This example uses the default start rule name of `Start`.
A parser rule has zero or more fields on the right side of its definition. A parser rule has zero or more fields on the right side of its definition.
Each of these fields is either a token name or a rule name. Each of these fields is either a token name or a rule name.
A field can be immediately followed by a `?` character to signify that it is
optional.
A field can optionally be followed by a `:` and then a field alias name. A field can optionally be followed by a `:` and then a field alias name.
If present, the field alias name is used to refer to the field value in user If present, the field alias name is used to refer to the field value in user
code blocks, or if AST mode is active, the field alias name is used as the code blocks, or if AST mode is active, the field alias name is used as the
field name in the generated AST node structure. field name in the generated AST node structure.
A field can be immediately followed by a `?` character to signify that it is An optional and named field must use the format `field?:name`.
optional. Example:
Another example:
``` ```
token public; token public;
@@ -655,7 +656,7 @@ token private;
token int; token int;
token ident /[a-zA-Z_][a-zA-Z_0-9]*/; token ident /[a-zA-Z_][a-zA-Z_0-9]*/;
token semicolon /;/; token semicolon /;/;
IntegerDeclaration -> Visibility? int ident:name semicolon; IntegerDeclaration -> Visibility?:visibility int ident:name semicolon;
Visibility -> public; Visibility -> public;
Visibility -> private; Visibility -> private;
``` ```
@@ -663,7 +664,7 @@ Visibility -> private;
In a parser rule code block, parser values for the right side fields are In a parser rule code block, parser values for the right side fields are
accessible as `$1` for the first field's parser value, `$2` for the second accessible as `$1` for the first field's parser value, `$2` for the second
field's parser value, etc... field's parser value, etc...
For the `IntegerDeclaration` rule, the third field value can also be referred For the `IntegerDeclaration` rule, the first field value can also be referred to as `${visibility}` and the third field value can also be referred
to as `${name}`. to as `${name}`.
The `$$` symbol accesses the output parser value for this rule. The `$$` symbol accesses the output parser value for this rule.
The above examples demonstrate how the parser values for the rule components The above examples demonstrate how the parser values for the rule components
@@ -776,7 +777,7 @@ A pointer to this instance is passed to the generated functions.
### `p_position_t` ### `p_position_t`
The `p_position_t` structure contains two fields `row` and `col`. The `p_position_t` structure contains two fields `row` and `col`.
These fields contain the 0-based row and column describing a parser position. These fields contain the 1-based row and column describing a parser position.
For D targets, the `p_position_t` structure can be checked for validity by For D targets, the `p_position_t` structure can be checked for validity by
querying the `valid` property. querying the `valid` property.
+1 -1
View File
@@ -198,7 +198,7 @@ class Propane
if @ast && ptypename if @ast && ptypename
raise Error.new("Multiple ptypes are unsupported in AST mode") raise Error.new("Multiple ptypes are unsupported in AST mode")
end end
md = consume!(/((?:#{IDENTIFIER_REGEX}(?::#{IDENTIFIER_REGEX})?\??\s*)*)\s*/, "expected rule component list") md = consume!(/((?:#{IDENTIFIER_REGEX}\??(?::#{IDENTIFIER_REGEX})?\s*)*)\s*/, "expected rule component list")
components = md[1].strip.split(/\s+/) components = md[1].strip.split(/\s+/)
if @ast if @ast
consume!(/;/, "expected `;'") consume!(/;/, "expected `;'")
+13 -2
View File
@@ -14,6 +14,7 @@ class Propane
@item_sets = [] @item_sets = []
@item_sets_set = {} @item_sets_set = {}
@warnings = Set.new @warnings = Set.new
@errors = Set.new
@options = options @options = options
start_item = Item.new(grammar.rules.first, 0) start_item = Item.new(grammar.rules.first, 0)
eval_item_sets = Set[ItemSet.new([start_item])] eval_item_sets = Set[ItemSet.new([start_item])]
@@ -41,8 +42,18 @@ class Propane
build_reduce_actions! build_reduce_actions!
build_tables! build_tables!
write_log! write_log!
errormessage = ""
if @errors.size > 0
errormessage += @errors.join("\n")
end
if @warnings.size > 0 && @options[:warnings_as_errors] if @warnings.size > 0 && @options[:warnings_as_errors]
raise Error.new("Fatal errors (-w):\n" + @warnings.join("\n")) if errormessage != ""
errormessage += "\n"
end
errormessage += "Fatal errors (-w):\n" + @warnings.join("\n")
end
if errormessage != ""
raise Error.new(errormessage)
end end
end end
@@ -171,7 +182,7 @@ class Propane
lookahead_tokens_for_rule = build_lookahead_tokens_to_reduce(reduce_rule, item_sets) lookahead_tokens_for_rule = build_lookahead_tokens_to_reduce(reduce_rule, item_sets)
lookahead_tokens_for_rule.each do |lookahead_token| lookahead_tokens_for_rule.each do |lookahead_token|
if existing_reduce_rule = reduce_actions[lookahead_token] if existing_reduce_rule = reduce_actions[lookahead_token]
raise Error.new("Error: reduce/reduce conflict (state #{item_set.id}) between rule #{existing_reduce_rule.name}##{existing_reduce_rule.id} (defined on line #{existing_reduce_rule.line_number}) and rule #{reduce_rule.name}##{reduce_rule.id} (defined on line #{reduce_rule.line_number})") @errors << "Error: reduce/reduce conflict (state #{item_set.id}) between rule #{existing_reduce_rule.name}##{existing_reduce_rule.id} (defined on line #{existing_reduce_rule.line_number}) and rule #{reduce_rule.name}##{reduce_rule.id} (defined on line #{reduce_rule.line_number}) for lookahead token #{lookahead_token}"
end end
reduce_actions[lookahead_token] = reduce_rule reduce_actions[lookahead_token] = reduce_rule
end end
+12 -12
View File
@@ -119,6 +119,8 @@ class Propane
def build_ast_fields(grammar) def build_ast_fields(grammar)
field_ast_node_indexes = {} field_ast_node_indexes = {}
field_indexes_across_all_rules = {} field_indexes_across_all_rules = {}
# Stores the index into @ast_fields by field alias name.
field_aliases = {}
@ast_fields = [] @ast_fields = []
@rules.each do |rule| @rules.each do |rule|
rule.components.each_with_index do |component, i| rule.components.each_with_index do |component, i|
@@ -136,6 +138,16 @@ class Propane
field_ast_node_indexes[field_name] = @ast_fields.size field_ast_node_indexes[field_name] = @ast_fields.size
@ast_fields << {field_name => struct_name} @ast_fields << {field_name => struct_name}
end end
rule.aliases.each do |alias_name, index|
if index == i
alias_ast_fields_index = field_ast_node_indexes[field_name]
if field_aliases[alias_name] && field_aliases[alias_name] != alias_ast_fields_index
raise Error.new("Error: conflicting AST node field positions for alias `#{alias_name}` in rule #{rule.name} defined on line #{rule.line_number}")
end
field_aliases[alias_name] = alias_ast_fields_index
@ast_fields[alias_ast_fields_index][alias_name] = @ast_fields[alias_ast_fields_index].first[1]
end
end
field_indexes_across_all_rules[node_name] ||= Set.new field_indexes_across_all_rules[node_name] ||= Set.new
field_indexes_across_all_rules[node_name] << field_ast_node_indexes[field_name] field_indexes_across_all_rules[node_name] << field_ast_node_indexes[field_name]
rule.rule_set_node_field_index_map[i] = field_ast_node_indexes[field_name] rule.rule_set_node_field_index_map[i] = field_ast_node_indexes[field_name]
@@ -150,18 +162,6 @@ class Propane
"#{grammar.ast_prefix}#{node_name}#{grammar.ast_suffix}" "#{grammar.ast_prefix}#{node_name}#{grammar.ast_suffix}"
end end
end end
# Now merge in the field aliases as given by the user in the
# grammar.
field_aliases = {}
@rules.each do |rule|
rule.aliases.each do |alias_name, index|
if field_aliases[alias_name] && field_aliases[alias_name] != index
raise Error.new("Error: conflicting AST node field positions for alias `#{alias_name}`")
end
field_aliases[alias_name] = index
@ast_fields[index][alias_name] = @ast_fields[index].first[1]
end
end
end end
end end
+1 -1
View File
@@ -1,3 +1,3 @@
class Propane class Propane
VERSION = "1.5.1" VERSION = "2.1.1"
end end
+115
View File
@@ -689,6 +689,7 @@ EOF
results = run_propane(capture: true, language: language) results = run_propane(capture: true, language: language)
expect(results.status).to_not eq 0 expect(results.status).to_not eq 0
expect(results.stderr).to match %r{Error: reduce/reduce conflict \(state \d+\) between rule E#\d+ \(defined on line 10\) and rule F#\d+ \(defined on line 11\)} expect(results.stderr).to match %r{Error: reduce/reduce conflict \(state \d+\) between rule E#\d+ \(defined on line 10\) and rule F#\d+ \(defined on line 11\)}
expect(File.binread("spec/run/testparser.log")).to match %r{Reduce.actions:}
end end
it "provides matched text to user code blocks" do it "provides matched text to user code blocks" do
@@ -1117,6 +1118,47 @@ EOF
expect(results.status).to eq 0 expect(results.status).to eq 0
end end
it "allows naming an optional rule component in AST generation mode" do
if language == "d"
write_grammar <<EOF
ast;
<<
import std.stdio;
>>
token a;
token b;
token c;
token d;
Start -> a?:a b R?:r;
R -> c d;
R -> d c;
EOF
else
write_grammar <<EOF
ast;
<<
#include <stdio.h>
>>
token a;
token b;
token c;
token d;
Start -> a?:a b R?:r;
R -> c d;
R -> d c;
EOF
end
run_propane(language: language)
compile("spec/test_named_optional_rule_component_ast.#{language}", language: language)
results = run_test
expect(results.stderr).to eq ""
expect(results.status).to eq 0
end
it "stores token and rule positions in AST nodes" do it "stores token and rule positions in AST nodes" do
write_grammar <<EOF write_grammar <<EOF
ast; ast;
@@ -1177,6 +1219,29 @@ EOF
expect(results.status).to eq 0 expect(results.status).to eq 0
end end
it "aliases the correct field when multiple rules are in a rule set in AST mode" do
write_grammar <<EOF
ast;
token a;
token b;
token c;
drop /\\s+/;
Start -> a;
Start -> Foo;
Start -> T:first T:second T:third;
Foo -> b;
T -> a;
T -> b;
T -> c;
EOF
run_propane(language: language)
compile("spec/test_ast_field_aliases.#{language}", language: language)
results = run_test
expect(results.stderr).to eq ""
expect(results.status).to eq 0
end
it "allows specifying field aliases when AST mode is not enabled" do it "allows specifying field aliases when AST mode is not enabled" do
if language == "d" if language == "d"
write_grammar <<EOF write_grammar <<EOF
@@ -1211,6 +1276,56 @@ Start -> id:first id:second <<
printf("first is %s\\n", ${first}); printf("first is %s\\n", ${first});
printf("second is %s\\n", ${second}); printf("second is %s\\n", ${second});
>> >>
EOF
end
run_propane(language: language)
compile("spec/test_field_aliases.#{language}", language: language)
results = run_test
expect(results.stderr).to eq ""
expect(results.status).to eq 0
expect(results.stdout).to match /first is foo1.*second is bar2/m
end
it "aliases the correct field when multiple rules are in a rule set when AST mode is not enabled" do
if language == "d"
write_grammar <<EOF
<<
import std.stdio;
>>
ptype string;
token id /[a-zA-Z_][a-zA-Z0-9_]*/ <<
$$ = match;
>>
drop /\\s+/;
Start -> id;
Start -> Foo;
Start -> id:first id:second <<
writeln("first is ", ${first});
writeln("second is ", ${second});
>>
Foo -> ;
EOF
else
write_grammar <<EOF
<<
#include <stdio.h>
#include <string.h>
>>
ptype char const *;
token id /[a-zA-Z_][a-zA-Z0-9_]*/ <<
char * s = malloc(match_length + 1);
strncpy(s, (char const *)match, match_length);
s[match_length] = 0;
$$ = s;
>>
drop /\\s+/;
Start -> id;
Start -> Foo;
Start -> id:first id:second <<
printf("first is %s\\n", ${first});
printf("second is %s\\n", ${second});
>>
Foo -> ;
EOF EOF
end end
run_propane(language: language) run_propane(language: language)
+60 -60
View File
@@ -11,92 +11,92 @@ int main()
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(2, start->pT1->pToken->position.row);
assert_eq(0, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
assert_eq(1, start->pT1->pToken->end_position.row); assert_eq(2, start->pT1->pToken->end_position.row);
assert_eq(0, start->pT1->pToken->end_position.col); assert_eq(1, start->pT1->pToken->end_position.col);
assert(p_position_valid(start->pT1->pA->position)); assert(p_position_valid(start->pT1->pA->position));
assert_eq(2, start->pT1->pA->position.row); assert_eq(3, start->pT1->pA->position.row);
assert_eq(2, start->pT1->pA->position.col); assert_eq(3, start->pT1->pA->position.col);
assert_eq(2, start->pT1->pA->end_position.row); assert_eq(3, start->pT1->pA->end_position.row);
assert_eq(7, start->pT1->pA->end_position.col); assert_eq(8, start->pT1->pA->end_position.col);
assert_eq(1, start->pT1->position.row); assert_eq(2, start->pT1->position.row);
assert_eq(0, start->pT1->position.col); assert_eq(1, start->pT1->position.col);
assert_eq(2, start->pT1->end_position.row); assert_eq(3, start->pT1->end_position.row);
assert_eq(7, start->pT1->end_position.col); assert_eq(8, start->pT1->end_position.col);
assert_eq(1, start->position.row); assert_eq(2, start->position.row);
assert_eq(0, start->position.col); assert_eq(1, start->position.col);
assert_eq(2, start->end_position.row); assert_eq(3, start->end_position.row);
assert_eq(7, start->end_position.col); assert_eq(8, start->end_position.col);
input = "a\nbb"; input = "a\nbb";
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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(0, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(0, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
assert_eq(0, start->pT1->pToken->end_position.row); assert_eq(1, start->pT1->pToken->end_position.row);
assert_eq(0, start->pT1->pToken->end_position.col); assert_eq(1, start->pT1->pToken->end_position.col);
assert(p_position_valid(start->pT1->pA->position)); assert(p_position_valid(start->pT1->pA->position));
assert_eq(1, start->pT1->pA->position.row); assert_eq(2, start->pT1->pA->position.row);
assert_eq(0, start->pT1->pA->position.col); assert_eq(1, start->pT1->pA->position.col);
assert_eq(1, start->pT1->pA->end_position.row); assert_eq(2, start->pT1->pA->end_position.row);
assert_eq(1, start->pT1->pA->end_position.col); assert_eq(2, start->pT1->pA->end_position.col);
assert_eq(0, start->pT1->position.row); assert_eq(1, start->pT1->position.row);
assert_eq(0, start->pT1->position.col); assert_eq(1, start->pT1->position.col);
assert_eq(1, start->pT1->end_position.row); assert_eq(2, start->pT1->end_position.row);
assert_eq(1, start->pT1->end_position.col); assert_eq(2, start->pT1->end_position.col);
assert_eq(0, start->position.row); assert_eq(1, start->position.row);
assert_eq(0, start->position.col); assert_eq(1, start->position.col);
assert_eq(1, start->end_position.row); assert_eq(2, start->end_position.row);
assert_eq(1, start->end_position.col); assert_eq(2, start->end_position.col);
input = "a\nc\nc"; input = "a\nc\nc";
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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(0, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(0, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
assert_eq(0, start->pT1->pToken->end_position.row); assert_eq(1, start->pT1->pToken->end_position.row);
assert_eq(0, start->pT1->pToken->end_position.col); assert_eq(1, start->pT1->pToken->end_position.col);
assert(p_position_valid(start->pT1->pA->position)); assert(p_position_valid(start->pT1->pA->position));
assert_eq(1, start->pT1->pA->position.row); assert_eq(2, start->pT1->pA->position.row);
assert_eq(0, start->pT1->pA->position.col); assert_eq(1, start->pT1->pA->position.col);
assert_eq(2, start->pT1->pA->end_position.row); assert_eq(3, start->pT1->pA->end_position.row);
assert_eq(0, start->pT1->pA->end_position.col); assert_eq(1, start->pT1->pA->end_position.col);
assert_eq(0, start->pT1->position.row); assert_eq(1, start->pT1->position.row);
assert_eq(0, start->pT1->position.col); assert_eq(1, start->pT1->position.col);
assert_eq(2, start->pT1->end_position.row); assert_eq(3, start->pT1->end_position.row);
assert_eq(0, start->pT1->end_position.col); assert_eq(1, start->pT1->end_position.col);
assert_eq(0, start->position.row); assert_eq(1, start->position.row);
assert_eq(0, start->position.col); assert_eq(1, start->position.col);
assert_eq(2, start->end_position.row); assert_eq(3, start->end_position.row);
assert_eq(0, start->end_position.col); assert_eq(1, start->end_position.col);
input = "a"; input = "a";
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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(0, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(0, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
assert_eq(0, start->pT1->pToken->end_position.row); assert_eq(1, start->pT1->pToken->end_position.row);
assert_eq(0, start->pT1->pToken->end_position.col); assert_eq(1, start->pT1->pToken->end_position.col);
assert(!p_position_valid(start->pT1->pA->position)); assert(!p_position_valid(start->pT1->pA->position));
assert_eq(0, start->pT1->position.row); assert_eq(1, start->pT1->position.row);
assert_eq(0, start->pT1->position.col); assert_eq(1, start->pT1->position.col);
assert_eq(0, start->pT1->end_position.row); assert_eq(1, start->pT1->end_position.row);
assert_eq(0, start->pT1->end_position.col); assert_eq(1, start->pT1->end_position.col);
assert_eq(0, start->position.row); assert_eq(1, start->position.row);
assert_eq(0, start->position.col); assert_eq(1, start->position.col);
assert_eq(0, start->end_position.row); assert_eq(1, start->end_position.row);
assert_eq(0, start->end_position.col); assert_eq(1, start->end_position.col);
return 0; return 0;
} }
+60 -60
View File
@@ -15,90 +15,90 @@ unittest
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(2, start.pT1.pToken.position.row);
assert_eq(0, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
assert_eq(1, start.pT1.pToken.end_position.row); assert_eq(2, start.pT1.pToken.end_position.row);
assert_eq(0, start.pT1.pToken.end_position.col); assert_eq(1, start.pT1.pToken.end_position.col);
assert(start.pT1.pA.position.valid); assert(start.pT1.pA.position.valid);
assert_eq(2, start.pT1.pA.position.row); assert_eq(3, start.pT1.pA.position.row);
assert_eq(2, start.pT1.pA.position.col); assert_eq(3, start.pT1.pA.position.col);
assert_eq(2, start.pT1.pA.end_position.row); assert_eq(3, start.pT1.pA.end_position.row);
assert_eq(7, start.pT1.pA.end_position.col); assert_eq(8, start.pT1.pA.end_position.col);
assert_eq(1, start.pT1.position.row); assert_eq(2, start.pT1.position.row);
assert_eq(0, start.pT1.position.col); assert_eq(1, start.pT1.position.col);
assert_eq(2, start.pT1.end_position.row); assert_eq(3, start.pT1.end_position.row);
assert_eq(7, start.pT1.end_position.col); assert_eq(8, start.pT1.end_position.col);
assert_eq(1, start.position.row); assert_eq(2, start.position.row);
assert_eq(0, start.position.col); assert_eq(1, start.position.col);
assert_eq(2, start.end_position.row); assert_eq(3, start.end_position.row);
assert_eq(7, start.end_position.col); assert_eq(8, start.end_position.col);
input = "a\nbb"; input = "a\nbb";
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context); start = p_result(&context);
assert_eq(0, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(0, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
assert_eq(0, start.pT1.pToken.end_position.row); assert_eq(1, start.pT1.pToken.end_position.row);
assert_eq(0, start.pT1.pToken.end_position.col); assert_eq(1, start.pT1.pToken.end_position.col);
assert(start.pT1.pA.position.valid); assert(start.pT1.pA.position.valid);
assert_eq(1, start.pT1.pA.position.row); assert_eq(2, start.pT1.pA.position.row);
assert_eq(0, start.pT1.pA.position.col); assert_eq(1, start.pT1.pA.position.col);
assert_eq(1, start.pT1.pA.end_position.row); assert_eq(2, start.pT1.pA.end_position.row);
assert_eq(1, start.pT1.pA.end_position.col); assert_eq(2, start.pT1.pA.end_position.col);
assert_eq(0, start.pT1.position.row); assert_eq(1, start.pT1.position.row);
assert_eq(0, start.pT1.position.col); assert_eq(1, start.pT1.position.col);
assert_eq(1, start.pT1.end_position.row); assert_eq(2, start.pT1.end_position.row);
assert_eq(1, start.pT1.end_position.col); assert_eq(2, start.pT1.end_position.col);
assert_eq(0, start.position.row); assert_eq(1, start.position.row);
assert_eq(0, start.position.col); assert_eq(1, start.position.col);
assert_eq(1, start.end_position.row); assert_eq(2, start.end_position.row);
assert_eq(1, start.end_position.col); assert_eq(2, start.end_position.col);
input = "a\nc\nc"; input = "a\nc\nc";
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context); start = p_result(&context);
assert_eq(0, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(0, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
assert_eq(0, start.pT1.pToken.end_position.row); assert_eq(1, start.pT1.pToken.end_position.row);
assert_eq(0, start.pT1.pToken.end_position.col); assert_eq(1, start.pT1.pToken.end_position.col);
assert(start.pT1.pA.position.valid); assert(start.pT1.pA.position.valid);
assert_eq(1, start.pT1.pA.position.row); assert_eq(2, start.pT1.pA.position.row);
assert_eq(0, start.pT1.pA.position.col); assert_eq(1, start.pT1.pA.position.col);
assert_eq(2, start.pT1.pA.end_position.row); assert_eq(3, start.pT1.pA.end_position.row);
assert_eq(0, start.pT1.pA.end_position.col); assert_eq(1, start.pT1.pA.end_position.col);
assert_eq(0, start.pT1.position.row); assert_eq(1, start.pT1.position.row);
assert_eq(0, start.pT1.position.col); assert_eq(1, start.pT1.position.col);
assert_eq(2, start.pT1.end_position.row); assert_eq(3, start.pT1.end_position.row);
assert_eq(0, start.pT1.end_position.col); assert_eq(1, start.pT1.end_position.col);
assert_eq(0, start.position.row); assert_eq(1, start.position.row);
assert_eq(0, start.position.col); assert_eq(1, start.position.col);
assert_eq(2, start.end_position.row); assert_eq(3, start.end_position.row);
assert_eq(0, start.end_position.col); assert_eq(1, start.end_position.col);
input = "a"; input = "a";
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context); start = p_result(&context);
assert_eq(0, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(0, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
assert_eq(0, start.pT1.pToken.end_position.row); assert_eq(1, start.pT1.pToken.end_position.row);
assert_eq(0, start.pT1.pToken.end_position.col); assert_eq(1, start.pT1.pToken.end_position.col);
assert(!start.pT1.pA.position.valid); assert(!start.pT1.pA.position.valid);
assert_eq(0, start.pT1.position.row); assert_eq(1, start.pT1.position.row);
assert_eq(0, start.pT1.position.col); assert_eq(1, start.pT1.position.col);
assert_eq(0, start.pT1.end_position.row); assert_eq(1, start.pT1.end_position.row);
assert_eq(0, start.pT1.end_position.col); assert_eq(1, start.pT1.end_position.col);
assert_eq(0, start.position.row); assert_eq(1, start.position.row);
assert_eq(0, start.position.col); assert_eq(1, start.position.col);
assert_eq(0, start.end_position.row); assert_eq(1, start.end_position.row);
assert_eq(0, start.end_position.col); assert_eq(1, start.end_position.col);
} }
+56 -56
View File
@@ -11,74 +11,74 @@ int main()
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(&context);
assert_eq(0, start->pT1->pToken->position.row); assert_eq(1, start->pT1->pToken->position.row);
assert_eq(0, start->pT1->pToken->position.col); assert_eq(1, start->pT1->pToken->position.col);
assert_eq(0, start->pT1->pToken->end_position.row); assert_eq(1, start->pT1->pToken->end_position.row);
assert_eq(0, start->pT1->pToken->end_position.col); assert_eq(1, start->pT1->pToken->end_position.col);
assert_eq(0, start->pT1->position.row); assert_eq(1, start->pT1->position.row);
assert_eq(0, start->pT1->position.col); assert_eq(1, start->pT1->position.col);
assert_eq(0, start->pT1->end_position.row); assert_eq(1, start->pT1->end_position.row);
assert_eq(0, start->pT1->end_position.col); assert_eq(1, start->pT1->end_position.col);
assert_eq(0, start->pT2->pToken->position.row); assert_eq(1, start->pT2->pToken->position.row);
assert_eq(1, start->pT2->pToken->position.col); assert_eq(2, start->pT2->pToken->position.col);
assert_eq(0, start->pT2->pToken->end_position.row); assert_eq(1, start->pT2->pToken->end_position.row);
assert_eq(2, start->pT2->pToken->end_position.col); assert_eq(3, start->pT2->pToken->end_position.col);
assert_eq(0, start->pT2->position.row); assert_eq(1, start->pT2->position.row);
assert_eq(1, start->pT2->position.col); assert_eq(2, start->pT2->position.col);
assert_eq(0, start->pT2->end_position.row); assert_eq(1, start->pT2->end_position.row);
assert_eq(2, start->pT2->end_position.col); assert_eq(3, start->pT2->end_position.col);
assert_eq(0, start->pT3->pToken->position.row); assert_eq(1, start->pT3->pToken->position.row);
assert_eq(3, start->pT3->pToken->position.col); assert_eq(4, start->pT3->pToken->position.col);
assert_eq(0, start->pT3->pToken->end_position.row); assert_eq(1, start->pT3->pToken->end_position.row);
assert_eq(5, start->pT3->pToken->end_position.col); assert_eq(6, start->pT3->pToken->end_position.col);
assert_eq(0, start->pT3->position.row); assert_eq(1, start->pT3->position.row);
assert_eq(3, start->pT3->position.col); assert_eq(4, start->pT3->position.col);
assert_eq(0, start->pT3->end_position.row); assert_eq(1, start->pT3->end_position.row);
assert_eq(5, start->pT3->end_position.col); assert_eq(6, start->pT3->end_position.col);
assert_eq(0, start->position.row); assert_eq(1, start->position.row);
assert_eq(0, start->position.col); assert_eq(1, start->position.col);
assert_eq(0, start->end_position.row); assert_eq(1, start->end_position.row);
assert_eq(5, start->end_position.col); assert_eq(6, start->end_position.col);
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)); p_context_init(&context, (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(2, start->pT1->pToken->position.row); assert_eq(3, start->pT1->pToken->position.row);
assert_eq(2, start->pT1->pToken->position.col); assert_eq(3, start->pT1->pToken->position.col);
assert_eq(2, start->pT1->pToken->end_position.row); assert_eq(3, start->pT1->pToken->end_position.row);
assert_eq(3, start->pT1->pToken->end_position.col); assert_eq(4, start->pT1->pToken->end_position.col);
assert_eq(2, start->pT1->position.row); assert_eq(3, start->pT1->position.row);
assert_eq(2, start->pT1->position.col); assert_eq(3, start->pT1->position.col);
assert_eq(2, start->pT1->end_position.row); assert_eq(3, start->pT1->end_position.row);
assert_eq(3, start->pT1->end_position.col); assert_eq(4, start->pT1->end_position.col);
assert_eq(3, start->pT2->pToken->position.row); assert_eq(4, start->pT2->pToken->position.row);
assert_eq(0, start->pT2->pToken->position.col); assert_eq(1, start->pT2->pToken->position.col);
assert_eq(4, start->pT2->pToken->end_position.row); assert_eq(5, start->pT2->pToken->end_position.row);
assert_eq(1, start->pT2->pToken->end_position.col); assert_eq(2, start->pT2->pToken->end_position.col);
assert_eq(3, start->pT2->position.row); assert_eq(4, start->pT2->position.row);
assert_eq(0, start->pT2->position.col); assert_eq(1, start->pT2->position.col);
assert_eq(4, start->pT2->end_position.row); assert_eq(5, start->pT2->end_position.row);
assert_eq(1, start->pT2->end_position.col); assert_eq(2, start->pT2->end_position.col);
assert_eq(6, start->pT3->pToken->position.row); assert_eq(7, start->pT3->pToken->position.row);
assert_eq(5, start->pT3->pToken->position.col); assert_eq(6, start->pT3->pToken->position.col);
assert_eq(6, start->pT3->pToken->end_position.row); assert_eq(7, start->pT3->pToken->end_position.row);
assert_eq(5, start->pT3->pToken->end_position.col); assert_eq(6, start->pT3->pToken->end_position.col);
assert_eq(6, start->pT3->position.row); assert_eq(7, start->pT3->position.row);
assert_eq(5, start->pT3->position.col); assert_eq(6, start->pT3->position.col);
assert_eq(6, start->pT3->end_position.row); assert_eq(7, start->pT3->end_position.row);
assert_eq(5, start->pT3->end_position.col); assert_eq(6, start->pT3->end_position.col);
assert_eq(2, start->position.row); assert_eq(3, start->position.row);
assert_eq(2, start->position.col); assert_eq(3, start->position.col);
assert_eq(6, start->end_position.row); assert_eq(7, start->end_position.row);
assert_eq(5, start->end_position.col); assert_eq(6, start->end_position.col);
return 0; return 0;
} }
+56 -56
View File
@@ -15,72 +15,72 @@ unittest
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
Start * start = p_result(&context); Start * start = p_result(&context);
assert_eq(0, start.pT1.pToken.position.row); assert_eq(1, start.pT1.pToken.position.row);
assert_eq(0, start.pT1.pToken.position.col); assert_eq(1, start.pT1.pToken.position.col);
assert_eq(0, start.pT1.pToken.end_position.row); assert_eq(1, start.pT1.pToken.end_position.row);
assert_eq(0, start.pT1.pToken.end_position.col); assert_eq(1, start.pT1.pToken.end_position.col);
assert_eq(0, start.pT1.position.row); assert_eq(1, start.pT1.position.row);
assert_eq(0, start.pT1.position.col); assert_eq(1, start.pT1.position.col);
assert_eq(0, start.pT1.end_position.row); assert_eq(1, start.pT1.end_position.row);
assert_eq(0, start.pT1.end_position.col); assert_eq(1, start.pT1.end_position.col);
assert_eq(0, start.pT2.pToken.position.row); assert_eq(1, start.pT2.pToken.position.row);
assert_eq(1, start.pT2.pToken.position.col); assert_eq(2, start.pT2.pToken.position.col);
assert_eq(0, start.pT2.pToken.end_position.row); assert_eq(1, start.pT2.pToken.end_position.row);
assert_eq(2, start.pT2.pToken.end_position.col); assert_eq(3, start.pT2.pToken.end_position.col);
assert_eq(0, start.pT2.position.row); assert_eq(1, start.pT2.position.row);
assert_eq(1, start.pT2.position.col); assert_eq(2, start.pT2.position.col);
assert_eq(0, start.pT2.end_position.row); assert_eq(1, start.pT2.end_position.row);
assert_eq(2, start.pT2.end_position.col); assert_eq(3, start.pT2.end_position.col);
assert_eq(0, start.pT3.pToken.position.row); assert_eq(1, start.pT3.pToken.position.row);
assert_eq(3, start.pT3.pToken.position.col); assert_eq(4, start.pT3.pToken.position.col);
assert_eq(0, start.pT3.pToken.end_position.row); assert_eq(1, start.pT3.pToken.end_position.row);
assert_eq(5, start.pT3.pToken.end_position.col); assert_eq(6, start.pT3.pToken.end_position.col);
assert_eq(0, start.pT3.position.row); assert_eq(1, start.pT3.position.row);
assert_eq(3, start.pT3.position.col); assert_eq(4, start.pT3.position.col);
assert_eq(0, start.pT3.end_position.row); assert_eq(1, start.pT3.end_position.row);
assert_eq(5, start.pT3.end_position.col); assert_eq(6, start.pT3.end_position.col);
assert_eq(0, start.position.row); assert_eq(1, start.position.row);
assert_eq(0, start.position.col); assert_eq(1, start.position.col);
assert_eq(0, start.end_position.row); assert_eq(1, start.end_position.row);
assert_eq(5, start.end_position.col); assert_eq(6, start.end_position.col);
input = "\n\n bb\nc\ncc\n\n a"; input = "\n\n bb\nc\ncc\n\n a";
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS); assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context); start = p_result(&context);
assert_eq(2, start.pT1.pToken.position.row); assert_eq(3, start.pT1.pToken.position.row);
assert_eq(2, start.pT1.pToken.position.col); assert_eq(3, start.pT1.pToken.position.col);
assert_eq(2, start.pT1.pToken.end_position.row); assert_eq(3, start.pT1.pToken.end_position.row);
assert_eq(3, start.pT1.pToken.end_position.col); assert_eq(4, start.pT1.pToken.end_position.col);
assert_eq(2, start.pT1.position.row); assert_eq(3, start.pT1.position.row);
assert_eq(2, start.pT1.position.col); assert_eq(3, start.pT1.position.col);
assert_eq(2, start.pT1.end_position.row); assert_eq(3, start.pT1.end_position.row);
assert_eq(3, start.pT1.end_position.col); assert_eq(4, start.pT1.end_position.col);
assert_eq(3, start.pT2.pToken.position.row); assert_eq(4, start.pT2.pToken.position.row);
assert_eq(0, start.pT2.pToken.position.col); assert_eq(1, start.pT2.pToken.position.col);
assert_eq(4, start.pT2.pToken.end_position.row); assert_eq(5, start.pT2.pToken.end_position.row);
assert_eq(1, start.pT2.pToken.end_position.col); assert_eq(2, start.pT2.pToken.end_position.col);
assert_eq(3, start.pT2.position.row); assert_eq(4, start.pT2.position.row);
assert_eq(0, start.pT2.position.col); assert_eq(1, start.pT2.position.col);
assert_eq(4, start.pT2.end_position.row); assert_eq(5, start.pT2.end_position.row);
assert_eq(1, start.pT2.end_position.col); assert_eq(2, start.pT2.end_position.col);
assert_eq(6, start.pT3.pToken.position.row); assert_eq(7, start.pT3.pToken.position.row);
assert_eq(5, start.pT3.pToken.position.col); assert_eq(6, start.pT3.pToken.position.col);
assert_eq(6, start.pT3.pToken.end_position.row); assert_eq(7, start.pT3.pToken.end_position.row);
assert_eq(5, start.pT3.pToken.end_position.col); assert_eq(6, start.pT3.pToken.end_position.col);
assert_eq(6, start.pT3.position.row); assert_eq(7, start.pT3.position.row);
assert_eq(5, start.pT3.position.col); assert_eq(6, start.pT3.position.col);
assert_eq(6, start.pT3.end_position.row); assert_eq(7, start.pT3.end_position.row);
assert_eq(5, start.pT3.end_position.col); assert_eq(6, start.pT3.end_position.col);
assert_eq(2, start.position.row); assert_eq(3, start.position.row);
assert_eq(2, start.position.col); assert_eq(3, start.position.col);
assert_eq(6, start.end_position.row); assert_eq(7, start.end_position.row);
assert_eq(5, start.end_position.col); assert_eq(6, start.end_position.col);
} }
+8 -8
View File
@@ -12,28 +12,28 @@ int main()
input = "a\n123\na a"; input = "a\n123\na a";
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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 == 2); assert(p_position(&context).row == 3);
assert(p_position(&context).col == 3); assert(p_position(&context).col == 4);
assert(p_token(&context) == TOKEN_a); assert(p_token(&context) == TOKEN_a);
input = "12"; input = "12";
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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 == 0); assert(p_position(&context).row == 1);
assert(p_position(&context).col == 0); assert(p_position(&context).col == 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, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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 == 2); assert(p_position(&context).row == 3);
assert(p_position(&context).col == 1); assert(p_position(&context).col == 2);
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)); p_context_init(&context, (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 == 5); assert(p_position(&context).row == 6);
assert(p_position(&context).col == 4); 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);
+4 -4
View File
@@ -16,24 +16,24 @@ unittest
input = "a\n123\na a"; input = "a\n123\na a";
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(&context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(2, 3)); 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); p_context_init(&context, input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(&context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(0, 0)); 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); p_context_init(&context, input);
assert(p_parse(&context) == P_UNEXPECTED_INPUT); assert(p_parse(&context) == P_UNEXPECTED_INPUT);
assert(p_position(&context) == p_position_t(2, 1)); 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); p_context_init(&context, input);
assert(p_parse(&context) == P_DECODE_ERROR); assert(p_parse(&context) == P_DECODE_ERROR);
assert(p_position(&context) == p_position_t(5, 4)); 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");
+36 -36
View File
@@ -41,68 +41,68 @@ int main()
p_context_t context; p_context_t context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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 == 0u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 0u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 0u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 0u); 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 == 0u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 2u); assert(token_info.position.col == 3u);
assert(token_info.end_position.row == 0u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 2u); 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 == 0u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 4u); assert(token_info.position.col == 5u);
assert(token_info.end_position.row == 0u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 4u); 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 == 0u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 6u); assert(token_info.position.col == 7u);
assert(token_info.end_position.row == 0u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 6u); 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 == 1u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 0u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 2u); 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 == 1u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 4u); assert(token_info.position.col == 5u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 4u); 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 == 1u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 6u); assert(token_info.position.col == 7u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 8u); 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 == 1u); assert(token_info.position.row == 2u);
assert(token_info.position.col == 9u); assert(token_info.position.col == 10u);
assert(token_info.end_position.row == 1u); assert(token_info.end_position.row == 2u);
assert(token_info.end_position.col == 9u); 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_init(&context, (uint8_t const *)"", 0u); p_context_init(&context, (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 == 0u); assert(token_info.position.row == 1u);
assert(token_info.position.col == 0u); assert(token_info.position.col == 1u);
assert(token_info.end_position.row == 0u); assert(token_info.end_position.row == 1u);
assert(token_info.end_position.col == 0u); 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);
+9 -9
View File
@@ -47,23 +47,23 @@ unittest
p_context_t context; p_context_t context;
p_context_init(&context, input); p_context_init(&context, 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(0, 0), p_position_t(0, 0), 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(0, 2), p_position_t(0, 2), 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(0, 4), p_position_t(0, 4), 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(0, 6), p_position_t(0, 6), 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(1, 0), p_position_t(1, 2), 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(1, 4), p_position_t(1, 4), 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(1, 6), p_position_t(1, 8), 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(1, 9), p_position_t(1, 9), 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, ""); p_context_init(&context, "");
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(0, 0), p_position_t(0, 0), 0, TOKEN___EOF)); assert(token_info == p_token_info_t(p_position_t(1, 1), p_position_t(1, 1), 0, TOKEN___EOF));
} }
@@ -0,0 +1,45 @@
#include "testparser.h"
#include <assert.h>
#include <string.h>
#include "testutils.h"
int main()
{
char const * input = "b";
p_context_t context;
p_context_init(&context, (uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS);
Start * start = p_result(&context);
assert(start->a == NULL);
assert(start->pToken2 != NULL);
assert_eq(TOKEN_b, start->pToken2->token);
assert(start->pR3 == NULL);
assert(start->pR == NULL);
assert(start->r == NULL);
input = "abcd";
p_context_init(&context, (uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context);
assert(start->a != NULL);
assert_eq(TOKEN_a, start->pToken1->token);
assert(start->pToken2 != NULL);
assert(start->pR3 != NULL);
assert(start->pR != NULL);
assert(start->r != NULL);
assert(start->pR == start->pR3);
assert(start->pR == start->r);
assert_eq(TOKEN_c, start->pR->pToken1->token);
input = "bdc";
p_context_init(&context, (uint8_t const *)input, strlen(input));
assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context);
assert(start->a == NULL);
assert(start->pToken2 != NULL);
assert(start->r != NULL);
assert_eq(TOKEN_d, start->pR->pToken1->token);
return 0;
}
@@ -0,0 +1,46 @@
import testparser;
import std.stdio;
import testutils;
int main()
{
return 0;
}
unittest
{
string input = "b";
p_context_t context;
p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS);
Start * start = p_result(&context);
assert(start.pToken1 is null);
assert(start.pToken2 !is null);
assert_eq(TOKEN_b, start.pToken2.token);
assert(start.pR3 is null);
assert(start.pR is null);
assert(start.r is null);
input = "abcd";
p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context);
assert(start.pToken1 != null);
assert_eq(TOKEN_a, start.pToken1.token);
assert(start.pToken2 != null);
assert(start.pR3 != null);
assert(start.pR != null);
assert(start.r != null);
assert(start.pR == start.pR3);
assert(start.pR == start.r);
assert_eq(TOKEN_c, start.pR.pToken1.token);
input = "bdc";
p_context_init(&context, input);
assert(p_parse(&context) == P_SUCCESS);
start = p_result(&context);
assert(start.pToken1 is null);
assert(start.pToken2 !is null);
assert(start.pR !is null);
assert_eq(TOKEN_d, start.pR.pToken1.token);
}
+2 -2
View File
@@ -8,8 +8,8 @@ int main()
p_context_t context; p_context_t context;
p_context_init(&context, (uint8_t const *)input, strlen(input)); p_context_init(&context, (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 == 0); assert(p_position(&context).row == 1);
assert(p_position(&context).col == 1); assert(p_position(&context).col == 2);
assert(context.token == TOKEN___EOF); assert(context.token == TOKEN___EOF);
input = "a b"; input = "a b";
+1 -1
View File
@@ -12,7 +12,7 @@ unittest
p_context_t context; p_context_t context;
p_context_init(&context, input); p_context_init(&context, input);
assert(p_parse(&context) == P_UNEXPECTED_TOKEN); assert(p_parse(&context) == P_UNEXPECTED_TOKEN);
assert(p_position(&context) == p_position_t(0, 1)); 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";