NODE* parse_any(SCANNER *s, int mode) { NODE *x = NULL; int c; skip_white(s); if (s_eof(s)) return raise(s, "unexpected end of file"); c = s_peek(s); if (c == '(') { s_getc(s); x = parse_paren(s, mode); if (x == NULL) return NULL; if (s_eof(s)) { return raise(s, "unexpected end of file"); } skip_white(s); if (s_getc(s) != ')') { return invalid_token(s); } } else if (c == '\'') x = parse_quote(s); else if (c == '`') return parse_bquote(s); else if (c == '"') x = parse_string(s); else if (isalnum((int)c) || strchr(SYMBOL_CHARS, c)) x = parse_primitive(s); else return invalid_token(s); return x; }
void test_parse_paren() { struct token_list *tkl = make_token_list(); struct token *tk0 = make_token(tok_punc, "(", 0.0, 0); struct token *tk1 = make_token(tok_number, NULL, 0.0, 42); struct token *tk2 = make_token(tok_punc, "+", 0.0, 0); struct token *tk3 = make_token(tok_number, NULL, 0.0, 24); struct token *tk4 = make_token(tok_punc, ")", 0.0, 0); append_token_list(tkl, tk0); append_token_list(tkl, tk1); append_token_list(tkl, tk2); append_token_list(tkl, tk3); append_token_list(tkl, tk4); struct ast_node *result = parse_paren(tkl); EXPECT_EQ(result->val, tk2); EXPECT_EQ(result->num_children, 2); EXPECT_EQ(result->children[0]->val, tk1); EXPECT_EQ(result->children[1]->val, tk3); EXPECT_EQ(result->children[0]->num_children, 0); EXPECT_EQ(result->children[1]->num_children, 0); destroy_token_list(tkl); delete_node(result); }
AstParen* ParseParen::parse_paren(pstr_t str) { AstParen* paren = new AstParen(); paren->strhead = str; switch (get_symbol(str)) { case SYMBOL_PAREN_LEFT: break; default: pstr_t recover = syntaxErrorHandler->never_reach(str, __FUNCTION__); if (recover == line->end()) { delete paren; return parse_paren(recover); } else { paren->strtail = recover; return paren; } } AstNode *expr = parseExpression->parse(scan(str+1)); str = scan(expr->strtail); paren->children.push_back(expr); while (true) { switch (get_symbol(str)) { case SYMBOL_PAREN_RIGHT: paren->strtail = str + 1; return paren; default: str = syntaxErrorHandler->invalid_char(str, __FUNCTION__); if (str == line->end()) { paren->strtail = str; return paren; } } } }