summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lex.c42
-rw-r--r--lex.h16
-rw-r--r--parse.c45
3 files changed, 68 insertions, 35 deletions
diff --git a/lex.c b/lex.c
index edcfd0b..9e29420 100644
--- a/lex.c
+++ b/lex.c
@@ -26,7 +26,7 @@ String collect_identifier(RawLine* line) {
-TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena);
+TokenVec lex_level(RawLine* line, char until, RegionVec* reg_arena);
void expect_char(RawLine* line, char expected) {
@@ -38,7 +38,7 @@ void expect_char(RawLine* line, char expected) {
}
-MaybeChunk lex_expansion_chunk(RawLine* line, ExpansionRegionVec* reg_arena, QuotationMode qmode) {
+MaybeChunk lex_expansion_chunk(RawLine* line, RegionVec* reg_arena, QuotationMode qmode) {
line->pos++; // Consume $
if (line->str[line->pos] == '(') {
line->pos++;
@@ -50,11 +50,11 @@ MaybeChunk lex_expansion_chunk(RawLine* line, ExpansionRegionVec* reg_arena, Quo
TokenVec inner_toks = lex_level(line, ')', reg_arena);
expect_char(line, ')');
expect_char(line, ')');
- push_to_ExpansionRegionVec(
+ push_to_RegionVec(
reg_arena,
- (ExpansionRegion){.mode = ARITHM, .tokens = inner_toks}
+ (Region){.mode = ARITHM, .tokens = inner_toks}
);
- ExpansionRegion* reg_ptr = &reg_arena->items[reg_arena->count]; // TODO: maybe have push() return a pointer [in the macro]
+ Region* reg_ptr = &reg_arena->items[reg_arena->count]; // TODO: maybe have push() return a pointer [in the macro]
return (MaybeChunk){
.some = true,
.value = (Chunk){
@@ -66,11 +66,11 @@ MaybeChunk lex_expansion_chunk(RawLine* line, ExpansionRegionVec* reg_arena, Quo
} else {
TokenVec inner_toks = lex_level(line, ')', reg_arena);
expect_char(line, ')');
- push_to_ExpansionRegionVec(
+ push_to_RegionVec(
reg_arena,
- (ExpansionRegion){.mode = CMD_SUB, .tokens = inner_toks}
+ (Region){.mode = CMD_SUB, .tokens = inner_toks}
);
- ExpansionRegion* reg_ptr = &reg_arena->items[reg_arena->count];
+ Region* reg_ptr = &reg_arena->items[reg_arena->count];
return (MaybeChunk) {
.some = true,
.value = (Chunk){
@@ -97,7 +97,7 @@ MaybeChunk lex_expansion_chunk(RawLine* line, ExpansionRegionVec* reg_arena, Quo
}
-void lex_double_quoted_section(RawLine* line, ChunkVec* coll, ExpansionRegionVec* reg_arena) {
+void lex_double_quoted_section(RawLine* line, Word* coll, RegionVec* reg_arena) {
line->pos++;
String accum = make_String(256);
while (line->str[line->pos] != '\"') {
@@ -117,20 +117,20 @@ void lex_double_quoted_section(RawLine* line, ChunkVec* coll, ExpansionRegionVec
if (exp_chunk.some) {
if (accum.count > 0) {
- push_to_ChunkVec(coll, (Chunk){
+ push_to_Word(coll, (Chunk){
.qmode = DOUBLE_Q,
.kind = LITERAL,
.as.literal_str = inner(accum)
});
accum = make_String(256);
}
- push_to_ChunkVec(coll, exp_chunk.value);
+ push_to_Word(coll, exp_chunk.value);
exp_chunk.some = false;
}
}
line->pos++;
if (accum.count > 0) {
- push_to_ChunkVec(coll, (Chunk){
+ push_to_Word(coll, (Chunk){
.qmode = DOUBLE_Q,
.kind = LITERAL,
.as.literal_str = inner(accum)
@@ -139,7 +139,7 @@ void lex_double_quoted_section(RawLine* line, ChunkVec* coll, ExpansionRegionVec
}
-Chunk next_word_unquoted(RawLine* line, ExpansionRegionVec* reg_arena) {
+Chunk next_word_unquoted(RawLine* line, RegionVec* reg_arena) {
String buf = make_String(256);
for (char c; (c=line->str[line->pos], c != '$' && c != '\0' && c != ' '); line->pos++) {
push_to_String(&buf, c);
@@ -165,11 +165,11 @@ Chunk collect_single_quoted_section(RawLine* line) {
-TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
+TokenVec lex_level(RawLine* line, char until, RegionVec* reg_arena) {
printf("\n\n==== START LEVEL ===\n\n");
TokenVec tokens = make_TokenVec(256);
- ChunkVec curr_chunks = make_ChunkVec(256);
+ Word curr_chunks = make_Word(256);
String word_buf = make_String(256);
while (line->str[line->pos] != until) {
@@ -177,7 +177,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
if (line->str[line->pos] == ' ') {
if (word_buf.count > 0) {
- push_to_ChunkVec(
+ push_to_Word(
&curr_chunks,
(Chunk){.qmode = UN_Q, .kind = LITERAL, .as.literal_str = inner(word_buf)}
);
@@ -185,7 +185,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
}
if (curr_chunks.count > 0) {
push_to_TokenVec(&tokens, (Token){.kind = TOK_WORD, .as.word = curr_chunks});
- curr_chunks = make_ChunkVec(256);
+ curr_chunks = make_Word(256);
}
while (line->str[line->pos] == ' ') line->pos++;
@@ -193,7 +193,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
switch (line->str[line->pos]) {
case '\'':
- push_to_ChunkVec(&curr_chunks, collect_single_quoted_section(line));
+ push_to_Word(&curr_chunks, collect_single_quoted_section(line));
break;
case '\"':
lex_double_quoted_section(line, &curr_chunks, reg_arena);
@@ -202,7 +202,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
line->pos++;
MaybeChunk mchunk = lex_expansion_chunk(line, reg_arena, UN_Q);
if (mchunk.some) {
- push_to_ChunkVec(&curr_chunks, mchunk.value);
+ push_to_Word(&curr_chunks, mchunk.value);
} else {
push_to_String(&word_buf, '$');
}
@@ -213,7 +213,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
}
if (word_buf.count > 0) {
- push_to_ChunkVec(
+ push_to_Word(
&curr_chunks,
(Chunk){.qmode = UN_Q, .kind = LITERAL, .as.literal_str = inner(word_buf)}
);
@@ -228,7 +228,7 @@ TokenVec lex_level(RawLine* line, char until, ExpansionRegionVec* reg_arena) {
LexResult lex(char* input) {
RawLine line = {.str = input, .pos = 0};
- ExpansionRegionVec reg_arena = make_ExpansionRegionVec(256);
+ RegionVec reg_arena = make_RegionVec(256);
TokenVec toks = lex_level(&line, '\0', &reg_arena);
return (LexResult){.top_tokens = toks, .reg_arena = reg_arena};
}
diff --git a/lex.h b/lex.h
index f8d48ab..b6a102d 100644
--- a/lex.h
+++ b/lex.h
@@ -4,7 +4,7 @@
#include "typeutils.h"
-typedef struct ExpansionRegion ExpansionRegion;
+typedef struct Region Region;
typedef enum {
@@ -24,13 +24,15 @@ typedef struct {
QuotationMode qmode;
union {
char* literal_str;
- ExpansionRegion* reg_ptr;
+ Region* reg_ptr;
char* varname;
} as;
} Chunk;
-DECLARE_VEC(Chunk, ChunkVec)
+DECLARE_VEC(Chunk, Word)
+
+DECLARE_VEC(Word, WordVec)
typedef enum {
TOK_WORD,
@@ -52,7 +54,7 @@ typedef struct {
TokenKind kind;
union {
- ChunkVec word;
+ Word word;
SpecialToken spec;
} as;
} Token;
@@ -67,19 +69,19 @@ typedef enum {
ARITHM,
} RegionMode;
-struct ExpansionRegion {
+struct Region {
RegionMode mode;
TokenVec tokens;
};
DECLARE_MAYBE(Chunk);
-DECLARE_VEC(ExpansionRegion, ExpansionRegionVec)
+DECLARE_VEC(Region, RegionVec)
typedef struct {
TokenVec top_tokens;
- ExpansionRegionVec reg_arena;
+ RegionVec reg_arena;
} LexResult;
diff --git a/parse.c b/parse.c
index c1f1bb8..87af679 100644
--- a/parse.c
+++ b/parse.c
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+
#include "typeutils.h"
#include "lex.h"
@@ -5,13 +7,15 @@ DECLARE_VEC(char*, StrVec)
typedef struct {
- TokenVec tokens;
+ Token* ptr;
+ size_t len;
size_t pos;
} TokStream;
typedef enum {
STDIN_REDIR,
- STDOUT_REDIT,
+ STDOUT_REDIR_TRUNC,
+ STDOUT_REDIR_APPEND,
} RedirKind;
@@ -19,14 +23,14 @@ typedef struct {
RedirKind kind;
union {
- char* std_redir_filename;
+ Word std_redir_filename;
} as;
} Redirect;
DECLARE_VEC(Redirect, RedirectVec)
typedef struct {
- StrVec args;
+ WordVec args;
RedirectVec redirects;
// TODO: prefix variable settings
} Command;
@@ -48,21 +52,48 @@ typedef struct {
DECLARE_VEC(PipelineElement, Pipeline)
+
Command parse_command(TokStream* toks) {
- StrVec args = make_StrVec(256);
+ WordVec args = make_WordVec(256);
RedirectVec redirects = make_RedirectVec(256);
for (
Token curr_tok;
- (curr_tok = toks->tokens.items[toks->pos], !(curr_tok.kind == TOK_SPECIAL && (curr_tok.as.spec == PIPE && curr_tok.as.spec == EOL)));
+ (curr_tok = toks->ptr[toks->pos], !(curr_tok.kind == TOK_SPECIAL && (curr_tok.as.spec == PIPE && curr_tok.as.spec == EOL)));
toks->pos++
) {
if (curr_tok.kind == TOK_SPECIAL) {
+ Token tok;
+ switch (curr_tok.as.spec) {
+ case WRITE_REDIR_TRUNC:
+ toks->pos++;
+ tok = toks->ptr[toks->pos];
+ if(tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_TRUNC, .as.std_redir_filename = tok.as.word});
+ break;
+ case WRITE_REDIR_APPEND:
+ toks->pos++;
+ tok = toks->ptr[toks->pos];
+ if(tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_APPEND, .as.std_redir_filename = tok.as.word});
+ break;
+ case READ_REDIR:
+ toks->pos++;
+ tok = toks->ptr[toks->pos];
+ if(tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_APPEND, .as.std_redir_filename = tok.as.word});
+ break;
+ default:
+ exit(69);
+ }
+ } else if (curr_tok.kind == TOK_WORD){
+ push_to_WordVec(&args, curr_tok.as.word);
}
}
+ return (Command){.args = args, .redirects = redirects};
}
Pipeline parse_tokstream(TokenVec toks) {
- TokStream tokstream = {.tokens = toks, .pos = 0};
+ TokStream tokstream = {.ptr = toks.items, .len = toks.count, .pos = 0};
Pipeline result = make_Pipeline(256);
}