From d96ab7d81aeb9676779faa7c1380dd48f5440b07 Mon Sep 17 00:00:00 2001 From: Mistivia Date: Thu, 19 Jun 2025 07:06:29 +0800 Subject: parse list test --- src/parser.c | 16 +++++++- tests/test_parser.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/parser.c b/src/parser.c index ff7d625..f60946a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -118,7 +118,17 @@ static ParseResult expect_space(Parser *parser) { return ParseErr(parser, "Unexpected EOF.\n."); } if (isspace(Parser_peek(parser))) { - Parser_getchar(parser); + return ParseOk(parser->ctx->nil); + } + return ParseErr(parser, "Expect space.\n"); +} + +static ParseResult expect_space_or_end(Parser *parser) { + if (Parser_peek(parser) == EOF) { + return ParseErr(parser, "Unexpected EOF.\n."); + } + if (isspace(Parser_peek(parser)) + || Parser_peek(parser) == ')') { return ParseOk(parser->ctx->nil); } return ParseErr(parser, "Expect space.\n"); @@ -127,6 +137,7 @@ static ParseResult expect_space(Parser *parser) { static SExpRef build_list_from_vector(Interp *ctx, SExpRefVector elems) { int i = SExpRefVector_len(&elems) - 1; SExpRef ret = *SExpRefVector_ref(&elems, i); + i--; for (; i >= 0; i--) { SExpRef cur = *SExpRefVector_ref(&elems, i); ret = cons(ctx, cur, ret); @@ -159,7 +170,7 @@ ParseResult parse_list(Parser *parser) { ret = parse_sexp(parser); if (ParseResult_is_err(ret)) goto end; SExpRefVector_push_back(&elems, ret.val); - ret = expect_space(parser); + ret = expect_space_or_end(parser); if (ParseResult_is_err(ret)) goto end; skip_spaces(parser); } @@ -183,6 +194,7 @@ static char *read_token(Parser *parser) { int i = 0; while (!isspace(Parser_peek(parser)) && Parser_peek(parser) != EOF + && Parser_peek(parser) != ')' && i < BUFSIZE - 1) { parser->token_buf[i] = Parser_getchar(parser); i++; diff --git a/tests/test_parser.c b/tests/test_parser.c index c0587cb..28c30e0 100644 --- a/tests/test_parser.c +++ b/tests/test_parser.c @@ -43,7 +43,113 @@ int main() { parser.ctx = &interp; ParseResult res; - SExp sexp; + SExp sexp, a, b, c; + + res = parse_str(&parser, "((1 2)\n . 3)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kPairSExp); + c = *Interp_ref(&interp, a.pair.cdr); + a = *Interp_ref(&interp, a.pair.car); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + a = *Interp_ref(&interp, c.pair.car); + c = *Interp_ref(&interp, c.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 2); + assert(c.type == kNilSExp); + assert(b.type == kIntegerSExp); + assert(b.integer == 3); + + res = parse_str(&parser, "((1 2) . 3)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kPairSExp); + c = *Interp_ref(&interp, a.pair.cdr); + a = *Interp_ref(&interp, a.pair.car); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + a = *Interp_ref(&interp, c.pair.car); + c = *Interp_ref(&interp, c.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 2); + assert(c.type == kNilSExp); + assert(b.type == kIntegerSExp); + assert(b.integer == 3); + + res = parse_str(&parser, "((1 2) 3)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kPairSExp); + c = *Interp_ref(&interp, a.pair.cdr); + a = *Interp_ref(&interp, a.pair.car); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + a = *Interp_ref(&interp, c.pair.car); + c = *Interp_ref(&interp, c.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 2); + assert(c.type == kNilSExp); + a = *Interp_ref(&interp, b.pair.car); + b = *Interp_ref(&interp, b.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 3); + assert(b.type == kNilSExp); + + ERROR_TEST("(1 2 . 3 4)"); + ERROR_TEST("(1 2 . )"); + ERROR_TEST("(1 2 .)"); + + res = parse_str(&parser, "(1 2 . 3)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + assert(b.type == kPairSExp); + a = *Interp_ref(&interp, b.pair.car); + b = *Interp_ref(&interp, b.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 2); + assert(b.type == kIntegerSExp); + assert(b.integer == 3); + + res = parse_str(&parser, "(1 . 2)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + assert(b.type == kIntegerSExp); + assert(b.integer == 2); + + res = parse_str(&parser, "(1 2)"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kPairSExp); + a = *Interp_ref(&interp, sexp.pair.car); + b = *Interp_ref(&interp, sexp.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 1); + a = *Interp_ref(&interp, b.pair.car); + b = *Interp_ref(&interp, b.pair.cdr); + assert(a.type == kIntegerSExp); + assert(a.integer == 2); + assert(b.type == kNilSExp); + ATOM_TEST("1.11", kRealSExp, real, 1.11); ATOM_TEST("-1.11", kRealSExp, real, -1.11); @@ -76,6 +182,11 @@ int main() { ERROR_TEST("@1"); ERROR_TEST("a|"); + res = parse_str(&parser, "()"); + assert(!ParseResult_is_err(res)); + sexp = *Interp_ref(&interp, res.val); + assert(sexp.type == kNilSExp); + Interp_free(&interp); Parser_free(&parser); printf("[PASS] parser\n"); -- cgit v1.0