summaryrefslogtreecommitdiffstats
path: root/src/lex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lex.cpp')
-rw-r--r--src/lex.cpp84
1 files changed, 82 insertions, 2 deletions
diff --git a/src/lex.cpp b/src/lex.cpp
index 7a3fb6a..70362a7 100644
--- a/src/lex.cpp
+++ b/src/lex.cpp
@@ -243,6 +243,85 @@ int lex_t::lex_keyword(parser_value_t *value) {
return ret->token;
}
+int lex_t::unterminated_block(parser_value_t *value) {
+ if (ferror(file))
+ return io_error(value);
+
+ value->error = "unterminated code block";
+ return -1;
+}
+
+int lex_t::lex_block(parser_value_t *value) {
+ size_t parens = 0;
+ bool line_comment = false;
+ bool block_comment = false;
+ bool str = false;
+
+ size_t pos = 0;
+ size_t len = 1024;
+ char *buf = static_cast<char*>(std::malloc(len));
+
+ char prev = 0;
+
+ while (true) {
+ if (!next(true)) {
+ std::free(buf);
+ return unterminated_block(value);
+ }
+
+ char cur = current();
+
+ if (line_comment) {
+ if (cur == '\n' || cur == '\r')
+ line_comment = false;
+ }
+ else if (block_comment) {
+ if (prev == '*' && cur == '/')
+ block_comment = false;
+ }
+ else if (str) {
+ if (prev != '\\' && cur == '"')
+ str = false;
+ }
+ else {
+ if (cur == '{') {
+ parens++;
+ }
+ else if (cur == '}') {
+ if (!parens)
+ break;
+
+ parens--;
+ }
+ else if (cur == '"') {
+ str = true;
+ }
+ else if (prev == '/' && cur == '/') {
+ line_comment = true;
+ }
+ else if (prev == '/' && cur == '*') {
+ block_comment = true;
+ }
+ }
+
+ if (pos >= len) {
+ len *= 2;
+ buf = static_cast<char*>(std::realloc(buf, len));
+ }
+
+ buf[pos++] = cur;
+ prev = cur;
+ }
+
+ value->str = strndup(buf, pos);
+ std::free(buf);
+
+ next(true);
+ consume(true);
+
+ return TOK_BLOCK;
+}
+
int lex_t::lex_symbol(parser_value_t *value, bool terminal) {
if (needspace)
return syntax_error(value);
@@ -293,8 +372,6 @@ int lex_t::lex(parser_value_t *value) {
case ';':
case ':':
- case '{':
- case '}':
case '|':
case '=':
token = current();
@@ -341,6 +418,9 @@ int lex_t::lex(parser_value_t *value) {
return TOK_CHAR;
+ case '{':
+ return lex_block(value);
+
//case '"':
//return lex_string(value);