From 7d2348ece9b72cecd4d5417a4e39ee705c349e0a Mon Sep 17 00:00:00 2001 From: Ákos Kőrösi Date: Thu, 21 May 2026 19:11:09 +0200 Subject: start building for dollar expansions --- src/lexparse.c | 26 ++++++++++++++++++++++++++ src/main.c | 4 +++- src/preproc.c | 53 +++++++++++++++++++++++++++++++++-------------------- src/stages.h | 3 ++- src/syntax.h | 2 ++ 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/lexparse.c b/src/lexparse.c index 3d48cfe..4ef228c 100644 --- a/src/lexparse.c +++ b/src/lexparse.c @@ -1,4 +1,5 @@ #include +#include #include "syntax.h" #include "../src/utils.h" @@ -38,6 +39,31 @@ MaybeToken consolidate_buffer(LexingBuffer* buf) { } +static MaybeChunk handle_dollar_expansion(char* line, size_t* pos, QuotationMode qmode) { + (*pos)++; + + if (line[*pos] == '(') { + // TODO + exit(66); + } else if (line[*pos] == '_' || isalnum(line[*pos])){ + String buf = make_String(256); + while (line[*pos] == '_' || isalnum(line[*pos])) { + push_to_String(&buf, line[(*pos)++]); + } + return (MaybeChunk){ + .some = true, + .value = (Chunk){ + .qmode = qmode, + .kind = CHUNK_VAR, + .as.varname = inner(&buf) + } + }; + } else { + return (MaybeChunk){.some = false}; + } +} + + static Chunk collect_un_q_literal(char* line, size_t* pos) { String buf = make_String(256); size_t i; diff --git a/src/main.c b/src/main.c index dc451f9..1f9198b 100644 --- a/src/main.c +++ b/src/main.c @@ -6,9 +6,11 @@ #include "syntax.h" #include "stages.h" +#include "utils.h" int main() { + ShellState shstate = {.shell_vars = make_KeyValMap(256), .aliases = make_KeyValMap(256)}; char* line; while (1) { line = readline("$ "); @@ -16,7 +18,7 @@ int main() { if (strcmp(line, "exit") == 0) exit(0); add_history(line); Ast ast = lex(line); - PipelineTree pltree = process_ast(ast); + PipelineTree pltree = process_ast(ast, &shstate); execute_pipeline_tree(pltree); } free(line); diff --git a/src/preproc.c b/src/preproc.c index d64f4c3..6aa7748 100644 --- a/src/preproc.c +++ b/src/preproc.c @@ -1,6 +1,7 @@ #include #include #include "syntax.h" +#include "utils.h" void split_str_on_space(char* str, StrVec* result) { String buf = make_String(256); @@ -19,23 +20,34 @@ void split_str_on_space(char* str, StrVec* result) { } } -StrVec process_word(Word word) { + +void process_chunk(Chunk chunk, StrVec* result, ShellState* shstate) { + assert(!(chunk.qmode == SINGLE_Q && chunk.kind != CHUNK_LIT)); + + char* chunk_val; + switch (chunk.kind) { + case CHUNK_LIT: + chunk_val = chunk.as.lit_str; + break; + case CHUNK_VAR: + chunk_val = get_var(chunk.as.varname, shstate); + break; + default: + exit(77); + } + + if (chunk.qmode == UN_Q) { + split_str_on_space(chunk_val, result); + } else { + push_to_StrVec(result, chunk_val); + } +} + +StrVec process_word(Word word, ShellState* shstate) { StrVec result = make_StrVec(256); for (int i = 0; i < word.count; i++) { Chunk chunk = *get_from_Word(&word, i); - switch (chunk.qmode) { - case SINGLE_Q: - push_to_StrVec(&result, chunk.as.lit_str); - break; - case DOUBLE_Q: - // TODO - exit(67); - break; - case UN_Q: - // TODO: this only does literals, implement the rest - split_str_on_space(chunk.as.lit_str, &result); - break; - } + process_chunk(chunk, &result, shstate); } return result; } @@ -51,7 +63,8 @@ typedef struct { DECLARE_VEC(ExpandedToken, ExpandedTokenVec) -Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) { + +Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool, ShellState* shstate) { ExpandedTokenVec exp_tokens = make_ExpandedTokenVec(256); @@ -63,7 +76,7 @@ Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) { push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_SPEC, .as.spec = tok.as.spec}); break; case TOK_WORD: - strs = process_word(tok.as.word); + strs = process_word(tok.as.word, shstate); for (int n = 0; n < strs.count; n++) { push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_WORD, .as.word = *get_from_StrVec(&strs, n)}); } @@ -120,11 +133,11 @@ Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) { } break; case SPEC_SUB_IN: - sub_pl = process_token_sequence(*(TokenVec*)curr_tok.as.spec.as.proc_sub_region, pl_pool); + sub_pl = process_token_sequence(*(TokenVec*)curr_tok.as.spec.as.proc_sub_region, pl_pool, shstate); push_to_ArgVec(&curr_cmd.args, (Arg){.kind = ARG_PS_IN, .as.sub_pipeline = sub_pl}); break; case SPEC_SUB_OUT: - sub_pl = process_token_sequence(*(TokenVec*)curr_tok.as.spec.as.proc_sub_region, pl_pool); + sub_pl = process_token_sequence(*(TokenVec*)curr_tok.as.spec.as.proc_sub_region, pl_pool, shstate); push_to_ArgVec(&curr_cmd.args, (Arg){.kind = ARG_PS_OUT, .as.sub_pipeline = sub_pl}); break; } @@ -134,8 +147,8 @@ Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) { } -PipelineTree process_ast(Ast ast) { +PipelineTree process_ast(Ast ast, ShellState* shstate) { PipelineVec pls = make_PipelineVec(256); - Pipeline* root_pl = process_token_sequence(*ast.root, &pls); + Pipeline* root_pl = process_token_sequence(*ast.root, &pls, shstate); return (PipelineTree){.pl_pool = pls, root_pl}; } diff --git a/src/stages.h b/src/stages.h index 4faaf14..f009c78 100644 --- a/src/stages.h +++ b/src/stages.h @@ -1,7 +1,8 @@ #pragma once #include "syntax.h" +#include "utils.h" Ast lex(char* input); -PipelineTree process_ast(Ast ast); +PipelineTree process_ast(Ast ast, ShellState* shstate); void execute_pipeline_tree(PipelineTree pltree); diff --git a/src/syntax.h b/src/syntax.h index a0ccfac..12293ae 100644 --- a/src/syntax.h +++ b/src/syntax.h @@ -63,6 +63,8 @@ typedef struct { } as; } Chunk; +DECLARE_MAYBE(Chunk, MaybeChunk) + DECLARE_VEC(Chunk, Word) -- cgit v1.2.3