aboutsummaryrefslogtreecommitdiff
path: root/src/parser.h
blob: 363478c6573eadbe7f7cef7dc13cb495024ef3b0 (plain) (blame)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef ORYX_PARSER_H
#define ORYX_PARSER_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "lexer.h"
#include "types.h"

enum {
	/* The first four AST tokens are declarations.  A declaration is any
	   token T for which ‘T <= _AST_DECLS_END’ holds.  Declarations can
	   also be made public by using the ‘pub’ keyword, and you can tell
	   if a declaration is public by if the LSB is set. */

	/* Variable declaration, lhs and rhs may be unused
	   ‘x := rhs’; aux[lhs].decl */
	ASTDECL,

	/* Constant declaration, lhs may be unused
	   ‘x :: rhs’; aux[lhs].decl */
	ASTCDECL,

	_AST_DECLS_END = ASTCDECL,

	/* Function prototype
	   ‘(a: b, c: d) rhs’; aux[lhs].fnproto */
	ASTFNPROTO,

	/* Function
	   ‘(…)@lhs {…}@rhs’ */
	ASTFN,

	/* Braced block, an empty block has lhs = AST_EMPTY and rhs = 0
	   { stmt@lhs; …; stmt@rhs; } */
	ASTBLK,

	/* Identifier literal */
	ASTIDENT,

	/* Numeric literal */
	ASTNUMLIT,

	/* Typename */
	ASTTYPE,

	/* Return statement, rhs may be unused
	   ‘return rhs’ */
	ASTRET,

	/* Assignment,
	   ‘lhs = rhs’ */
	ASTASIGN,

	/* Unary negation
	   ‘-rhs’ */
	ASTUNNEG,

	/* Unary complement
	   ‘~rhs’ */
	ASTUNCMPL,

	/* NOTE: Ensure that the enumerations defined above this comment do
	   not exceed 37 — the value of ‘%’ — or they will conflict with the
	   definitions below. */

	/* Binary add
	   ‘lhs + rhs’ */
	ASTBINADD = '+',

	/* Binary subtraction
	   ‘lhs - rhs’ */
	ASTBINSUB = '-',

	/* Binary multiplication
	   ‘lhs - rhs’ */
	ASTBINMUL = '*',

	/* Binary division
	   ‘lhs - rhs’ */
	ASTBINDIV = '/',

	/* Binary modulus
	   ‘lhs % rhs’ */
	ASTBINMOD = '%',

	/* Binary XOR
	   ‘lhs ~ rhs’ */
	ASTBINXOR = '~',

	/* Binary bitwise AND
	   ‘lhs & rhs’ */
	ASTBINAND = '&',

	/* Binary bitwise OR
	   ‘lhs & rhs’ */
	ASTBINIOR = '|',

	/* Binary not equals
	   ‘lhs != rhs’ */
	ASTBINNEQ = UINT8_MAX - 3,

	/* Binary left shift
	   ‘lhs << rhs’ */
	ASTBINSHL = UINT8_MAX - 2,

	/* Binary equals
	   ‘lhs == rhs’ */
	ASTBINEQ = UINT8_MAX - 1,

	/* Binary right shift
	   ‘lhs >> rhs’ */
	ASTBINSHR = UINT8_MAX - 0,
};

#define AST_EMPTY     ((idx_t)-1)
#define AST_SOA_BLKSZ (1 + sizeof(idx_t) + sizeof(pair_t))

typedef struct {
	union {
		struct {
			idx_t type;
			bool ispub    : 1;
			bool isstatic : 1;
			bool isundef  : 1;
		} decl;
	} *buf;
	size_t len, cap;
} aux_t;

typedef struct {
	idx_t lhs, rhs;
} pair_t;

typedef struct {
	uint8_t *kinds;
	idx_t *lexemes;
	pair_t *kids;
	size_t len, cap;
} ast_t;

#define ast_free(x) free((x).kinds)
#define aux_free(x) free((x).buf)

/* Parse the tokens in TOKS into an abstract syntax tree, and store
   auxilliary information in AUX */
ast_t parsetoks(lexemes_t toks, aux_t *aux)
	__attribute__((nonnull));

/* Starting from the node at indent I in AST, return the index of the next node
   in AST that is of the same nest-depth as I */
idx_t fwdnode(ast_t ast, idx_t i);

#endif /* !ORYX_PARSER_H */