diff options
-rw-r--r-- | parser.c | 18 | ||||
-rw-r--r-- | tests/010/json.tl | 22 | ||||
-rw-r--r-- | tests/012/parse.tl | 52 | ||||
-rw-r--r-- | txr.1 | 18 |
4 files changed, 106 insertions, 4 deletions
@@ -636,11 +636,12 @@ static val lisp_parse_impl(val self, enum prime_parser prime, { uses_or2; val source = default_null_arg(source_in); - val input_stream = if3(stringp(source), + val str = stringp(source); + val input_stream = if3(str, make_string_byte_input_stream(source), or2(source, std_input)); val name = or2(default_null_arg(name_in), - if3(stringp(source), + if3(str, lit("string"), stream_get_prop(input_stream, name_k))); val parser = ensure_parser(input_stream, name); @@ -676,6 +677,19 @@ static val lisp_parse_impl(val self, enum prime_parser prime, break; } + if (str) { + int junk = 0; + if (prime == prime_json) { + yystype yyl; + junk = yylex(&yyl, pi->scanner); + } else { + junk = pi->recent_tok.yy_char; + } + + if (junk) + yyerrorf(pi->scanner, lit("trailing material after expression"), nao); + } + parsed = t; uw_unwind { diff --git a/tests/010/json.tl b/tests/010/json.tl index 29ee2833..8d414b2e 100644 --- a/tests/010/json.tl +++ b/tests/010/json.tl @@ -92,7 +92,27 @@ (get-json "\"abc\"") "abc" (get-json "true") t (get-json "false") nil - (get-json "null") null) + (get-json "null") null + (get-json "[1,2,3]") #(1.0 2.0 3.0) + (get-json "{\"a\":\"b\"}") #H(() ("a" "b"))) + +(mtest + (get-json "0 \n") 0.0 + (get-json "\"abc\" \n") "abc" + (get-json "true \n") t + (get-json "false \n") nil + (get-json "null \n") null + (get-json "[1,2,3] \n") #(1.0 2.0 3.0) + (get-json "{\"a\":\"b\"} \n") #H(() ("a" "b"))) + +(mtest + (get-json "0,") :error + (get-json "\"abc\",") :error + (get-json "true,") :error + (get-json "false,") :error + (get-json "null,") :error + (get-json "[1,2,3],") :error + (get-json "{\"a\":\"b\"},") :error) (mtest (tojson #(1.0 "abc" t)) "[1,\"abc\",true]" diff --git a/tests/012/parse.tl b/tests/012/parse.tl index 2bce20dc..6d091b00 100644 --- a/tests/012/parse.tl +++ b/tests/012/parse.tl @@ -12,3 +12,55 @@ (test (regex-parse (str-buf #b'F3FF')) (compound #\xDCF3 #\xDCFF))) + +(mtest + (read "0") 0 + (read "0x") 0x + (read "a") a + (read "abc") abc + (read "abc.def") abc.def + (read "(1 2 3)") (1 2 3) + (read "#;(1 2 3) 4") 4 + (read "#;(1 2 3) #; a.b 4") 4 + (read "0 ") 0 + (read "0x ") 0x + (read "a ") a + (read "abc ") abc + (read "abc.def ") abc.def + (read "(1 2 3) ") (1 2 3) + (read "#;(1 2 3) 4 ") 4 + (read "#;(1 2 3) #; a.b 4 ") 4 + (read "0,") :error + (read "0x,") :error + (read "a,") :error + (read "abc,") :error + (read "abc.def,") :error + (read "(1 2 3),") :error + (read "#;(1 2 3) 4,") :error + (read "#;(1 2 3) #; a.b 4,") :error) + +(mtest + (iread "0") 0 + (iread "0x") 0x + (iread "a") a + (iread "abc") abc + (iread "abc.def") abc + (iread "(1 2 3)") (1 2 3) + (iread "#;(1 2 3) 4") 4 + (iread "#;(1 2 3) #; a.b 4") .b + (iread "0 ") 0 + (iread "0x ") 0x + (iread "a ") a + (iread "abc ") abc + (iread "abc.def ") abc + (iread "(1 2 3) ") (1 2 3) + (iread "#;(1 2 3) 4 ") 4 + (iread "#;(1 2 3) #; a.b 4 ") .b + (iread "0,") 0 + (iread "0x,") 0x + (iread "a,") a + (iread "abc,") abc + (iread "abc.def,") abc + (iread "(1 2 3),") (1 2 3) + (iread "#;(1 2 3) 4,") 4 + (iread "#;(1 2 3) #; a.b 4,") .b) @@ -57319,7 +57319,23 @@ string, or a stream. If it is omitted, then .code *stdin* is used as the stream. -The source must provide the text representation of one complete \*(TL object. +The +.meta source +must provide the text representation of one complete \*(TL object. +If +.meta source +and the function being applied is +.codn read , +then if the object is followed by any non-whitespace material, the +situation is treated as a syntax error, even if that material is +a syntactically valid additional object. +The +.code iread +function ignores this situation. Other differences between +.code read +and +.code iread +are given below. Multiple calls to read on the same stream will extract successive objects from the stream. To parse successive objects from a string, it is necessary |