]> gitweb.factorcode.org Git - factor.git/commitdiff
Add a hand parser. Improves speed from 23 seconds to 0.03 seconds when parsing a...
authorPhilipp Winkler <philippwinkler@gmail.com>
Fri, 29 May 2009 21:41:24 +0000 (14:41 -0700)
committerPhilipp Winkler <philippwinkler@gmail.com>
Thu, 4 Jun 2009 18:25:33 +0000 (11:25 -0700)
basis/json/reader/authors.txt
basis/json/reader/reader-tests.factor
basis/json/reader/reader.factor

index 44b06f94bce2ac1f87c75319d38703e6ad205a53..d269b4ffb5eeb52d93237bde1cc2ce661ffd9618 100644 (file)
@@ -1 +1,3 @@
 Chris Double
+Peter Burns
+Philipp Winkler
index e97d45babe179f928e83cc285dc50a60ea680b9b..fa6c8d7d3aaa21807f49d212108729465b5deb9f 100644 (file)
@@ -19,6 +19,8 @@ IN: json.reader.tests
 { 10.25 } [ "1025e-2" json> ] unit-test
 { 0.125 } [ "0.125" json> ] unit-test
 { -0.125 } [ "-0.125" json> ] unit-test
+{ -0.00125 } [ "-0.125e-2" json> ] unit-test
+{ -012.5 } [ "-0.125e+2" json> ] unit-test
 
 ! not widely supported by javascript, but allowed in the grammar, and a nice
 ! feature to get
index 887a7a50e5672e396aae587b46d55e26c7991831..1544af55cfd9f97d3ee505e6a7e755f7e73aed80 100644 (file)
@@ -1,61 +1,97 @@
-! Copyright (C) 2008 Peter Burns.
+! Copyright (C) 2008 Peter Burns, 2009 Philipp Winkler
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel peg peg.ebnf math.parser math.parser.private strings math
-math.functions sequences arrays vectors hashtables assocs
-prettyprint json ;
+USING: arrays assocs combinators io io.streams.string json
+kernel math math.parser math.parser.private sequences strings ;
 IN: json.reader
 
 <PRIVATE
+: value ( char -- num char )
+    1string " \t\r\n,:}]" read-until
+    [
+        append
+        [ string>float ]
+        [ [ "eE." index ] any? [ >integer ] unless ] bi
+    ] dip ;
 
-: grammar-list>vector ( seq -- vec ) first2 values swap prefix ;
+DEFER: j-string
+    
+: convert-string ( str -- str )
+    read1
+    {
+        { CHAR: b [ 8 ] }
+        { CHAR: f [ 12 ] }
+        { CHAR: n [ CHAR: \n ] }
+        { CHAR: r [ CHAR: \r ] }
+        { CHAR: t [ CHAR: \t ] }
+        { CHAR: u [ 4 read hex> ] }
+        [ ]
+    } case
+    dup
+    [ 1string append j-string append ]
+    [ drop ] if ;
+    
+: j-string ( -- str )
+    "\\\"" read-until CHAR: \" =
+    [ convert-string ] unless ;
+    
+: second-last ( seq -- second-last )
+    [ length 2 - ] keep nth ; inline
 
-! Grammar for JSON from RFC 4627
-EBNF: (json>)
+: third-last ( seq -- third-last )
+    [ length 3 - ] keep nth ; inline
+    
+: last2 ( seq -- second-last last )
+    [ second-last ] [ last ] bi ; inline
 
-ws = (" " | "\r" | "\t" | "\n")*
+: last3 ( seq -- third-last second-last last )
+    [ third-last ] [ last2 ] bi ; inline
 
-true = "true" => [[ t ]]
-false = "false" => [[ f ]]
-null = "null" => [[ json-null ]]
+: v-over-push ( vec -- vec' )
+    dup length 2 >=
+    [
+        dup
+        [ pop ]
+        [ last ] bi push
+    ] when ;
 
-hex = [0-9a-fA-F]
-char = '\\"'  [[ CHAR: "  ]]
-     | "\\\\" [[ CHAR: \  ]]
-     | "\\/"  [[ CHAR: /  ]]
-     | "\\b"  [[ 8        ]]
-     | "\\f"  [[ 12       ]]
-     | "\\n"  [[ CHAR: \n ]]
-     | "\\r"  [[ CHAR: \r ]]
-     | "\\t"  [[ CHAR: \t ]]
-     | "\\u" (hex hex hex hex) [[ hex> ]] => [[ second ]]
-     | [^"\]
-string = '"' char*:cs '"' => [[ cs >string ]]
+: v-pick-push ( vec -- vec' )
+    dup length 3 >=
+    [
+        dup
+        [ pop ]
+        [ second-last ] bi push
+    ] when ;
 
-sign = ("-" | "+")? => [[ "-" = "-" "" ? ]]
-digits = [0-9]+     => [[ >string ]]
-decimal = "." digits  => [[ concat ]]
-exp = ("e" | "E") sign digits => [[ concat ]]
-number = sign digits decimal? exp? => [[ dup concat swap fourth [ string>float ] [ string>number ] if ]]
-
-elements = value ("," value)* => [[ grammar-list>vector ]]
-array = "[" elements?:arr "]" => [[ arr >array ]]
-
-pair = ws string:key ws ":" value:val => [[ { key val } ]]
-members = pair ("," pair)* => [[ grammar-list>vector ]]
-object = "{" members?:hash "}" => [[ hash >hashtable ]]
-
-val = true
-    | false
-    | null
-    | string
-    | number
-    | array
-    | object
-
-value = ws val:v ws => [[ v ]]
-
-;EBNF
+: (close-hash) ( accum -- accum' )
+    dup length 3 >= [ v-over-push ] when
+    dup dup [ pop ] dip pop swap
+    zip H{ } assoc-clone-like over push ;
+                                                 
+: scan ( accum char -- accum )
+    [
+        {
+            { CHAR: \" [ j-string over push ] }
+            { CHAR: [  [ V{ } clone over push ] }
+            { CHAR: ,  [ v-over-push ] }
+            { CHAR: ]  [ v-over-push dup pop >array over push ] }
+            { CHAR: {  [ 2 [ V{ } clone over push ] times ] }
+            { CHAR: :  [ v-pick-push ] }
+            { CHAR: }  [ (close-hash) ] }
+            { CHAR: \u000020 [ ] }
+            { CHAR: \t [ ] }
+            { CHAR: \r [ ] }
+            { CHAR: \n [ ] }
+            { CHAR: t  [ 3 read drop t over push ] }
+            { CHAR: f  [ 4 read drop f over push ] }
+            { CHAR: n  [ 3 read drop json-null over push ] }
+            [ value [ over push ] dip [ scan ] when*  ]
+        } case 
+    ] when* ;
 
+: (json-parser>) ( string -- object )
+    [ V{ } clone [ read1 dup ] [ scan ] while drop first ] with-string-reader ;
+    
 PRIVATE>
-
-: json> ( string -- object ) (json>) ;
\ No newline at end of file
+    
+: json> ( string -- object )
+    (json-parser>) ;
\ No newline at end of file