diff --git a/lib/propane/generator.rb b/lib/propane/generator.rb index 21c5923..0a4bce5 100644 --- a/lib/propane/generator.rb +++ b/lib/propane/generator.rb @@ -276,6 +276,19 @@ class Propane "statevalues[$-1-n_states+#{index}].pvalue.v_#{rule.components[index - 1].ptypename}" end end + code = code.gsub(/\$\{(\w+)\}/) do |match| + aliasname = $1 + if index = rule.aliases[aliasname] + case @language + when "c" + "state_values_stack_index(statevalues, -(int)n_states + #{index})->pvalue.v_#{rule.components[index].ptypename}" + when "d" + "statevalues[$-n_states+#{index}].pvalue.v_#{rule.components[index].ptypename}" + end + else + raise Error.new("Field alias '#{aliasname}' not found") + end + end else code = code.gsub(/\$\$/) do |match| if @grammar.ast diff --git a/spec/propane_spec.rb b/spec/propane_spec.rb index 42d712f..9e961b1 100644 --- a/spec/propane_spec.rb +++ b/spec/propane_spec.rb @@ -237,7 +237,7 @@ EOF expect(results.status).to_not eq 0 end - it "does not error when an alias is in different positions for different rules in a rule set when AST mode is disabled" do + it "does not error when an alias is in different positions for different rules in a rule set when AST mode is not enabled" do write_grammar < b; T -> c; EOF run_propane(language: language) - compile("spec/test_field_aliases.#{language}", 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 + if language == "d" + write_grammar <> +ptype string; +token id /[a-zA-Z_][a-zA-Z0-9_]*/ << + $$ = match; +>> +drop /\\s+/; +Start -> id:first id:second << + writeln("first is ", ${first}); + writeln("second is ", ${second}); +>> +EOF + else + write_grammar < +#include +>> +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:first id:second << + printf("first is %s\\n", ${first}); + 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 end end end diff --git a/spec/test_field_aliases.c b/spec/test_field_aliases.c new file mode 100644 index 0000000..d02d7b6 --- /dev/null +++ b/spec/test_field_aliases.c @@ -0,0 +1,13 @@ +#include "testparser.h" +#include +#include +#include "testutils.h" + +int main() +{ + char const * input = "foo1\nbar2"; + p_context_t context; + p_context_init(&context, (uint8_t const *)input, strlen(input)); + assert(p_parse(&context) == P_SUCCESS); + return 0; +} diff --git a/spec/test_field_aliases.d b/spec/test_field_aliases.d new file mode 100644 index 0000000..61f3a2f --- /dev/null +++ b/spec/test_field_aliases.d @@ -0,0 +1,15 @@ +import testparser; +import std.stdio; + +int main() +{ + return 0; +} + +unittest +{ + string input = "foo1\nbar2"; + p_context_t context; + p_context_init(&context, input); + assert(p_parse(&context) == P_SUCCESS); +}