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
