Trying to implement a JSON parser in PGE:
(probably buggy) Grammar: (Feel free to send corrections to this
offlist. =-)
# From http://www.json.org/
grammar JSON;
rule object { \{ <members>? \} }
rule array { \[ <elements>? \] }
rule string { " <char>* " }
rule members { <string> : <value> [, <string> : <value> ] * }
rule elements { <value> [, <value> ] * }
rule value {
| <string>
| <number>
| <object>
| <array>
| true
| false
| null
}
# XXX Doesn't handle the "or-control" atm.
rule char {
| <-["\\]>
| \\ <["\\/bfnrt]>
| \u <[0..9a..fA..F]>**{4}
}
rule number {
-?
[ <[0..9]> | <[1..9]> <[0..9]>+]
[ \. <[0..9]>+ ]?
[ <[Ee]> <[+\-]>? <[0..9]>+ ]?
}
I then use pgc to compile this to a .pir file, and use the following
test file:
.sub main :main
load_bytecode 'PGE.pbc'
load_bytecode 'grammar.pir' # the json grammar file
.local pmc parse, match
parse = get_root_global ['parrot'; 'JSON'], 'value'
$P0 = get_root_global ['parrot'; 'PGE::Match'], 'newfrom'
match = $P0('3.2', '0', 'JSON')
match.to(0)
match = parse(match)
unless match goto failed
load_bytecode 'dumper.pbc'
load_bytecode 'PGE/Dumper.pbc'
$S0 = typeof match
say $S0
$P0 = get_root_global ['parrot'], '_dumper'
$P0(match)
end
failed:
say "that's not a JSON value"
.end
When I run this, I get the following error:
JSON
"VAR1" => PMC 'JSON' => Null PMC access in get_string()
current instr.: 'parrot;PGE::Match;new' pc 506 (compilers/pge/PGE/
Match.pir:187)
called from Sub 'parrot;JSON;value' pc 3990 (grammar.pir:1525)
called from Sub 'parrot;PGE::Match;__get_string' pc 773 (compilers/
pge/PGE/Match.pir:367)
called from Sub 'parrot;JSON;value' pc 4038 (grammar.pir:1545)
called from Sub 'parrot;PGE::Match;__get_string' pc 773 (compilers/
pge/PGE/Match.pir:367)
called from Sub 'parrot;PGE::Match;__dump' pc 20 (runtime/parrot/
library/PGE/Dumper.pir:33)
called from Sub 'parrot;Data::Dumper::Default;pmcDefault' pc 262 (/
Users/wcoleda/research/parrot/runtime/parrot/library/Data/Dumper/
Default.pir:202)
called from Sub 'parrot;Data::Dumper::Base;dump' pc 393 (/Users/
wcoleda/research/parrot/runtime/parrot/library/Data/Dumper/Base.pir:251)
called from Sub 'parrot;Data::Dumper::Default;dumpWithName' pc 39 (/
Users/wcoleda/research/parrot/runtime/parrot/library/Data/Dumper/
Default.pir:51)
called from Sub 'parrot;Data::Dumper;dumper' pc 63 (/Users/wcoleda/
research/parrot/runtime/parrot/library/Data/Dumper.pir:33)
called from Sub '_dumper' pc 52 (runtime/parrot/library/dumper.pir:87)
called from Sub 'main' pc 70 (test.pir:20)
Jerry Gay suggests via IRC that this is related to the recent None/
Null changes. Poking around a bit, I see that 'target' is a PMC in
the body of Match::new, but a string is expected in the return value
of this call in the generated JSON::value. So, applying the following
naive patch to avoid returning a Null PMC where it might get
autoboxed to a string...
(*small test case that shows this behavior:
.sub main :main
$S0 = doit()
.end
.sub doit
null P1
.return (P1)
.end
*)
--- compilers/pge/PGE/Match.pir (revision 836)
+++ compilers/pge/PGE/Match.pir (local)
@@ -76,6 +76,9 @@
if from >= 0 goto end
from = fromd
end:
+ unless null target goto real_end
+ target = new .Undef
+ real_end:
.return (me, target, from, pos)
.end
@@ -184,6 +187,9 @@
mpos = -1
setattribute mob, '$.pos', mpos
+ unless null target goto done
+ target = new .Undef
+ done:
.return (mob, pos, target, mfrom, mpos, iscont)
.end
rebuilding, and rerunning the test file gives instead:
JSON
"VAR1" => PMC 'JSON' => maximum recursion depth exceeded
current instr.: 'parrot;PGE::Match;newfrom' pc 254 (compilers/pge/PGE/
Match.pir:42)
called from Sub 'parrot;PGE::Match;ws' pc 3177 (compilers/pge/PGE/
Regex.pir:423)
called from Sub 'parrot;JSON;string' pc 1600 (grammar.pir:623)
called from Sub 'parrot;JSON;value' pc 4272 (grammar.pir:1644)
called from Sub 'parrot;PGE::Match;__get_string' pc 791 (compilers/
pge/PGE/Match.pir:375)
called from Sub 'parrot;JSON;value' pc 4038 (grammar.pir:1545)
called from Sub 'parrot;PGE::Match;__get_string' pc 791 (compilers/
pge/PGE/Match.pir:375)
called from Sub 'parrot;JSON;value' pc 4038 (grammar.pir:1545)
called from Sub 'parrot;PGE::Match;__get_string' pc 791 (compilers/
pge/PGE/Match.pir:375)
called from Sub 'parrot;JSON;value' pc 4038 (grammar.pir:1545)
called from Sub 'parrot;PGE::Match;__get_string' pc 791 (compilers/
pge/PGE/Match.pir:375)
<SNIP>
So clearly my old patch is slightly too naive.
Anyone cares to dig deeper, I'd appreciate it.
--
Will "Coke" Coleda
[EMAIL PROTECTED]