/* Tuplr: A programming language * Copyright (C) 2008-2009 David Robillard * * Tuplr is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * Tuplr is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Tuplr. If not, see . */ #include #include "tuplr.hpp" #define FOREACH(IT, i, c) for (IT i = (c).begin(); i != (c).end(); ++i) using namespace std; using boost::format; Funcs ASTConsCall::funcs; std::ostream& err = std::cerr; std::ostream& out = std::cout; /*************************************************************************** * S-Expression Lexer :: text -> S-Expressions (SExp) * ***************************************************************************/ SExp readExpression(Cursor& cur, std::istream& in) { #define PUSH(s, t) { if (t != "") { s.top().list.push_back(SExp(loc, t)); t = ""; } } #define YIELD(s, t) { if (s.empty()) { return SExp(loc, t); } else PUSH(s, t) } stack stk; string tok; Cursor loc; // start of tok while (char ch = in.get()) { ++cur.col; switch (ch) { case EOF: if (!stk.empty()) throw Error("unexpected end of file", cur); return SExp(cur); case ';': while ((ch = in.get()) != '\n') {} case '\n': ++cur.line; cur.col = 0; case ' ': case '\t': if (tok != "") YIELD(stk, tok); break; case '"': loc = cur; do { tok.push_back(ch); ++cur.col; } while ((ch = in.get()) != '"'); YIELD(stk, tok + '"'); break; case '(': stk.push(SExp(cur)); break; case ')': switch (stk.size()) { case 0: throw Error("unexpected `)'", cur); case 1: PUSH(stk, tok); return stk.top(); default: PUSH(stk, tok); SExp l = stk.top(); stk.pop(); stk.top().list.push_back(l); } break; default: if (tok == "") loc = cur; tok += ch; } } switch (stk.size()) { case 0: return SExp(loc, tok); case 1: return stk.top(); default: throw Error("missing `)'", cur); } return SExp(cur); }