| /** Convert the simple input to be java code; wrap in a class, |
| * convert method with "public void", add decls. This shows how to insert |
| * extra text into a stream of tokens and how to replace a token |
| * with some text. Calling toString() on the TokenRewriteStream |
| * in Main will print out the original input stream. |
| * |
| * Note that you can do the instructions in any order as the |
| * rewrite instructions just get queued up and executed upon toString(). |
| */ |
| grammar T; |
| options { language = Perl5; } |
| |
| program |
| : method+ |
| { |
| $input->insert_before($input->LT(1), "public class Wrapper {\n"); |
| // note the reference to the last token matched for method: |
| $input->insert_after($method.stop, "\n}\n"); |
| } |
| ; |
| |
| method |
| : m='method' ID '(' ')' body |
| { $input->replace($m, "public void"); } |
| ; |
| |
| body |
| scope { |
| // decls is on body's local variable stack but is visible to |
| // any rule that body calls such as stat. From other rules |
| // it is referenced as $body::decls |
| // From within rule body, you can use $decls shorthand |
| decls; |
| } |
| @init { |
| $body::decls = []; |
| } |
| : lcurly='{' stat* '}' |
| { |
| // dump declarations for all identifiers seen in statement list |
| foreach my $id ($body::decls) { |
| $tokens->insert_after($lcurly, "\nint $id;"); |
| } |
| } |
| ; |
| |
| stat: ID '=' expr ';' { $body::decls->add($ID.text); } // track left-hand-sides |
| ; |
| |
| expr: mul ('+' mul)* |
| ; |
| |
| mul : atom ('*' atom)* |
| ; |
| |
| atom: ID |
| | INT |
| ; |
| |
| ID : ('a'..'z'|'A'..'Z')+ ; |
| |
| INT : ('0'..'9')+ ; |
| |
| WS : (' '|'\t'|'\n')+ { $channel = $self->HIDDEN; } |
| ; |