aboutsummaryrefslogtreecommitdiffstats
path: root/src/lex.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-06-29 00:28:50 +0000
committerDavid Robillard <d@drobilla.net>2009-06-29 00:28:50 +0000
commit314482b95ff83f1f88e41d45fadd05a7e625bb0c (patch)
tree56da1ec61b8f98746a7e27e045959cf9c91ad084 /src/lex.cpp
parentf3ef0b25195098389bc7aea1e75d98e62b91b1e2 (diff)
downloadresp-314482b95ff83f1f88e41d45fadd05a7e625bb0c.tar.gz
resp-314482b95ff83f1f88e41d45fadd05a7e625bb0c.tar.bz2
resp-314482b95ff83f1f88e41d45fadd05a7e625bb0c.zip
Split code up further.
git-svn-id: http://svn.drobilla.net/resp/tuplr@165 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/lex.cpp')
-rw-r--r--src/lex.cpp95
1 files changed, 95 insertions, 0 deletions
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 <dave@drobilla.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+
+ * @brief Lexing (build a SExp from a string)
+ */
+
+#include <stack>
+#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<SExp> 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);
+}