1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#pragma once
#include "utils.h"
typedef struct Region Region;
// Lexing stage
typedef enum {
UN_Q,
SINGLE_Q,
DOUBLE_Q,
} QuotationMode;
typedef enum {
LITERAL,
REGION_EXP,
VAR_EXP, // TODO: Later include other exps
} ChunkKind;
typedef struct {
ChunkKind kind;
QuotationMode qmode;
union {
char* literal_str;
Region* reg_ptr;
char* varname;
} as;
} Chunk;
DECLARE_MAYBE(Chunk, MaybeChunk);
DECLARE_VEC(Chunk*, Word)
typedef enum {
TOK_WORD,
TOK_SPECIAL,
TOK_PROCSUB_IN,
TOK_PROCSUB_OUT,
} TokenKind;
typedef enum {
PIPE,
WRITE_REDIR_TRUNC,
WRITE_REDIR_APPEND,
READ_REDIR,
EOL,
} SpecialToken;
DECLARE_MAYBE(SpecialToken, MaybeSpecialToken)
typedef struct {
TokenKind kind;
union {
Word word;
SpecialToken spec;
Region* procsub_region;
} as;
} Token;
DECLARE_VEC(Token*, TokenPtrVec)
typedef enum {
CMDS,
ARITHM,
} RegionMode;
struct Region {
RegionMode mode;
TokenPtrVec tokens;
};
DECLARE_VEC(Region, RegionVec)
DECLARE_VEC(Chunk, ChunkVec)
DECLARE_VEC(Token, TokenVec)
// Lexing
typedef struct {
RegionVec regions;
TokenVec tokens;
ChunkVec chunks;
} PreprocArena;
TokenPtrVec lex(char* input, PreprocArena* arena);
// Parsing
typedef enum {
CONN_PIPE,
CONN_EOL,
// TODO: add the |& thingy
} Connector;
DECLARE_MAYBE(Connector, MaybeConnector)
typedef struct {
TokenVec cmd_toks;
Connector conn;
} PipelineElement;
DECLARE_VEC(PipelineElement, Pipeline)
Pipeline parse_tokstream(Token* tokstream);
|