ESH

Executive Shell
git clone http://git.omkov.net/ESH
Log | Tree | Refs | README | Download

ESH/src/parse.c (104 lines, 2.6 KiB) -rw-r--r-- file download

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