aboutsummaryrefslogtreecommitdiffstats
path: root/src/lex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lex.cpp')
-rw-r--r--src/lex.cpp32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/lex.cpp b/src/lex.cpp
index 0097346..f633b00 100644
--- a/src/lex.cpp
+++ b/src/lex.cpp
@@ -16,7 +16,8 @@
*/
/** @file
- * @brief Lexing (build an unparsed textual AST from a string)
+ * @brief Lexing (build a CST from a string).
+ * A CST is a lexeme, or a tuple of CST's.
*/
#include <stdio.h>
@@ -40,8 +41,8 @@ readChar(Cursor& cur, istream& in)
AST*
readExpression(Cursor& cur, istream& in)
{
-#define PUSH(s, t) { if (t != "") { s.top()->push_back(new AString(loc, t)); t = ""; } }
-#define YIELD(s, t) { if (s.empty()) { return new AString(loc, t); } else PUSH(s, t) }
+#define PUSH(s, t) { if (t != "") { s.top()->push_back(new ALexeme(loc, t)); t = ""; } }
+#define YIELD(s, t) { if (s.empty()) { return new ALexeme(loc, t); } else PUSH(s, t) }
stack<ATuple*> stk;
string tok;
Cursor loc; // start of tok
@@ -52,13 +53,31 @@ readExpression(Cursor& cur, istream& in)
return new ATuple(cur);
case ';':
while ((c = readChar(cur, in)) != '\n') {}
- case '\n': case ' ': case '\t':
+ case '\n': case ' ': case '\t': case '\r': case '\f':
if (tok != "") YIELD(stk, tok);
break;
case '"':
loc = cur;
- do { tok.push_back(c); } while ((c = readChar(cur, in)) != '"');
- YIELD(stk, tok + '"');
+ tok.push_back(c); // leading quote
+ while ((c = readChar(cur, in)) != '"') {
+ if (c == '\\') { // string escape
+ switch (c = readChar(cur, in)) {
+ case '"':
+ tok.push_back('"');
+ break;
+ case '\\':
+ tok.push_back('\\');
+ break;
+ default:
+ cin.putback(c);
+ throw Error(cur, string("unknown string escape `\\") + (char)c + "'");
+ }
+ } else { // any other character
+ tok.push_back(c);
+ }
+ }
+ tok.push_back(c); // trailing quote
+ YIELD(stk, tok);
break;
case '(':
stk.push(new ATuple(cur));
@@ -66,6 +85,7 @@ readExpression(Cursor& cur, istream& in)
case ')':
switch (stk.size()) {
case 0:
+ cin.putback(c);
throw Error(cur, "unexpected `)'");
case 1:
PUSH(stk, tok);