1/** Convert the simple input to be java code; wrap in a class,
2 *  convert method with "public void", add decls.  This shows how to insert
3 *  extra text into a stream of tokens and how to replace a token
4 *  with some text.  Calling toString() on the TokenRewriteStream
5 *  in Main will print out the original input stream.
6 *
7 *  Note that you can do the instructions in any order as the
8 *  rewrite instructions just get queued up and executed upon toString().
9 */
10grammar T;
11options { language = Perl5; }
12
13program
14    :   method+
15        {
16        $input->insert_before($input->LT(1), "public class Wrapper {\n");
17        // note the reference to the last token matched for method:
18        $input->insert_after($method.stop, "\n}\n");
19        }
20    ;
21
22method
23    :   m='method' ID '(' ')' body
24        { $input->replace($m, "public void"); }
25    ;
26
27body
28scope {
29    // decls is on body's local variable stack but is visible to
30    // any rule that body calls such as stat.  From other rules
31    // it is referenced as $body::decls
32    // From within rule body, you can use $decls shorthand
33    decls;
34}
35@init {
36    $body::decls = [];
37}
38    :   lcurly='{' stat* '}'
39        {
40        // dump declarations for all identifiers seen in statement list
41        foreach my $id ($body::decls) {
42            $tokens->insert_after($lcurly, "\nint $id;");
43        }
44        }
45    ;
46
47stat:   ID '=' expr ';' { $body::decls->add($ID.text); } // track left-hand-sides
48    ;
49
50expr:   mul ('+' mul)*
51    ;
52
53mul :   atom ('*' atom)*
54    ;
55
56atom:   ID
57    |   INT
58    ;
59
60ID  :   ('a'..'z'|'A'..'Z')+ ;
61
62INT :   ('0'..'9')+ ;
63
64WS  :   (' '|'\t'|'\n')+ { $channel = $self->HIDDEN; }
65    ;
66