ExpPtr parseCall (Lexer& lex, ExpPtr in) { auto args = parseTuple(lex); ExpList exps; exps.reserve(args->subexps.size() + 1); exps.push_back(in); exps.insert(exps.end(), args->subexps.begin(), args->subexps.end()); return Exp::make(eCall, exps, in->span + args->span); }
void parseBlockExp (Lexer& lex, ExpList& list) { switch (lex.current().tok) { case tSemicolon: lex.advance(); break; case tLet: list.push_back(parseLet(lex)); lex.eat(tSemicolon); break; case tLCurl: list.push_back(parseBlock(lex)); break; case tIf: list.push_back(parseCond(lex)); break; case tLoop: list.push_back(parseLoop(lex)); break; case tFor: list.push_back(parseFor(lex)); break; // everthing else does default: list.push_back(parseAssign(lex, parseExp(lex))); if (lex.current() != tSemicolon) lex.expect(tRCurl); else lex.eat(tSemicolon); break; } }
ExpPtr parseLoop (Lexer& lex) { Span spStart, spEnd; ExpPtr body; spStart = lex.eat(tLoop).span; ExpList sub; sub.reserve(2); if (lex.current() == tLCurl) { sub.push_back(body = parseBlock(lex)); } else { sub.push_back(parseExp(lex)); sub.push_back(body = parseBlock(lex)); } spEnd = body->span; return Exp::make(eLoop, std::move(sub), spStart + spEnd); }
ExpPtr parseExp (Lexer& lex) { Span spStart, spEnd; ExpList vals; ExpPtr e; Token tok; e = parseTerm(lex); vals.push_back(e); spStart = spEnd = e->span; while (lex.current() == tIdent) if (lex.current().isOperator()) { // <op> tok = lex.advance(); e = Exp::make(eVar, tok.str, bool(true), {}, tok.span); vals.push_back(e); // <term> e = parseTerm(lex); vals.push_back(e); spEnd = e->span; } else lex.expect("operator"); if (vals.size() == 1) return vals[0]; // else if (vals.size() == 3) // return Exp::make(eCall, { vals[1], vals[0], vals[2] }, // spStart + spEnd); else return Exp::make(eInfix, vals, spStart + spEnd); }
ExpPtr parseList (Lexer& lex) { Span spStart, spEnd; ExpList vals; spStart = lex.eat(tLBrack).span; while (lex.current() != tRBrack) { vals.push_back(parseExp(lex)); if (lex.current() == tComma) lex.advance(); else break; } spEnd = lex.eat(tRBrack).span; return Exp::make(eList, std::move(vals), spStart + spEnd); }
ExpPtr parseTuple (Lexer& lex) { ExpList exps; ExpPtr e; Span spStart, spEnd; spStart = lex.eat(tLParen).span; while (lex.current() != tRParen) { e = parseExp(lex); exps.push_back(e); if (lex.current() == tComma) lex.advance(); else break; } spEnd = lex.eat(tRParen).span; return Exp::make(eTuple, exps, spStart + spEnd); }