/* Aplwc - A Programming Language With Constraints * * Copyright (C) 2026 Peter Mikkelsen * * 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 . */ #include #include #include #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); }