frontend: Add parsing of shell blocks

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-03-21 17:15:24 -04:00
parent c717e80636
commit 7c0f40abbf
4 changed files with 70 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
.cc clang
.ld lld-link
# Shell block
CFLAGS ::
-Iinclude/
-mgeneral-regs-only

View File

@@ -21,6 +21,8 @@
#include "common/ptrbox.h"
#include "common/trace.h"
#define SHELL_BLOCK_TERMINATE '~'
/*
* Test if a given character counts as a whitespace character
*
@@ -247,6 +249,69 @@ lexer_scan_directive(struct quip_state *state, struct token *tokres)
return -1;
}
/*
* Scan a shell block
*
* @state: Quip state
* @tokres: Token result is written here
*
* Returns zero on success
*/
static int
lexer_scan_shellblock(struct quip_state *state, struct token *tokres)
{
char c, *buf;
size_t bufsz, bufcap;
bool is_leading = true;
bufsz = 0;
bufcap = 8;
if ((buf = malloc(bufcap)) == NULL) {
return -1;
}
for (;;) {
if ((c = lexer_consume(state, false)) == '\0') {
trace_error(state, "unexpected end of file within shellblock\n");
free(buf);
return -1;
}
/* Handle overflow if needed */
if (bufsz > bufcap - 1) {
bufcap += 8;
buf = realloc(buf, bufcap);
}
/* Handle newlines */
if (c == '\n') {
buf[bufsz++] = ' ';
is_leading = true;
continue;
}
if (c == SHELL_BLOCK_TERMINATE) {
buf[bufsz] = '\0';
break;
}
if (is_leading && lexer_is_ws(c)) {
continue;
}
is_leading = false;
buf[bufsz++] = c;
if (buf == NULL) {
return -1;
}
}
tokres->type = TT_SHELLBLOCK;
tokres->s = ptrbox_strdup(&state->ptrbox, buf);
free(buf);
return 0;
}
int
lexer_scan(struct quip_state *state, struct token *tokres)
{
@@ -274,17 +339,12 @@ lexer_scan(struct quip_state *state, struct token *tokres)
case ':':
tokres->c = c;
if ((c = lexer_consume(state, false)) == ':') {
tokres->type = TT_COLONDUB;
return 0;
return lexer_scan_shellblock(state, tokres);
}
lexer_putback(state, c);
tokres->type = TT_COLON;
return 0;
case '~':
tokres->type = TT_TILDE;
tokres->c = c;
return 0;
default:
if (lexer_scan_name(state, c, tokres) == 0) {
return 0;

View File

@@ -37,11 +37,10 @@ static const char *toktab[] = {
[TT_NONE] = symtok("none"),
[TT_NAME] = symtok("name"),
[TT_NEWLINE] = symtok("newline"),
[TT_SHELLBLOCK] = symtok("shellblock"),
[TT_CC] = qtok(".cc"),
[TT_LD] = qtok(".ld"),
[TT_COLON] = qtok(":"),
[TT_TILDE] = qtok("~"),
[TT_COLONDUB] = qtok("::")
[TT_COLON] = qtok(":")
};
int

View File

@@ -18,11 +18,10 @@ typedef enum {
TT_NONE, /* [none] */
TT_NAME, /* [name] */
TT_NEWLINE, /* [newline] */
TT_SHELLBLOCK, /* [shellblock] */
TT_CC, /* '.cc' */
TT_LD, /* '.ld' */
TT_COLON, /* ':' */
TT_TILDE, /* '~' */
TT_COLONDUB, /* '::' */
} tt_t;
/*