diff options
Diffstat (limited to 'src/lex.cpp')
-rw-r--r-- | src/lex.cpp | 84 |
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); |