4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
0
|
// Copyright (C) 2023, Jakob Wakeling |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
1
|
// All rights reserved. |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
2
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
3
|
#include "parse.h" |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
4
|
#include "util/log.h" |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
5
|
#include "util/stack.h" |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
6
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
7
|
#include <assert.h> |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
8
|
#include <stdio.h> |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
9
|
#include <stdlib.h> |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
10
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
11
|
char *ast_ks[] = { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
12
|
"AK_VOID", "AK_COMM", "AK_PIPE", |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
13
|
}; |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
14
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
15
|
/* Initialise an AST node. */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
16
|
extern ast *ast_init(ast_k kind) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
17
|
ast *a = xcalloc(1, sizeof(*a)); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
18
|
a->k = kind; return a; |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
19
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
20
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
21
|
/* Uninitialise an AST node and its children. */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
22
|
extern void ast_free(ast *a) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
23
|
if (a == NULL) { return; } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
24
|
ast_free(a->lc); ast_free(a->rc); stack_free(&a->c); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
25
|
free(a->rin.s); free(a->rout.s); free(a->rerr.s); free(a); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
26
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
27
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
28
|
#define T (l->t) /* Current Token */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
29
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
30
|
static ast *parse_comm(lex *l); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
31
|
static ast *parse_pipe(lex *l, ast *lhs); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
32
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
33
|
/* Parse a program. */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
34
|
extern ast *parse(lex *l) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
35
|
for (; T.k == TK_END; lex_next(l)); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
36
|
if (T.k == TK_EOF) { return NULL; } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
37
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
38
|
if (T.k != TK_WORD) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
39
|
log_warn("Unexpected \"%s\", was expecting a word", tok_ks[T.k]); return NULL; |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
40
|
} |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
41
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
42
|
ast *lhs = parse_comm(l); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
43
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
44
|
for (;;) switch (lex_next(l).k) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
45
|
case TK_PIPE: { lhs = parse_pipe(l, lhs); } continue; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
46
|
default: {} return lhs; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
47
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
48
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
49
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
50
|
/* Parse a command statement. */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
51
|
static ast *parse_comm(lex *l) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
52
|
assert(T.k == TK_WORD); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
53
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
54
|
ast *a = ast_init(AK_COMM); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
55
|
a->c = stack_init(sizeof (char *), &free); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
56
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
57
|
/* Push each command argument onto the child stack */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
58
|
stack_push(&a->c, (a->s = lex_next(l).s)); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
59
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
60
|
for (;;) switch (lex_peek(l).k) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
61
|
case TK_WORD: { stack_push(&a->c, lex_next(l).s); } continue; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
62
|
case TK_RIN: { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
63
|
if (lex_next(l), T.k == TK_WORD) { a->rin.s = lex_next(l).s; } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
64
|
else { log_warn("Unexpected token \"%s\"", tok_ks[T.k]); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
65
|
} continue; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
66
|
case TK_ROUT: { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
67
|
if (lex_next(l), T.k == TK_WORD) { a->rout.s = lex_next(l).s; a->rout.app = false; } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
68
|
else { log_warn("Unexpected token \"%s\"", tok_ks[T.k]); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
69
|
} continue; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
70
|
case TK_RAPP: { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
71
|
if (lex_next(l), T.k == TK_WORD) { a->rout.s = lex_next(l).s; a->rout.app = true; } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
72
|
else { log_warn("Unexpected token \"%s\"", tok_ks[T.k]); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
73
|
} continue; |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
74
|
default: { stack_push(&a->c, NULL); } return a; |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
75
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
76
|
} |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
77
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
78
|
/* Parse a pipe statement. */ |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
79
|
static ast *parse_pipe(lex *l, ast *lhs) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
80
|
ast *a = ast_init(AK_PIPE); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
81
|
a->lc = lhs; a->rc = parse_comm(l); return a; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
82
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
83
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
84
|
/* Print parser debug output. */ |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
85
|
extern void ast_debug(ast *a, u64 indent) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
86
|
for (u64 i = 0; i != indent; i += 1) { printf("\t"); } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
87
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
88
|
printf("%s: %s", ast_ks[a->k], a->s); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
89
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
90
|
if (a->k == AK_COMM) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
91
|
for (u64 i = 1; i != a->c.al - 1; i += 1) { |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
92
|
printf(" %s", ((char **)a->c.a)[i]); |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
93
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
94
|
if (a->rin.s) { printf(" < %s", a->rin.s); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
95
|
if (a->rout.s) { printf(a->rout.app ? " >> %s" : " > %s", a->rout.s); } |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
96
|
} |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
97
|
|
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
98
|
printf("\n"); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
99
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
100
|
if (a->lc) { ast_debug(a->lc, indent + 1); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
101
|
if (a->rc) { ast_debug(a->rc, indent + 1); } |
4681f43 |
Jakob Wakeling |
2023-12-27 16:22:43 |
102
|
} |
|
|
|
103
|
|