summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÁkos Kőrösi <korakos99@gmail.com>2026-05-12 02:31:34 +0200
committerÁkos Kőrösi <korakos99@gmail.com>2026-05-12 02:31:34 +0200
commitb59501340a5d6b1c0ace169f140391cc0555015e (patch)
tree71e8da755209a63cf57c52907777485cda9f27e2
parent30fd15dec535007340ffb0d8b7617a7b0d76ef3a (diff)
write some lexing; split code into files
-rw-r--r--.gitignore1
-rw-r--r--lex.h72
-rw-r--r--main.c182
-rw-r--r--typeutils.h63
4 files changed, 206 insertions, 112 deletions
diff --git a/.gitignore b/.gitignore
index e660fd9..54ae6be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
bin/
+.clangd
diff --git a/lex.h b/lex.h
new file mode 100644
index 0000000..db4d713
--- /dev/null
+++ b/lex.h
@@ -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)
diff --git a/main.c b/main.c
index 0052ad9..cbbe8b3 100644
--- a/main.c
+++ b/main.c
@@ -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;