Excursions into Parrot
Let me warn you from the start: Patrick Michaud’s slides make it look deceptively easy!
First of all, I created “simple.pg” according to his recipe:
grammar Simple::Grammar ;
token variable { [ | _ ] \w* }
token number { \d+ }
token addop { \+ | - }
token mulop { \* | / }
rule expression { [ ] * }
rule addterm { [ ] * }
rule multerm { | | \( \) }
This looks all fine and dandy. Next, to compile: $ parrot pgc.pir simple.pg > simple.pir.
Error reading source file pgc.pir.
Huh? Well he didn’t say anything about that. Maybe I have a path wrong somewhere? A quick “locate” reveals it doesn’t lie anywhere on my computer. Next step is to check the downloaded source code to see if I wasn’t meant to delete it yet… ah, yes, it’s hiding under ./compilers/pge/. It looks like it will be easier to work from this directory, so I’ll move everything into there.
Unfortunately, pgc.pir won’t run straight away, and you’ll need to patch it up a bit:
@@ -49,7 +49,7 @@
.param pmc args
load_bytecode 'Getopt/Obj.pbc'
load_bytecode 'dumper.pbc'
- load_bytecode 'PGE/Dumper.pbc'
+ load_bytecode 'Data/Dumper.pbc'
'__onload'()
## create an option parser
@@ -153,8 +153,8 @@
.sub '__onload' :load
load_bytecode 'PGE.pbc'
- load_bytecode 'PGE/Text.pbc'
- load_bytecode 'PGE/Util.pbc'
+ load_bytecode 'PGE/Text.pir'
+ load_bytecode 'PGE/Util.pir'
.local pmc p6regex
p6regex = compreg 'PGE:
6Regex'
Now it runs fine and generates the output file perfectly. Quite a bit of code in there! Next to use the parser on a real string, using the example:
.include 'simple.pir'
.sub 'foo'
...
## get the parrot sub for parsing an expression
parse = find_global 'Simple::Grammar', 'expression'
## the expression to be parsed
expr = '3 + 4 * (a-2)'
## parse the expression
match = parse(expr)
## dump the parse tree
'_dumper'(match)
That little ellipsis is really in there to let you know that you need to read quite a few more Parrot docs before you’re allowed to progress past this step. ![]()
In fact, you’ll be able to get up to speed in no time just by copying some of the example files. I found that I could get by with guessing a bit;
- .sub needed an .end,
- the main method needs to be marked :main to run automatically,
- the variables need to be declared… with appropriate types… you can’t just use pmc for everything,
- and the _dumper code needed to be loaded.
Here’s what it eventually looked like:
.include 'simple.pir'
.sub main :main
.local pmc parse, match
.local string expr
## get the parrot sub for parsing an expression
parse = find_global 'Simple::Grammar', 'expression'
## the expression to be parsed
expr = "3 + 4 * (a-2)"
## parse the expression
match = parse(expr)
## dump the parse tree
load_bytecode 'dumper.pbc'
'_dumper'(match)
.end
But that’s not all, you’ll need to jump through the automagically-generated parser code to put in things that it forgot to. For brevity, here’s the diff:
@@ -1,6 +1,7 @@
.sub '__onload' :load
.local pmc optable
## namespace Simple::Grammar
+ load_bytecode 'PGE.pbc'
$I0 = find_type 'Simple::Grammar'
if $I0 != 0 goto onload_186
$P0 = subclass 'PGE::Grammar', 'Simple::Grammar'
@@ -288,6 +289,7 @@
.local string target :unique_reg
.local pmc mfrom, mpos :unique_reg
.local int cpos, iscont :unique_reg
+ load_bytecode 'PGE/Match.pir'
$P0 = getclass 'PGE::Match'
(mob, cpos, target, mfrom, mpos, iscont) = $P0.'new'(mob, adverbs :flat :named) .local pmc ustack :unique_reg
@@ -321,6 +323,7 @@
goto fail_cut
R: # concat
R147: # subrule ws
+ load_bytecode 'PGE/Regex.pir'
captob = captscope
$P0 = getattribute captob, '$.pos'
$P0 = pos
And now, one and a half hours later, for the grand finale…
$ parrot simpleparse.pir
"VAR1" => PMC 'PGE::Match' { ... }
VoilĂ ! My first excursion into Parrot. A bit fiddly, but I enjoyed myself ![]()

This parrot is DEAD!
No; merely pining.