ExpPtr parseCond (Lexer& lex) { Span spStart, spEnd; ExpPtr expCond, expThen, expElse; bool blockRequired = true; spStart = lex.eat(tIf).span; expCond = parseExp(lex); if (lex.current() == tThen) { lex.advance(); blockRequired = false; } expThen = blockRequired ? parseBlock(lex) : parseExp(lex); if (lex.current() == tElse) { lex.advance(); if (blockRequired) { // if {} else {} // if {} else if ... if (lex.current() != tIf) lex.expect(tLCurl); expElse = parseExp(lex); } else expElse = parseExp(lex); spEnd = expElse->span; } else if (!blockRequired) lex.expect(tElse); else { auto expUnit = Exp::make(eTuple, {}, spStart); expThen->subexps.push_back(expUnit); expElse = expUnit; // no else => unit (zero tuple) spEnd = expThen->span; } return Exp::make(eCond, { expCond, expThen, expElse }, spStart + spEnd); }
GlobProto parseToplevel (Lexer& lex) { GlobProto res; while (parseToplevel(lex, res)) ; lex.expect(tEOF); return res; }
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 parseAssign (Lexer& lex, ExpPtr left) { if (lex.current() != tEqual) return left; lex.eat(tEqual); auto right = parseExp(lex); lex.expect(tSemicolon); return Exp::make(eAssign, { left, right }, left->span + right->span); }
TyPtr parseType (Lexer& lex, Span& sp) { switch (lex.current().tok) { case tLambda: return parseTypePoly(lex, sp); case tLBrack: return parseTypeList(lex, sp); case tLParen: return parseTypeTuple(lex, sp); case tIdent: return parseTypeConcrete(lex, sp); case tWildcard: sp = lex.current().span; lex.advance(); return Ty::makeWildcard(); default: lex.expect("type"); return nullptr; } }
SigPtr parseSig (Lexer& lex, bool anything) { auto res = std::make_shared<Sig>(); // sig := (<var> (',' <var>)*)? for (;; anything = true) { if (anything) lex.expect(tIdent); else if (lex.current() != tIdent) break; parseVar(lex, res); if (lex.current() == tComma) lex.advance(); else break; } return res; }
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); }