diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | lex.h | 72 | ||||
| -rw-r--r-- | main.c | 182 | ||||
| -rw-r--r-- | typeutils.h | 63 |
4 files changed, 206 insertions, 112 deletions
@@ -1 +1,2 @@ bin/ +.clangd @@ -0,0 +1,72 @@ +#include "typeutils.h" + + +typedef struct Region Region; + + +typedef enum { + UN_Q, + SINGLE_Q, + DOUBLE_Q, +} QuotationMode; + + +typedef enum { + LITERAL, + CMD_SUB, + ARITHM, + VAR_EXP, // TODO: Later include other exps +} ChunkKind; + + +typedef struct { + ChunkKind kind; + QuotationMode mode; + + union { + char* lit_str; + Region* sub_cmd_region; + Region* arithm_expr_region; + char* param_string; + } as; +} Chunk; + + +DECLARE_VEC(Chunk, ChunkVec) + +typedef enum { + TOK_WORD, + TOK_SPECIAL, +} TokenKind; + +typedef enum { + PIPE, + WRITE_REDIR_TRUNC, + WRITE_REDIR_APPEND, + READ_REDIR, + EOL, +} SpecialToken; + +typedef struct { + TokenKind kind; + + union { + ChunkVec word; + SpecialToken spec; + } as; +} Token; + + +DECLARE_VEC(Token, TokenVec) + +DECLARE_MAYBE(SpecialToken) + + +struct Region { + QuotationMode mode; + TokenVec tokens; +}; + +DECLARE_MAYBE(Chunk); + +DECLARE_VEC(Region, RegionVec) @@ -1,141 +1,99 @@ +#include <ctype.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdio.h> +#include "lex.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 void 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; \ - } \ - - -DECLARE_VEC(char, String); - -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)); +String collect_identifier(char* input, size_t* pos) { + String id_buf = make_String(256); + while (input[*pos] == '_' || isalnum(input[*pos])) { + push_to_String(&id_buf, input[(*pos)++]); } - memcpy(target->items + target->count, src_str, strlen(src_str)); - target->count += strlen(src_str); + return id_buf; } +String collect_single_quoted_section(char* input, size_t* pos) { + (*pos)++; // Consume quote mark + String chunk_str = make_String(256); + while (input[*pos] != '\'') { + if (input[*pos] == '\0') exit(42); + push_to_String(&chunk_str, input[(*pos)++]); + } + (*pos)++; // Consume closing quote + return chunk_str; +} -#define DECLARE_MAYBE(T) \ - typedef struct { \ - bool some; \ - T value; \ - } Maybe##T; \ - - - -typedef enum { - UN_Q, - SINGLE_Q, - DOUBLE_Q, -} QuotationMode; - -typedef struct Region Region; - -typedef enum { - LITERAL, - CMD_SUB, - ARITHM, - PARAM, -} ChunkKind; +TokenVec lex_region(char* input, size_t* pos, char until); -typedef struct { - ChunkKind kind; - QuotationMode mode; +void expect_char(char* input, size_t* pos, char expected) { + if (input[*pos] != expected) exit(42); // TODO: nicer handling + (*pos)++; +} - union { - char* lit_str; - Region* sub_cmd_region; - Region* arithm_expr_region; - Region* param_region; - } as; -} Chunk; +void lex_double_quoted_section(char* input, size_t* pos, ChunkVec* coll, RegionVec* reg_arena) { + (*pos)++; + String accum = make_String(256); + while (input[*pos] != '\"') { + if (input[*pos] == '\0') exit(42); + + if (input[*pos] == '$') { + (*pos)++; + if (input[*pos] == '(') { + if (input[*pos] == '(') { + TokenVec inner_toks = lex_region(input, pos, ')'); + expect_char(input, pos, ')'); + expect_char(input, pos, ')'); + push_to_RegionVec(reg_arena, (Region){.}) + push_to_ChunkVec(coll, (Chunk){.mode = DOUBLE_Q, .kind = ARITHM, .as.arithm_expr_region = inner_toks}); + } + } else { + String id_name = collect_identifier(input, pos); + if (id_name.count > 0) { + push_to_ChunkVec(coll, (Chunk){.mode = DOUBLE_Q, .kind = VAR_EXP, .as.param_string = inner(id_name)}); + } + continue; + } + } else { + + } + } +} -DECLARE_VEC(Chunk, ChunkVec) -typedef enum { - TOK_WORD, - TOK_SPECIAL, -} TokenKind; -typedef enum { - PIPE, - WRITE_REDIR_TRUNC, - WRITE_REDIR_APPEND, - READ_REDIR, - EOL, -} SpecialToken; typedef struct { - TokenKind kind; - - union { - ChunkVec word; - SpecialToken spec; - } as; -} Token; - - -DECLARE_VEC(Token, TokenVec) - -DECLARE_MAYBE(SpecialToken) - -struct Region { - QuotationMode mode; - TokenVec tokens; -}; - -DECLARE_MAYBE(Chunk); - - -MaybeChunk unquoted_next_chunk(char* input, size_t* pos) { - String chunk; - char curr_c; - for (;(curr_c = input[*pos], curr_c != '$' && curr_c != '\'' && curr_c != '\"' && curr_c != '\0'); pos++) { - exit(1); - } - exit(1); -} - + Region root_reg; + RegionVec reg_arena; +} LexResult; +// TODO: maybe make an input+pos struct TokenVec lex_region(char* input, size_t* pos, char until) { TokenVec tokens = make_TokenVec(256); + RegionVec reg_arena; while (input[*pos] != until) { - while (input[*pos] == ' ') (*pos)++; + // Getting a token + + if (input[*pos] == ' ') { + (*pos)++; + continue; + } + + ChunkVec chunks = make_ChunkVec(256); + switch (input[*pos]) { + case '\'': + String qstring = get_single_quoted_chunk(input, pos); + push_to_ChunkVec(&chunks, (Chunk){.mode=SINGLE_Q, .kind = LITERAL, .as.lit_str = qstring.items}); + break; + + } } return tokens; diff --git a/typeutils.h b/typeutils.h new file mode 100644 index 0000000..1d260ef --- /dev/null +++ b/typeutils.h @@ -0,0 +1,63 @@ +#pragma once + +#include <ctype.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#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 void 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; \ + } + + +DECLARE_VEC(char, String); + +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)); + } + 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)); + } + str.items[str.count] = '\0'; + return str.items; +} + +#define DECLARE_MAYBE(T) \ + typedef struct { \ + bool some; \ + T value; \ + } Maybe##T; |
