summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parser.c18
-rw-r--r--tests/010/json.tl22
-rw-r--r--tests/012/parse.tl52
-rw-r--r--txr.118
4 files changed, 106 insertions, 4 deletions
diff --git a/parser.c b/parser.c
index bc01c2bf..fd274ebb 100644
--- a/parser.c
+++ b/parser.c
@@ -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)
diff --git a/txr.1 b/txr.1
index 0e38dff4..ac6edd06 100644
--- a/txr.1
+++ b/txr.1
@@ -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