summaryrefslogtreecommitdiff
path: root/core/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/parser.c')
-rw-r--r--core/parser.c93
1 files changed, 85 insertions, 8 deletions
diff --git a/core/parser.c b/core/parser.c
index b4f5696..fb8d817 100644
--- a/core/parser.c
+++ b/core/parser.c
@@ -26,6 +26,14 @@
#define tokstr(tok) \
toktab[(tok)->type]
+/* Unexpected token */
+#define utok(tok) \
+ cc_error("unexpected token %s\n", tokstr(tok));
+#define utok1(tok, exp_tt) \
+ cc_error("unexpected token %s, expected %s\n", tokstr(tok), tokstr1(exp_tt))
+
+static int parser_expect(struct cescal_state *state, struct token *res, tt_t exp);
+
/*
* Converts numeric tokens into human readable strings
*/
@@ -58,16 +66,51 @@ static const char *toktab[] = {
[TT_U64] = qtok("u64")
};
+
+/*
+ * Parse a preprocessor define directive
+ */
+static int
+parse_define(struct cescal_state *state, struct token *tok)
+{
+ struct symbol *sym;
+ int error;
+
+ if (state == NULL || tok == NULL) {
+ return -1;
+ }
+
+ if (parser_expect(state, tok, TT_IDENT) < 0) {
+ return -1;
+ }
+
+ /* XXX: Should probably be a warning */
+ if ((sym = symbol_byname(&state->symtab, tok->s)) != NULL) {
+ cc_error("redefinition of symbol %s\n", tok->s);
+ return -1;
+ }
+
+ /* Allocate the symbol */
+ error = symbol_allocate(&state->symtab, tok->s, SYMBOL_NONE, &sym);
+ if (error < 0) {
+ cc_error("[internal]: failed to allocate symbol\n");
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* Push a token to the token buffer in the preprocessing stage
*
+ * @state: Compiler state
* @tokbuf: Token buffer to push to
* @tok: Token to push
*
* Returns zero on success
*/
static int
-preprocessor_push(struct tokbuf *tokbuf, struct token *tok)
+preprocessor_push(struct cescal_state *state, struct tokbuf *tokbuf, struct token *tok)
{
if (tokbuf == NULL || tok == NULL) {
return -1;
@@ -75,8 +118,14 @@ preprocessor_push(struct tokbuf *tokbuf, struct token *tok)
switch (tok->type) {
case TT_IFNDEF:
+ break;
case TT_IFDEF:
+ break;
case TT_DEFINE:
+ if (parse_define(state, tok) < 0) {
+ return -1;
+ }
+
break;
default:
if (tokbuf_push(tokbuf, tok) < 0) {
@@ -90,8 +139,6 @@ preprocessor_push(struct tokbuf *tokbuf, struct token *tok)
static int
parser_nom(struct cescal_state *state, struct token *res)
{
- struct token tok;
-
if (state == NULL || res == NULL) {
errno = EINVAL;
return -1;
@@ -99,24 +146,52 @@ parser_nom(struct cescal_state *state, struct token *res)
switch (state->pass) {
case 0: /* Pre-processor */
- if (lexer_nom(state, &tok) < 0) {
+ if (lexer_nom(state, res) < 0) {
return -1;
}
- if (preprocessor_push(&state->tokbuf, &tok) < 0) {
+ if (preprocessor_push(state, &state->tokbuf, res) < 0) {
return -1;
}
break;
case 1: /* Parse */
- if (tokbuf_pop(&state->tokbuf, &tok) < 0) {
+ if (tokbuf_pop(&state->tokbuf, res) < 0) {
return -1;
}
break;
}
- *res = tok;
+ return 0;
+}
+
+/*
+ * Assert that the next token is of a specific type
+ *
+ * @state: Compiler state
+ * @res: Token result is written here
+ * @exp: Token expedcted
+ *
+ * Returns zero on success
+ */
+static int
+parser_expect(struct cescal_state *state, struct token *res, tt_t exp)
+{
+ if (state == NULL || res == NULL) {
+ return -1;
+ }
+
+ if (parser_nom(state, res) < 0) {
+ cc_error("unexpected end of file\n");
+ return -1;
+ }
+
+ if (res->type != exp) {
+ utok1(res, exp);
+ return -1;
+ }
+
return 0;
}
@@ -131,7 +206,9 @@ parser_parse(struct cescal_state *state)
}
while (parser_nom(state, &tok) == 0) {
- cc_trace("got token %s\n", tokstr(&tok));
+ if (state->pass > 0) {
+ cc_trace("got token %s\n", tokstr(&tok));
+ }
}
++state->pass;