From 314482b95ff83f1f88e41d45fadd05a7e625bb0c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 29 Jun 2009 00:28:50 +0000 Subject: Split code up further. git-svn-id: http://svn.drobilla.net/resp/tuplr@165 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/lex.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/lex.cpp (limited to 'src/lex.cpp') diff --git a/src/lex.cpp b/src/lex.cpp new file mode 100644 index 0000000..81dbe19 --- /dev/null +++ b/src/lex.cpp @@ -0,0 +1,95 @@ +/* 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 . + */ + +/** @file + + * @brief Lexing (build a SExp from a string) + */ + +#include +#include "tuplr.hpp" + +using namespace std; + +inline int +readChar(Cursor& cur, istream& in) +{ + int ch = in.get(); + switch (ch) { + case '\n': ++cur.line; cur.col = 0; break; + default: ++cur.col; + } + return ch; +} + +SExp +readExpression(Cursor& cur, istream& in) +{ +#define PUSH(s, t) { if (t != "") { s.top().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 (int c = readChar(cur, in)) { + switch (c) { + case EOF: + THROW_IF(!stk.empty(), cur, "unexpected end of file") + return SExp(cur); + case ';': + while ((c = readChar(cur, in)) != '\n') {} + case '\n': case ' ': case '\t': + if (tok != "") YIELD(stk, tok); + break; + case '"': + loc = cur; + do { tok.push_back(c); } while ((c = readChar(cur, in)) != '"'); + YIELD(stk, tok + '"'); + break; + case '(': + stk.push(SExp(cur)); + break; + case ')': + switch (stk.size()) { + case 0: + throw Error(cur, "unexpected `)'"); + case 1: + PUSH(stk, tok); + return stk.top(); + default: + PUSH(stk, tok); + SExp l = stk.top(); + stk.pop(); + stk.top().push_back(l); + } + break; + case '#': + if (in.peek() == '|') { + while (!(readChar(cur, in) == '|' && readChar(cur, in) == '#')) {} + break; + } + default: + if (tok == "") loc = cur; + tok += c; + } + } + switch (stk.size()) { + case 0: return SExp(loc, tok); + case 1: return stk.top(); + default: throw Error(cur, "missing `)'"); + } + return SExp(cur); +} -- cgit v1.2.1