| ... | @@ -170,6 +170,13 @@ static AstNode *create_char_lit_node(Context *c, uint8_t value) { | ... | @@ -170,6 +170,13 @@ static AstNode *create_char_lit_node(Context *c, uint8_t value) { |
| 170 | return node; | 170 | return node; |
| 171 | } | 171 | } |
| 172 | | 172 | |
| | 173 | static AstNode *create_str_lit_node(Context *c, Buf *buf) { |
| | 174 | AstNode *node = create_node(c, NodeTypeStringLiteral); |
| | 175 | buf_init_from_buf(&node->data.string_literal.buf, buf); |
| | 176 | node->data.string_literal.c = true; |
| | 177 | return node; |
| | 178 | } |
| | 179 | |
| 173 | static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { | 180 | static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { |
| 174 | AstNode *node = create_node(c, NodeTypeNumberLiteral); | 181 | AstNode *node = create_node(c, NodeTypeNumberLiteral); |
| 175 | node->data.number_literal.kind = NumLitUInt; | 182 | node->data.number_literal.kind = NumLitUInt; |
| ... | @@ -1255,6 +1262,97 @@ static bool is_simple_symbol(Buf *buf) { | ... | @@ -1255,6 +1262,97 @@ static bool is_simple_symbol(Buf *buf) { |
| 1255 | return true; | 1262 | return true; |
| 1256 | } | 1263 | } |
| 1257 | | 1264 | |
| | 1265 | enum ParseCStrState { |
| | 1266 | ParseCStrStateExpectQuot, |
| | 1267 | ParseCStrStateNormal, |
| | 1268 | ParseCStrStateEscape, |
| | 1269 | }; |
| | 1270 | |
| | 1271 | static int parse_c_str_lit(Buf *buf, Buf *out_str) { |
| | 1272 | ParseCStrState state = ParseCStrStateExpectQuot; |
| | 1273 | buf_resize(out_str, 0); |
| | 1274 | |
| | 1275 | for (int i = 0; i < buf_len(buf); i += 1) { |
| | 1276 | uint8_t c = buf_ptr(buf)[i]; |
| | 1277 | switch (state) { |
| | 1278 | case ParseCStrStateExpectQuot: |
| | 1279 | if (c == '"') { |
| | 1280 | state = ParseCStrStateNormal; |
| | 1281 | } else { |
| | 1282 | return -1; |
| | 1283 | } |
| | 1284 | break; |
| | 1285 | case ParseCStrStateNormal: |
| | 1286 | switch (c) { |
| | 1287 | case '\\': |
| | 1288 | state = ParseCStrStateEscape; |
| | 1289 | break; |
| | 1290 | case '\n': |
| | 1291 | return -1; |
| | 1292 | case '"': |
| | 1293 | return 0; |
| | 1294 | default: |
| | 1295 | buf_append_char(out_str, c); |
| | 1296 | } |
| | 1297 | break; |
| | 1298 | case ParseCStrStateEscape: |
| | 1299 | switch (c) { |
| | 1300 | case '\'': |
| | 1301 | buf_append_char(out_str, '\''); |
| | 1302 | state = ParseCStrStateNormal; |
| | 1303 | break; |
| | 1304 | case '"': |
| | 1305 | buf_append_char(out_str, '"'); |
| | 1306 | state = ParseCStrStateNormal; |
| | 1307 | break; |
| | 1308 | case '?': |
| | 1309 | buf_append_char(out_str, '\?'); |
| | 1310 | state = ParseCStrStateNormal; |
| | 1311 | break; |
| | 1312 | case '\\': |
| | 1313 | buf_append_char(out_str, '\\'); |
| | 1314 | state = ParseCStrStateNormal; |
| | 1315 | break; |
| | 1316 | case 'a': |
| | 1317 | buf_append_char(out_str, '\a'); |
| | 1318 | state = ParseCStrStateNormal; |
| | 1319 | break; |
| | 1320 | case 'b': |
| | 1321 | buf_append_char(out_str, '\b'); |
| | 1322 | state = ParseCStrStateNormal; |
| | 1323 | break; |
| | 1324 | case 'f': |
| | 1325 | buf_append_char(out_str, '\f'); |
| | 1326 | state = ParseCStrStateNormal; |
| | 1327 | break; |
| | 1328 | case 'n': |
| | 1329 | buf_append_char(out_str, '\n'); |
| | 1330 | state = ParseCStrStateNormal; |
| | 1331 | break; |
| | 1332 | case 'r': |
| | 1333 | buf_append_char(out_str, '\r'); |
| | 1334 | state = ParseCStrStateNormal; |
| | 1335 | break; |
| | 1336 | case 't': |
| | 1337 | buf_append_char(out_str, '\t'); |
| | 1338 | state = ParseCStrStateNormal; |
| | 1339 | break; |
| | 1340 | case 'v': |
| | 1341 | buf_append_char(out_str, '\v'); |
| | 1342 | state = ParseCStrStateNormal; |
| | 1343 | break; |
| | 1344 | default: |
| | 1345 | // TODO octal escape sequence, hexadecimal escape sequence, and |
| | 1346 | // universal character name |
| | 1347 | return -1; |
| | 1348 | } |
| | 1349 | break; |
| | 1350 | } |
| | 1351 | } |
| | 1352 | |
| | 1353 | return -1; |
| | 1354 | } |
| | 1355 | |
| 1258 | static void process_macro(Context *c, Buf *name, Buf *value) { | 1356 | static void process_macro(Context *c, Buf *name, Buf *value) { |
| 1259 | //fprintf(stderr, "macro '%s' = '%s'\n", buf_ptr(name), buf_ptr(value)); | 1357 | //fprintf(stderr, "macro '%s' = '%s'\n", buf_ptr(name), buf_ptr(value)); |
| 1260 | if (is_zig_keyword(name)) { | 1358 | if (is_zig_keyword(name)) { |
| ... | @@ -1269,7 +1367,12 @@ static void process_macro(Context *c, Buf *name, Buf *value) { | ... | @@ -1269,7 +1367,12 @@ static void process_macro(Context *c, Buf *name, Buf *value) { |
| 1269 | return; | 1367 | return; |
| 1270 | } | 1368 | } |
| 1271 | // maybe it's a string literal | 1369 | // maybe it's a string literal |
| 1272 | // TODO | 1370 | Buf str_lit = BUF_INIT; |
| | 1371 | if (!parse_c_str_lit(value, &str_lit)) { |
| | 1372 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_str_lit_node(c, &str_lit)); |
| | 1373 | c->macro_table.put(name, var_node); |
| | 1374 | return; |
| | 1375 | } |
| 1273 | | 1376 | |
| 1274 | // maybe it's an unsigned integer | 1377 | // maybe it's an unsigned integer |
| 1275 | uint64_t uint; | 1378 | uint64_t uint; |