summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lex.c14
-rw-r--r--main.c26
-rw-r--r--parse.c48
-rw-r--r--typeutils.h119
4 files changed, 134 insertions, 73 deletions
diff --git a/lex.c b/lex.c
index 8ffb2a8..8c64751 100644
--- a/lex.c
+++ b/lex.c
@@ -31,7 +31,6 @@ TokenVec lex_level(RawLine* line, char until, RegionVec* reg_arena);
void expect_char(RawLine* line, char expected) {
if (line->str[line->pos] != expected) {
- printf("Expected %c, got %c.", expected, line->str[line->pos]);
exit(45); // TODO: nicer handling
}
line->pos++;
@@ -86,7 +85,7 @@ MaybeChunk lex_expansion_chunk(RawLine* line, RegionVec* reg_arena, QuotationMod
.value = (Chunk){
.qmode = qmode,
.kind = VAR_EXP,
- .as.varname = inner(id_name),
+ .as.varname = inner(&id_name),
}
};
}
@@ -118,7 +117,7 @@ void lex_double_quoted_section(RawLine* line, Word* coll, RegionVec* reg_arena)
push_to_Word(coll, (Chunk){
.qmode = DOUBLE_Q,
.kind = LITERAL,
- .as.literal_str = inner(accum)
+ .as.literal_str = inner(&accum)
});
accum = make_String(256);
}
@@ -131,7 +130,7 @@ void lex_double_quoted_section(RawLine* line, Word* coll, RegionVec* reg_arena)
push_to_Word(coll, (Chunk){
.qmode = DOUBLE_Q,
.kind = LITERAL,
- .as.literal_str = inner(accum)
+ .as.literal_str = inner(&accum)
});
}
}
@@ -142,7 +141,7 @@ Chunk next_word_unquoted(RawLine* line, RegionVec* reg_arena) {
for (char c; (c=line->str[line->pos], c != '$' && c != '\0' && c != ' '); line->pos++) {
push_to_String(&buf, c);
}
- return (Chunk){.qmode = UN_Q, .kind = LITERAL, .as.literal_str = inner(buf)};
+ return (Chunk){.qmode = UN_Q, .kind = LITERAL, .as.literal_str = inner(&buf)};
}
@@ -157,7 +156,7 @@ Chunk collect_single_quoted_section(RawLine* line) {
return (Chunk){
.qmode = SINGLE_Q,
.kind = LITERAL,
- .as.literal_str = inner(chunk_str),
+ .as.literal_str = inner(&chunk_str),
};
}
@@ -176,7 +175,7 @@ void close_literal_germ(LexState* state) {
(Chunk){
.qmode = UN_Q,
.kind = LITERAL,
- .as.literal_str = inner(state->unq_liter_germ)
+ .as.literal_str = inner(&state->unq_liter_germ)
}
);
state->unq_liter_germ = make_String(256);
@@ -201,6 +200,7 @@ TokenVec lex_level(RawLine* line, char until, RegionVec* reg_arena) {
while (line->str[line->pos] != until) {
+
if (line->str[line->pos] == ' ') {
close_word_and_lit_germs(&state);
while (line->str[line->pos] == ' ') line->pos++;
diff --git a/main.c b/main.c
index 690b6d9..70382c4 100644
--- a/main.c
+++ b/main.c
@@ -6,6 +6,28 @@
#include "lex.h"
#include "parse.h"
+void uglyprint_pl(Pipeline pl) {
+ for (int i = 0; i < pl.count; i++) {
+ printf("%d\n");
+ TokenVec toks = (*get_from_Pipeline(&pl, i)).cmd.args;
+ for (int j = 0; j < toks.count; j++) {
+ Token tok = *get_from_TokenVec(&toks, j);
+ if (tok.kind != TOK_WORD) {
+ printf(" [NON-WORD] ");
+ continue;
+ }
+ Word word = tok.as.word;
+ for (int k = 0; k < word.count; k++) {
+ Chunk chunk = *get_from_Word(&word, k);
+ if (chunk.kind == LITERAL) {
+ printf("%s", chunk.as.literal_str);
+ }
+ }
+ }
+ }
+}
+
+
int main() {
char* line;
while (1) {
@@ -14,11 +36,9 @@ int main() {
if (strcmp(line, "exit") == 0) exit(0);
LexResult res = lex(line);
Pipeline pl = parse_tokstream(res.top_tokens);
- printf("%s \n", line);
+ uglyprint_pl(pl);
}
-
free(line);
-
}
diff --git a/parse.c b/parse.c
index 90b904e..5ed08de 100644
--- a/parse.c
+++ b/parse.c
@@ -8,18 +8,21 @@ DECLARE_VEC(char*, StrVec)
typedef struct {
- Token* ptr;
- size_t len;
+ TokenVec vec;
size_t pos;
} TokStream;
Connector parse_connector(TokStream* toks) {
- Token tok = toks->ptr[toks->pos];
+ Token tok = *get_from_TokenVec(&toks->vec, toks->pos);
if (tok.kind != TOK_SPECIAL) exit(67);
switch (tok.as.spec) {
- case PIPE: return CONN_PIPE;
- case EOL: return CONN_EOL;
+ case PIPE:
+ toks->pos++;
+ return CONN_PIPE;
+ case EOL:
+ toks->pos++;
+ return CONN_EOL;
default: exit(76);
}
}
@@ -28,32 +31,31 @@ Connector parse_connector(TokStream* toks) {
Command parse_command(TokStream* toks) {
TokenVec args = make_TokenVec(256);
RedirectVec redirects = make_RedirectVec(256);
- for (
- Token curr_tok;
- (curr_tok = toks->ptr[toks->pos], !(curr_tok.kind == TOK_SPECIAL && (curr_tok.as.spec == PIPE || curr_tok.as.spec == EOL)));
- toks->pos++
- ) {
+ while (true) {
+ Token curr_tok = *get_from_TokenVec(&toks->vec, toks->pos);
+ if (curr_tok.kind == TOK_SPECIAL &&(curr_tok.as.spec == PIPE || curr_tok.as.spec == EOL)) {
+ break;
+ }
+
switch (curr_tok.kind) {
case TOK_SPECIAL:
- Token tok;
+ toks->pos++;
+ Token name_tok = *get_from_TokenVec(&toks->vec, toks->pos);
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});
+ if(name_tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_TRUNC, .as.std_redir_filename = name_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});
+ if(name_tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_APPEND, .as.std_redir_filename = name_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});
+ if(name_tok.kind != TOK_WORD) exit(1);
+ push_to_RedirectVec(&redirects, (Redirect){.kind = STDOUT_REDIR_APPEND, .as.std_redir_filename = name_tok.as.word});
break;
default:
exit(69);
@@ -62,13 +64,14 @@ Command parse_command(TokStream* toks) {
default:
push_to_TokenVec(&args, curr_tok);
}
+ toks->pos++;
}
return (Command){.args = args, .redirects = redirects};
}
-Pipeline parse_tokstream(TokenVec toks) {
- TokStream tokstream = {.ptr = toks.items, .len = toks.count, .pos = 0};
+Pipeline parse_tokstream(TokenVec tok_vec) {
+ TokStream tokstream = {.vec = tok_vec, .pos = 0};
Pipeline result = make_Pipeline(256);
while (true) {
Command cmd = parse_command(&tokstream);
@@ -76,4 +79,5 @@ Pipeline parse_tokstream(TokenVec toks) {
push_to_Pipeline(&result, (PipelineElement){.cmd = cmd, .conn = conn});
if (conn == CONN_EOL) break;
}
+ return result;
}
diff --git a/typeutils.h b/typeutils.h
index d83217d..e7aee6f 100644
--- a/typeutils.h
+++ b/typeutils.h
@@ -8,57 +8,94 @@
#include <stdio.h>
-#define DECLARE_VEC(T, Name) \
- typedef struct { \
- T* items; \
- size_t count; \
- size_t cap; \
- size_t incr_step; \
- } Name; \
- static inline Name make_##Name(size_t step) { \
- return (Name) { \
- .items = malloc(step* sizeof(T)), \
- .count = 0, \
- .cap = step, \
- .incr_step = step, \
- }; \
- } \
- static inline T* push_to_##Name(Name* vec, T item) { \
- if (vec->count == vec->cap) { \
- vec->cap += vec->incr_step; \
- vec->items = realloc( \
- vec->items, \
- vec->cap * sizeof(T) \
- ); \
- } \
- vec->items[vec->count] = item; \
- T* ptr = &vec->items[vec->count]; \
- vec->count++; \
- return ptr; \
- }
+#define DECLARE_VEC(T, Name) \
+ typedef struct { \
+ T **blocks; \
+ size_t count; \
+ size_t used; \
+ size_t cap; \
+ size_t block_size; \
+ } Name; \
+ \
+ static inline Name make_##Name(size_t block_size) { \
+ return (Name){ \
+ .blocks = NULL, \
+ .count = 0, \
+ .used = 0, \
+ .cap = 0, \
+ .block_size = block_size, \
+ }; \
+ } \
+ \
+ static inline T *push_to_##Name(Name *vec, T item) { \
+ size_t block_index = vec->count / vec->block_size; \
+ size_t item_index = vec->count % vec->block_size; \
+ \
+ if (block_index == vec->used) { \
+ if (vec->used == vec->cap) { \
+ size_t new_cap = vec->cap \
+ ? vec->cap * 2 \
+ : 8; \
+ \
+ T **new_blocks = realloc( \
+ vec->blocks, \
+ new_cap * sizeof(T *) \
+ ); \
+ \
+ if (!new_blocks) abort(); \
+ \
+ vec->blocks = new_blocks; \
+ vec->cap = new_cap; \
+ } \
+ \
+ vec->blocks[vec->used] = \
+ malloc(vec->block_size * sizeof(T)); \
+ \
+ if (!vec->blocks[vec->used]) abort(); \
+ \
+ vec->used++; \
+ } \
+ \
+ T *ptr = &vec->blocks[block_index][item_index]; \
+ *ptr = item; \
+ \
+ vec->count++; \
+ return ptr; \
+ } \
+ \
+ static inline T* get_from_##Name(Name *vec, size_t index) { \
+ if (index >= vec->count) return NULL; \
+ \
+ return &vec->blocks \
+ [index / vec->block_size] \
+ [index % vec->block_size]; \
+ }
DECLARE_VEC(char, String);
-static void append_str_to_String(String* target, char* src_str) {
- size_t required_size =
- ((target->count + strlen(src_str)) / target->incr_step + 1) * target->incr_step;
- if (required_size > target->cap) {
- target->cap = required_size;
- target->items = realloc(target->items, required_size * sizeof(char));
+
+static void append_str_to_String(String* target, const char* src_str) {
+ size_t len = strlen(src_str);
+
+ for (size_t i = 0; i < len; i++) {
+ push_to_String(target, src_str[i]);
}
- memcpy(target->items + target->count, src_str, strlen(src_str));
- target->count += strlen(src_str);
}
-static inline char* inner(String str) {
- if (str.count == str.cap) {
- str.items = realloc(str.items, (str.cap+1)*sizeof(char));
+static inline char* inner(String* str) {
+ char *out = malloc(str->count + 1);
+ if (!out) abort();
+
+ for (size_t i = 0; i < str->count; i++) {
+ out[i] = *get_from_String(str, i);
}
- str.items[str.count] = '\0';
- return str.items;
+
+ out[str->count] = '\0';
+ return out;
}
+
#define DECLARE_MAYBE(T) \
typedef struct { \
bool some; \