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]


Reply via email to