Allow rule terms to be marked as optional
This commit is contained in:
1 parent
494afb7307
commit
f3e4941ad8
14 files changed
+346
-5
No files matched your search
@@ -910,6 +910,111 @@ EOF
|
||||
run_propane(language: language)
|
||||
compile("spec/test_start_rule_ast.#{language}", language: language)
|
||||
end
|
||||
|
||||
it "allows marking a rule component as optional" do
|
||||
if language == "d"
|
||||
write_grammar <<EOF
|
||||
<<
|
||||
import std.stdio;
|
||||
>>
|
||||
|
||||
ptype int;
|
||||
ptype float = float;
|
||||
ptype string = string;
|
||||
|
||||
token a (float) << $$ = 1.5; >>
|
||||
token b << $$ = 2; >>
|
||||
token c << $$ = 3; >>
|
||||
token d << $$ = 4; >>
|
||||
Start -> a? b R? <<
|
||||
writeln("a: ", $1);
|
||||
writeln("b: ", $2);
|
||||
writeln("R: ", $3);
|
||||
>>
|
||||
R -> c d << $$ = "cd"; >>
|
||||
R (string) -> d c << $$ = "dc"; >>
|
||||
EOF
|
||||
else
|
||||
write_grammar <<EOF
|
||||
<<
|
||||
#include <stdio.h>
|
||||
>>
|
||||
|
||||
ptype int;
|
||||
ptype float = float;
|
||||
ptype string = char *;
|
||||
|
||||
token a (float) << $$ = 1.5; >>
|
||||
token b << $$ = 2; >>
|
||||
token c << $$ = 3; >>
|
||||
token d << $$ = 4; >>
|
||||
Start -> a? b R? <<
|
||||
printf("a: %.1f\\n", $1);
|
||||
printf("b: %d\\n", $2);
|
||||
printf("R: %s\\n", $3 == NULL ? "" : $3);
|
||||
>>
|
||||
R -> c d << $$ = "cd"; >>
|
||||
R (string) -> d c << $$ = "dc"; >>
|
||||
EOF
|
||||
end
|
||||
run_propane(language: language)
|
||||
compile("spec/test_optional_rule_component.#{language}", language: language)
|
||||
results = run_test
|
||||
expect(results.stderr).to eq ""
|
||||
expect(results.status).to eq 0
|
||||
verify_lines(results.stdout, [
|
||||
"a: 0#{language == "d" ? "" : ".0"}",
|
||||
"b: 2",
|
||||
"R: ",
|
||||
"a: 1.5",
|
||||
"b: 2",
|
||||
"R: cd",
|
||||
"a: 1.5",
|
||||
"b: 2",
|
||||
"R: dc",
|
||||
])
|
||||
end
|
||||
|
||||
it "allows marking a rule component as optional 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? b 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? b R?;
|
||||
R -> c d;
|
||||
R -> d c;
|
||||
EOF
|
||||
end
|
||||
run_propane(language: language)
|
||||
compile("spec/test_optional_rule_component_ast.#{language}", language: language)
|
||||
results = run_test
|
||||
expect(results.stderr).to eq ""
|
||||
expect(results.status).to eq 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "testparser.h"
|
||||
#include <assert.h>
|
||||
#include <string.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);
|
||||
|
||||
input = "abcd";
|
||||
p_context_init(&context, (uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(&context) == P_SUCCESS);
|
||||
|
||||
input = "abdc";
|
||||
p_context_init(&context, (uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(&context) == P_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import testparser;
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
string input = "b";
|
||||
p_context_t context;
|
||||
p_context_init(&context, input);
|
||||
assert(p_parse(&context) == P_SUCCESS);
|
||||
|
||||
input = "abcd";
|
||||
p_context_init(&context, input);
|
||||
assert(p_parse(&context) == P_SUCCESS);
|
||||
|
||||
input = "abdc";
|
||||
p_context_init(&context, input);
|
||||
assert(p_parse(&context) == P_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#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->pToken1 == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert_eq(TOKEN_b, start->pToken2->token);
|
||||
assert(start->pR3 == NULL);
|
||||
assert(start->pR == 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->pToken1 != NULL);
|
||||
assert_eq(TOKEN_a, start->pToken1->token);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->pR3 != NULL);
|
||||
assert(start->pR != NULL);
|
||||
assert(start->pR == start->pR3);
|
||||
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->pToken1 == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->pR != NULL);
|
||||
assert_eq(TOKEN_d, start->pR->pToken1->token);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
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);
|
||||
|
||||
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.pR == start.pR3);
|
||||
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);
|
||||
}
|
||||
Reference in new issue
Block a user