hi, * attached a patch that implements better macro parsing * begin of better heredoc parsing,but not finished yet. * added test for macro parsing
regards, klaas-jan
Index: languages/PIR/examples/macro2.pir =================================================================== --- languages/PIR/examples/macro2.pir (revision 0) +++ languages/PIR/examples/macro2.pir (revision 0) @@ -0,0 +1,49 @@ +.sub main + .local int i + #.a = 1 + a = a + .X(a,b) +.end + + +.macro X(a,b) + .local $x: doit() + + + loop: doit() + .a = .b + .sym int i +.endm + +.sub main + .local int i + #.a = 1 + a = a + .X(a,b) +.end + + +.macro X(a,b) + .local $x: doit() + + + loop: doit() + .a = .b + .sym int i +.endm + +.macro X(a,b) + .local $x: doit() + + + loop: doit() + .a = .b + .sym int i +.endm + +.sub main + .local int i + #.a = 1 + a = a + .X(a,b) +.end Index: languages/PIR/lib/pir.pg =================================================================== --- languages/PIR/lib/pir.pg (revision 17016) +++ languages/PIR/lib/pir.pg (working copy) @@ -2,8 +2,7 @@ # TO DO: # 1. fix Heredocs parsing -# 2. fix macro parsing -# 3. Test and fix things +# 2. Test and fix things token TOP { ^ <program> [ $ | <syntax_error: end of file expected> ] @@ -151,14 +150,11 @@ } -# this is a token, because no spaces are allowed between -# the id and the colon. -token label { - <id> <':'> -} + rule pir_instr { <local_decl> + | <sym_decl> | <lexical_decl> | <const_def> | <globalconst_def> @@ -181,12 +177,28 @@ ## Locals and Lexicals ## + +=head2 Local declarations + +Local declarations can be done using C<.sym> or C<.local> in normal context. +In macro context however, only C<.sym> is allowed, and the C<.local> keyword +indicates a label declaration. + +=cut + rule local_decl { - [ <'.local'> | <'.sym'> ] + <'.local'> [ <type> | <syntax_error: type for local symbol expected> ] <local_id_list> } +rule sym_decl { + <'.sym'> + [ <type> | <syntax_error: type for local symbol expected> ] + <local_id_list> +} + + rule local_id_list { <local_id> [ <','> <local_id> ]* } @@ -261,8 +273,8 @@ } rule conditional_expr { - [ <'null'> <target> ] - | [ <simple_expr> [ <relational_operator> <simple_expr> ]? ] + <'null'> <target> + | <simple_expr> [ <relational_operator> <simple_expr> ]? } ## Jump statements @@ -461,7 +473,9 @@ | [ <target> <'->'> ] ]? # optional invocant [ <target> | <string_constant> ] # method or sub name/id - <parenthesized_args> # sub args + <parenthesized_args> # sub args + <process_heredocs> + <clear_heredocs> } rule sub_invocation { @@ -500,11 +514,20 @@ [ <target> | <syntax_error: target for named argument expected> ] ]? | <target> + | <heredoc_id> ] <set_flags>? } +token heredoc_id { + <'<<'> <string_constant> <store_heredoc_label: $1> +} +rule heredoc_label { + .* ^^ <ident> $$ +} + + ## Argument passing ## rule arguments { @@ -633,10 +656,15 @@ [ <')'> | <syntax_error: ')' expected> ] } -#### TODO: FIX +# In order to be able to parse macro identifiers, before +# the macro body is parsed, some rules are redefined. +# After parsing the macro body, they are restored. +# regex macro_body { - .*? - <'.endm'> \h* \n + <init_macro_rules> + <labeled_pir_instr>* + <'.endm'> + <close_macro_rules> } @@ -713,6 +741,22 @@ # Tokens # +# this is a token, because no spaces are allowed between +# the id and the colon. +token normal_label { + <id> <':'> +} + + +token macro_label { + <'$'> <id> <':'> +} + +rule macro_label_decl { + <'.local'> [ <macro_label> | <syntax_error: $LABEL: expected> ] + | <normal_label> +} + token int_constant { <binary_constant> | <hex_constant> @@ -762,10 +806,17 @@ } -token target { - [ <id> | <reg> ] +token normal_target { + <id> | <reg> } +# in a macro, a target can also be a +# macro_id +# +token macro_target { + <id> | <reg> | <macro_id> +} + token id { <!keyword> \w+ } Index: languages/PIR/pirc.pir =================================================================== --- languages/PIR/pirc.pir (revision 17016) +++ languages/PIR/pirc.pir (working copy) @@ -40,6 +40,9 @@ errs = new .Integer set_root_global 'errors', errs + .local pmc labels + labels = new .ResizablePMCArray + set_root_global 'heredoc', labels # Process command line options load_bytecode "Getopt/Obj.pir" @@ -100,7 +103,7 @@ ERR_MSG: if errs == 1 goto ONE_ERROR - printerr "There were" + printerr "There were " printerr errs printerr " errors.\n" end @@ -158,37 +161,86 @@ load_bytecode 'languages/PIR/lib/pasm_core_gen.pbc' .end -.sub parenthesized_args_2 - .param pmc mob - .param pmc adverbs :slurpy :named - .local pmc match - .local string target - .local int cpos, mfrom, mpos + + + +.sub process_heredocs + .param pmc mob + - (mob, target, mfrom, mpos) = mob.'newfrom'(mob) - printerr "Target: [" - printerr target - printerr "]" + .local pmc labels + labels = get_root_global "heredoc" + .local pmc id + .local int count, i + + count = labels + i = 0 + + loop: + if i >= count goto endloop + id = shift labels + i += 1 + + printerr id + #mob = heredoc_label(mob) + #heredoc_label() + + goto loop + endloop: + +.end + + + +.sub store_heredoc_label + .param pmc mob + .param pmc heredocid + + printerr heredocid printerr "\n" - $S0 = mob.'text'() - printerr $S0 - mob.'next'() - $S0 = mob.'text'() - printerr $S0 - - # - #printerr match - #printerr "\n" - # - #printerr cpos - #printerr "\n" - #printerr target - #printerr "\n" - .return(mob) + + .local pmc labels + labels = get_root_global "heredoc" + push labels, heredocid + +# .local pmc iter, obj +# iter = new .Iterator, labels +# printerr "\n===============\n" +#loop: +# unless iter goto endloop +# obj = shift iter +# printerr "Obj: " +# printerr obj +# printerr "\n" +# goto loop +#endloop: +# printerr "\n===============\n" +# .return (mob, adverbs :flat :named) .end +# +# Clear all heredoc labels +# +.sub clear_heredocs + .local pmc labels + .local int count, i + labels = get_root_global 'heredoc' + count = labels + i = 0 + loop: + if i >= count goto endloop + delete labels[i] + i += 1 + goto loop + endloop: + #printerr "=============\n" +.end + + + + .sub warning .param pmc self .param string message @@ -243,6 +295,58 @@ .end + +=head2 Custom parse methods + +The rules C<target> and C<label> need to be redefined when parsing +macros. These wrapper rules invoke the appropiate rules in pir.pg +depending on the context. + +=cut + +.sub target + .param pmc mob + .param pmc adverbs :slurpy :named + $P0 = get_global 'macro_context' + if null $P0 goto do_normal + if $P0 > 0 goto do_macro + do_normal: + .return normal_target(mob, adverbs :flat :named) + do_macro: + .return macro_target(mob, adverbs :flat :named) +.end + + +.sub label + .param pmc mob + .param pmc adverbs :slurpy :named + $P0 = get_global 'macro_context' + if null $P0 goto do_normal + if $P0 > 0 goto do_macro + do_normal: + .return normal_label(mob, adverbs :flat :named) + do_macro: + .return macro_label_decl(mob, adverbs :flat :named) +.end + +.sub init_macro_rules + .local pmc macro_context + macro_context = new .Integer + macro_context = 1 + set_global 'macro_context', macro_context +.end + +.sub close_macro_rules + $P0 = get_global 'macro_context' + $P0 = 0 +.end + + + + + + + =head1 LICENSE Copyright (C) 2007, The Perl Foundation. Index: languages/PIR/t/macro.t =================================================================== --- languages/PIR/t/macro.t (revision 0) +++ languages/PIR/t/macro.t (revision 0) @@ -0,0 +1,42 @@ +#!perl + +use strict; +use warnings; +use lib qw(t . lib ../lib ../../lib ../../../lib); +use Parrot::Test tests => 1; +use Test::More; + +language_output_is( 'PIR_PGE', <<'CODE', <<'OUT', 'macro pasring' ); + +.sub main + .local int i +.end + +.macro X(a, b) + .a = .b + .local $a: +.endm + + +.sub main + .local int e,f + .X(e,f) +.end + +.macro X(a,b) + .local $x: foo() + + .local $y: + .a = .b + .sym int i +.endm + +.sub main + .X(a,b) +.end + + +CODE +"parse" => PMC 'PIR::Grammar' { ... } +Parse successful! +OUT