cf2eff500b0e — Chris Cannam 6 years ago
Error reporting improvements
1 files changed, 13 insertions(+), 11 deletions(-)

M json.sml
M json.sml +13 -11
@@ 1,6 1,7 @@ 
 
-(* An RFC-compliant minimal JSON parser with no dependency on anything
-   outside the Basis library. Also includes a simple serialiser.
+(* An RFC-compliant JSON parser in one SML file with no dependency 
+   on anything outside the Basis library. Also includes a simple
+   serialiser.
 
    Parser notes:
 

          
@@ 122,21 123,21 @@ structure Json :> JSON = struct
                  else raise Fail ("Invalid BMP point " ^ (Word.toString cp)))
         end
                       
-    fun error pos text = ERROR (text ^ " at position " ^ Int.toString (pos - 1))
-    fun token_error pos expected =
-        error pos ("Malformed token (expected \"" ^ expected ^ "\")")
+    fun error pos text = ERROR (text ^ " at character position " ^
+                                Int.toString (pos - 1))
+    fun token_error pos = error pos ("Unexpected token")
 
     fun lexNull pos acc (#"u" :: #"l" :: #"l" :: xs) =
         lex (pos + 3) (T.NULL :: acc) xs
-      | lexNull pos acc _ = token_error pos "null"
+      | lexNull pos acc _ = token_error pos
 
     and lexTrue pos acc (#"r" :: #"u" :: #"e" :: xs) =
         lex (pos + 3) (T.BOOL true :: acc) xs
-      | lexTrue pos acc _ = token_error pos "true"
+      | lexTrue pos acc _ = token_error pos
 
     and lexFalse pos acc (#"a" :: #"l" :: #"s" :: #"e" :: xs) =
         lex (pos + 4) (T.BOOL false :: acc) xs
-      | lexFalse pos acc _ = token_error pos "false"
+      | lexFalse pos acc _ = token_error pos
 
     and lexChar tok pos acc xs =
         lex pos (tok :: acc) xs

          
@@ 193,10 194,10 @@ structure Json :> JSON = struct
                 else if Char.isDigit x orelse List.exists (fn c => x = c) valid
                 then lexNumber' (pos + 1) (x :: digits) xs
                 else (rev digits, x :: xs, pos)
-            val (digits, rest, newpos) = lexNumber' pos [] (firstChar :: cc)
+            val (digits, rest, newpos) = lexNumber' (pos - 1) [] (firstChar :: cc)
         in
             case digits of
-                [] => error pos "Unexpected token"
+                [] => token_error pos
               | _ => lex newpos (T.NUMBER digits :: acc) rest
         end
                                            

          
@@ 271,7 272,8 @@ structure Json :> JSON = struct
                      ERROR e => ERROR e
                    | OK (j, xs) => OK ((key, j), xs))
               | parsePair other =
-                ERROR ("Object key/value pair expected before " ^ show other)
+                ERROR ("Object key/value pair expected around \"" ^
+                       show other ^ "\"")
             fun parseObject' acc [] = ERROR "End of input during object"
               | parseObject' acc tokens =
                 case parsePair tokens of