aboutsummaryrefslogtreecommitdiff
path: root/src/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.c')
-rw-r--r--src/parse.c148
1 files changed, 76 insertions, 72 deletions
diff --git a/src/parse.c b/src/parse.c
index 3b8f55bf..c31bea64 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -61,8 +61,8 @@ int op_tightness[] = {
};
static const char *keywords[] = {
- "_max_", "_min_", "and", "break", "continue", "defer", "deserialize", "do", "else", "enum",
- "extend", "extern", "for", "func", "if", "in", "inline", "lang", "mod", "mod1", "no", "none",
+ "C_code", "_max_", "_min_", "and", "break", "continue", "defer", "deserialize", "do", "else", "enum",
+ "extend", "extern", "for", "func", "if", "in", "lang", "mod", "mod1", "no", "none",
"not", "or", "pass", "return", "skip", "skip", "stop", "struct", "then", "unless", "use", "when",
"while", "xor", "yes",
};
@@ -147,6 +147,7 @@ static PARSER(parse_var);
static PARSER(parse_when);
static PARSER(parse_while);
static PARSER(parse_deserialize);
+static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos, char open_quote, char close_quote, char open_interp);
//
// Print a parse error and exit (or use the on_err longjmp)
@@ -1186,55 +1187,11 @@ PARSER(parse_bool) {
return NULL;
}
-PARSER(parse_text) {
- // ('"' ... '"' / "'" ... "'" / "`" ... "`")
- // "$" [name] [interp-char] quote-char ... close-quote
- const char *start = pos;
- const char *lang = NULL;
-
- // Escape sequence, e.g. \r\n
- if (*pos == '\\') {
- CORD cord = CORD_EMPTY;
- do {
- const char *c = unescape(ctx, &pos);
- cord = CORD_cat(cord, c);
- // cord = CORD_cat_char(cord, c);
- } while (*pos == '\\');
- return NewAST(ctx->file, start, pos, TextLiteral, .cord=cord);
- }
-
- char open_quote, close_quote, open_interp = '$';
- if (match(&pos, "\"")) { // Double quote
- open_quote = '"', close_quote = '"', open_interp = '$';
- } else if (match(&pos, "`")) { // Backtick
- open_quote = '`', close_quote = '`', open_interp = '$';
- } else if (match(&pos, "'")) { // Single quote
- open_quote = '\'', close_quote = '\'', open_interp = '\x03';
- } else if (match(&pos, "$")) { // Customized strings
- lang = get_id(&pos);
- // $"..." or $@"...."
- static const char *interp_chars = "~!@#$%^&*+=\\?";
- if (match(&pos, "$")) { // Disable interpolation with $
- open_interp = '\x03';
- } else if (strchr(interp_chars, *pos)) {
- open_interp = *pos;
- ++pos;
- } else if (*pos == '(') {
- open_interp = '@'; // For shell commands
- }
- static const char *quote_chars = "\"'`|/;([{<";
- if (!strchr(quote_chars, *pos))
- parser_err(ctx, pos, pos+1, "This is not a valid string quotation character. Valid characters are: \"'`|/;([{<");
- open_quote = *pos;
- ++pos;
- close_quote = closing[(int)open_quote] ? closing[(int)open_quote] : open_quote;
- } else {
- return NULL;
- }
-
+ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos, char open_quote, char close_quote, char open_interp)
+{
+ const char *pos = *out_pos;
int64_t starting_indent = get_indent(ctx, pos);
int64_t string_indent = starting_indent + SPACES_PER_INDENT;
-
ast_list_t *chunks = NULL;
CORD chunk = CORD_EMPTY;
const char *chunk_start = pos;
@@ -1299,6 +1256,57 @@ PARSER(parse_text) {
REVERSE_LIST(chunks);
char close_str[2] = {close_quote, 0};
expect_closing(ctx, &pos, close_str, "I was expecting a ", close_quote, " to finish this string");
+ *out_pos = pos;
+ return chunks;
+}
+
+PARSER(parse_text) {
+ // ('"' ... '"' / "'" ... "'" / "`" ... "`")
+ // "$" [name] [interp-char] quote-char ... close-quote
+ const char *start = pos;
+ const char *lang = NULL;
+
+ // Escape sequence, e.g. \r\n
+ if (*pos == '\\') {
+ CORD cord = CORD_EMPTY;
+ do {
+ const char *c = unescape(ctx, &pos);
+ cord = CORD_cat(cord, c);
+ // cord = CORD_cat_char(cord, c);
+ } while (*pos == '\\');
+ return NewAST(ctx->file, start, pos, TextLiteral, .cord=cord);
+ }
+
+ char open_quote, close_quote, open_interp = '$';
+ if (match(&pos, "\"")) { // Double quote
+ open_quote = '"', close_quote = '"', open_interp = '$';
+ } else if (match(&pos, "`")) { // Backtick
+ open_quote = '`', close_quote = '`', open_interp = '$';
+ } else if (match(&pos, "'")) { // Single quote
+ open_quote = '\'', close_quote = '\'', open_interp = '\x03';
+ } else if (match(&pos, "$")) { // Customized strings
+ lang = get_id(&pos);
+ // $"..." or $@"...."
+ static const char *interp_chars = "~!@#$%^&*+=\\?";
+ if (match(&pos, "$")) { // Disable interpolation with $
+ open_interp = '\x03';
+ } else if (strchr(interp_chars, *pos)) {
+ open_interp = *pos;
+ ++pos;
+ } else if (*pos == '(') {
+ open_interp = '@'; // For shell commands
+ }
+ static const char *quote_chars = "\"'`|/;([{<";
+ if (!strchr(quote_chars, *pos))
+ parser_err(ctx, pos, pos+1, "This is not a valid string quotation character. Valid characters are: \"'`|/;([{<");
+ open_quote = *pos;
+ ++pos;
+ close_quote = closing[(int)open_quote] ? closing[(int)open_quote] : open_quote;
+ } else {
+ return NULL;
+ }
+
+ ast_list_t *chunks = _parse_text_helper(ctx, &pos, open_quote, close_quote, open_interp);
return NewAST(ctx->file, start, pos, TextJoin, .lang=lang, .children=chunks);
}
@@ -2258,34 +2266,30 @@ PARSER(parse_extern) {
PARSER(parse_inline_c) {
const char *start = pos;
- if (!match_word(&pos, "inline")) return NULL;
-
- spaces(&pos);
- if (!match_word(&pos, "C")) return NULL;
+ if (!match_word(&pos, "C_code")) return NULL;
spaces(&pos);
type_ast_t *type = NULL;
- if (match(&pos, ":"))
- type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this inline C code");
-
- spaces(&pos);
- if (!match(&pos, "{"))
- parser_err(ctx, start, pos, "I expected a '{' here");
-
- int depth = 1;
- const char *c_code_start = pos;
- for (; *pos && depth > 0; ++pos) {
- if (*pos == '}') --depth;
- else if (*pos == '{') ++depth;
+ ast_list_t *chunks;
+ if (match(&pos, ":")) {
+ type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this C_code code");
+ spaces(&pos);
+ if (!match(&pos, "("))
+ parser_err(ctx, start, pos, "I expected a '(' here");
+ chunks = new(ast_list_t, .ast=NewAST(ctx->file, pos, pos, TextLiteral, "({"),
+ .next=_parse_text_helper(ctx, &pos, '(', ')', '@'));
+ if (type) {
+ REVERSE_LIST(chunks);
+ chunks = new(ast_list_t, .ast=NewAST(ctx->file, pos, pos, TextLiteral, "; })"), .next=chunks);
+ REVERSE_LIST(chunks);
+ }
+ } else {
+ if (!match(&pos, "{"))
+ parser_err(ctx, start, pos, "I expected a '{' here");
+ chunks = _parse_text_helper(ctx, &pos, '{', '}', '@');
}
- if (depth != 0)
- parser_err(ctx, start, start+1, "I couldn't find the closing '}' for this inline C code");
-
- CORD c_code = GC_strndup(c_code_start, (size_t)((pos-1) - c_code_start));
- if (type)
- c_code = CORD_all("({ ", c_code, "; })");
- return NewAST(ctx->file, start, pos, InlineCCode, .code=c_code, .type_ast=type);
+ return NewAST(ctx->file, start, pos, InlineCCode, .chunks=chunks, .type_ast=type);
}
PARSER(parse_doctest) {