diff options
| author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2026-04-19 17:09:06 +0200 |
|---|---|---|
| committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2026-04-19 17:09:06 +0200 |
| commit | c9f1161ecb323c7872559dd40c56d691dbd5959f (patch) | |
| tree | bc6b974c56d55e11a78cc10bd7da399e54d307cd /lib/parse.c | |
| parent | 984ca5a2330ce29b62892321f258d5a0afb0091c (diff) | |
Start working on parsing/scanning.
Too many changes to list them all individually.
Diffstat (limited to 'lib/parse.c')
| -rw-r--r-- | lib/parse.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/lib/parse.c b/lib/parse.c new file mode 100644 index 0000000..0bf2396 --- /dev/null +++ b/lib/parse.c @@ -0,0 +1,100 @@ +/* Aplwc - A Programming Language With Constraints + * + * Copyright (C) 2026 Peter Mikkelsen <petermikkelsen10@gmail.com> + * + * This file is part of aplwc. + * + * Aplwc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Aplwc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with aplwc. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <string.h> +#include <aplwc.h> +#include "aplwc_internal.h" + +static enum aplwc_token_tag peek(struct aplwc_eval_context *); +static struct aplwc_token *match(struct aplwc_eval_context *, enum aplwc_token_tag); +static void emit(struct aplwc_eval_context *, enum aplwc_ast_tag, struct aplwc_ast **); +static char *token_text(struct aplwc_eval_context *, struct aplwc_token *); +static void parse_syscmd(struct aplwc_eval_context *, struct aplwc_ast **); + +void +aplwc_parse(struct aplwc_eval_context *context) +{ + context->token_offset = 0; + + if(peek(context) == APLWC_TOKEN_SYSCMD) + parse_syscmd(context, &context->ast); + + if(context->ast == NULL) + emit(context, APLWC_AST_ERROR, &context->ast); +} + +static enum aplwc_token_tag +peek(struct aplwc_eval_context *context) +{ + enum aplwc_token_tag tag = -1; + + if(context->token_offset < context->n_tokens) + tag = context->tokens[context->token_offset]->tag; + return tag; +} + +static struct aplwc_token * +match(struct aplwc_eval_context *context, enum aplwc_token_tag tag) +{ + struct aplwc_token *tok = NULL; + + if(peek(context) == tag) + tok = context->tokens[context->token_offset++]; + return tok; +} + +static void +emit(struct aplwc_eval_context *context, enum aplwc_ast_tag tag, struct aplwc_ast **ast) +{ + if((*ast) != NULL) + aplwc_free_ast(context->aplwc, *ast); + + *ast = context->aplwc->alloc(sizeof(**ast)); + memset(*ast, 0, sizeof(**ast)); + (*ast)->tag = tag; +} + +static char * +token_text(struct aplwc_eval_context *context, struct aplwc_token *tok) +{ + size_t len = tok->offset_end - tok->offset_start + 1; + char *text = context->aplwc->alloc(len + 1); + memcpy(text, context->text + tok->offset_start, len); + text[len] = 0; + return text; +} + +static void +parse_syscmd(struct aplwc_eval_context *context, struct aplwc_ast **ast) +{ + struct aplwc_token *tok = match(context, APLWC_TOKEN_SYSCMD); + + char *name = token_text(context, tok); + struct aplwc_syscmd *syscmd = aplwc_lookup_syscmd(context->aplwc, name+1); + context->aplwc->free(name); + + if(syscmd){ + emit(context, APLWC_AST_SYSCMD, ast); + (*ast)->data.syscmd.syscmd = syscmd; + (*ast)->data.syscmd.args = aplwc_strdup(context->aplwc, ""); + }else + emit(context, APLWC_AST_ERROR, ast); +} |