diff --git a/assets/parser.d.erb b/assets/parser.d.erb index c1182f4..6ec6be2 100644 --- a/assets/parser.d.erb +++ b/assets/parser.d.erb @@ -184,7 +184,7 @@ class <%= @classname %> <% @grammar.patterns.each do |pattern| %> <% if pattern.code_id %> case <%= pattern.code_id %>u: { -<%= pattern.code %> +<%= expand_code(pattern.code) %> } break; <% end %> <% end %> diff --git a/lib/propane/generator.rb b/lib/propane/generator.rb index 0b14f28..16c8745 100644 --- a/lib/propane/generator.rb +++ b/lib/propane/generator.rb @@ -142,6 +142,19 @@ class Propane end end + # Expand expansions in user code block. + # + # @param code [String] + # User code block. + # + # @return [String] + # Expanded user code block. + def expand_code(code) + code.gsub(/\$token\(([$\w]+)\)/) do |match| + "TOKEN_#{Token.code_name($1)}" + end + end + end end diff --git a/spec/propane_spec.rb b/spec/propane_spec.rb index c989d21..64e4779 100644 --- a/spec/propane_spec.rb +++ b/spec/propane_spec.rb @@ -169,4 +169,27 @@ EOF "pass2", ]) end + + it "supports returning tokens from pattern code blocks" do + write_grammar <> +/ghi/ << + writeln("ghi!"); + return $token(abc); +>> +Start -> abc; +EOF + build_parser + compile("spec/test_return_token_from_pattern.d") + results = run + expect(results.status).to eq 0 + verify_lines(results.stdout, [ + "def!", + "ghi!", + "def!", + ]) + end end diff --git a/spec/test_return_token_from_pattern.d b/spec/test_return_token_from_pattern.d new file mode 100644 index 0000000..970e0d1 --- /dev/null +++ b/spec/test_return_token_from_pattern.d @@ -0,0 +1,14 @@ +import testparser; +import std.stdio; + +int main() +{ + return 0; +} + +unittest +{ + string input = "defghidef"; + auto parser = new Testparser.Parser(cast(const(ubyte) *)input.ptr, input.length); + assert(parser.parse() == true); +}