aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-04-22 15:24:18 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-04-22 15:24:18 -0700
commit8187396f640d2a56e0d56c7d199074b4590e49eb (patch)
tree5dbbeeba42680a30c43ccd1d1be3be89925d73d3 /src/parser.cpp
parent35362f8137b2c5109e6bc39cb12048c016b5b580 (diff)
downloadzig-8187396f640d2a56e0d56c7d199074b4590e49eb.tar.gz
zig-8187396f640d2a56e0d56c7d199074b4590e49eb.zip
add syntax to allow symbols to have arbitrary strings as names
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp175
1 files changed, 97 insertions, 78 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 29a65521d7..d73bacead2 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -87,10 +87,6 @@ static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
return node;
}
-static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) {
- buf_init_from_mem(buf, buf_ptr(pc->buf) + token->start_pos, token->end_pos - token->start_pos);
-}
-
static void parse_asm_template(ParseContext *pc, AstNode *node) {
Buf *asm_template = &node->data.asm_expr.asm_template;
@@ -277,6 +273,8 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool
// detect c string literal
enum State {
+ StatePre,
+ StateSkipQuot,
StateStart,
StateEscape,
StateHex1,
@@ -285,90 +283,100 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool
buf_resize(buf, 0);
- State state = StateStart;
- bool skip_quote;
+ State state = StatePre;
SrcPos pos = {token->start_line, token->start_column};
int hex_value = 0;
for (int i = token->start_pos; i < token->end_pos - 1; i += 1) {
uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i);
- if (i == token->start_pos) {
- skip_quote = (c == 'c');
- if (out_c_str) {
- *out_c_str = skip_quote;
- } else if (skip_quote) {
- ast_error(pc, token, "C string literal not allowed here");
- }
- } else if (skip_quote) {
- skip_quote = false;
- } else {
- switch (state) {
- case StateStart:
- if (c == '\\') {
- state = StateEscape;
- } else {
- buf_append_char(buf, c);
- if (offset_map) offset_map->append(pos);
- }
- break;
- case StateEscape:
- switch (c) {
- case '\\':
- buf_append_char(buf, '\\');
- if (offset_map) offset_map->append(pos);
- state = StateStart;
- break;
- case 'r':
- buf_append_char(buf, '\r');
- if (offset_map) offset_map->append(pos);
- state = StateStart;
- break;
- case 'n':
- buf_append_char(buf, '\n');
- if (offset_map) offset_map->append(pos);
- state = StateStart;
- break;
- case 't':
- buf_append_char(buf, '\t');
- if (offset_map) offset_map->append(pos);
- state = StateStart;
- break;
- case '"':
- buf_append_char(buf, '"');
- if (offset_map) offset_map->append(pos);
- state = StateStart;
- break;
- case 'x':
- state = StateHex1;
- break;
- default:
- ast_error(pc, token, "invalid escape character");
- break;
- }
- break;
- case StateHex1:
- {
- int hex_digit = get_hex_digit(c);
- if (hex_digit == -1) {
- ast_error(pc, token, "invalid hex digit: '%c'", c);
- }
- hex_value = hex_digit * 16;
- state = StateHex2;
+ switch (state) {
+ case StatePre:
+ switch (c) {
+ case '@':
+ state = StateSkipQuot;
break;
- }
- case StateHex2:
- {
- int hex_digit = get_hex_digit(c);
- if (hex_digit == -1) {
- ast_error(pc, token, "invalid hex digit: '%c'", c);
+ case 'c':
+ if (out_c_str) {
+ *out_c_str = true;
+ } else {
+ ast_error(pc, token, "C string literal not allowed here");
}
- hex_value += hex_digit;
- assert(hex_value >= 0 && hex_value <= 255);
- buf_append_char(buf, hex_value);
+ state = StateSkipQuot;
+ break;
+ case '"':
state = StateStart;
break;
+ default:
+ ast_error(pc, token, "invalid string character");
+ }
+ break;
+ case StateSkipQuot:
+ state = StateStart;
+ break;
+ case StateStart:
+ if (c == '\\') {
+ state = StateEscape;
+ } else {
+ buf_append_char(buf, c);
+ if (offset_map) offset_map->append(pos);
+ }
+ break;
+ case StateEscape:
+ switch (c) {
+ case '\\':
+ buf_append_char(buf, '\\');
+ if (offset_map) offset_map->append(pos);
+ state = StateStart;
+ break;
+ case 'r':
+ buf_append_char(buf, '\r');
+ if (offset_map) offset_map->append(pos);
+ state = StateStart;
+ break;
+ case 'n':
+ buf_append_char(buf, '\n');
+ if (offset_map) offset_map->append(pos);
+ state = StateStart;
+ break;
+ case 't':
+ buf_append_char(buf, '\t');
+ if (offset_map) offset_map->append(pos);
+ state = StateStart;
+ break;
+ case '"':
+ buf_append_char(buf, '"');
+ if (offset_map) offset_map->append(pos);
+ state = StateStart;
+ break;
+ case 'x':
+ state = StateHex1;
+ break;
+ default:
+ ast_error(pc, token, "invalid escape character");
+ }
+ break;
+ case StateHex1:
+ {
+ int hex_digit = get_hex_digit(c);
+ if (hex_digit == -1) {
+ ast_error(pc, token, "invalid hex digit: '%c'", c);
}
- }
+ hex_value = hex_digit * 16;
+ state = StateHex2;
+ break;
+ }
+ case StateHex2:
+ {
+ int hex_digit = get_hex_digit(c);
+ if (hex_digit == -1) {
+ ast_error(pc, token, "invalid hex digit: '%c'", c);
+ }
+ hex_value += hex_digit;
+ assert(hex_value >= 0 && hex_value <= 255);
+ buf_append_char(buf, hex_value);
+ state = StateStart;
+ break;
+ }
}
if (c == '\n') {
pos.line += 1;
@@ -381,6 +389,17 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool
if (offset_map) offset_map->append(pos);
}
+static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) {
+ uint8_t *first_char = (uint8_t *)buf_ptr(pc->buf) + token->start_pos;
+ bool at_sign = *first_char == '@';
+ if (at_sign) {
+ parse_string_literal(pc, token, buf, nullptr, nullptr);
+ } else {
+ buf_init_from_mem(buf, buf_ptr(pc->buf) + token->start_pos, token->end_pos - token->start_pos);
+ }
+}
+
+
static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix,
int skip_index, bool *overflow)
{