/* * parse.c * Copyright (C) 2013-2015 Mikael Pettersson * * This file is part of pdp10-tools. * * pdp10-tools 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. * * pdp10-tools 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 pdp10-tools. If not, see . */ #include #include #include #include "pdp10-opcodes.h" #include "input.h" /* for struct stmt */ #include "parse.h" #include "scan.h" #include "token.h" static int error(struct scan_state *scan_state, const char *msg, enum token token, const union token_attribute *token_attr) { fprintf(stderr, "%s: %s line %u: syntax error: %s; current token is ", scan_state->progname, scan_state->filename, scan_state->linenr, msg); token_print(stderr, token, token_attr); fprintf(stderr, "\n"); return -1; } static int parse_dot_file(struct scan_state *scan_state, struct stmt *stmt) { enum token token; union token_attribute token_attr; token = scan_token(scan_state, &token_attr); if (token == T_STRING) { stmt->u.string.text = token_attr.text; token = scan_token(scan_state, &token_attr); if (token == T_NEWLINE) { stmt->tag = S_DOT_FILE; return 1; } } return error(scan_state, "junk after .file directive", token, &token_attr); } static int parse_dot_globl(struct scan_state *scan_state, struct stmt *stmt) { enum token token; union token_attribute token_attr; token = scan_token(scan_state, &token_attr); if (token == T_SYMBOL) { stmt->u.symbol.name = token_attr.text; token = scan_token(scan_state, &token_attr); if (token == T_NEWLINE) { stmt->tag = S_DOT_GLOBL; return 1; } } return error(scan_state, "junk after .globl directive", token, &token_attr); } /* for now, accepts: .size ,.- */ static int parse_dot_size(struct scan_state *scan_state, struct stmt *stmt) { enum token token; union token_attribute token_attr; token = scan_token(scan_state, &token_attr); if (token == T_SYMBOL) { stmt->u.symbol.name = token_attr.text; token = scan_token(scan_state, &token_attr); if (token == T_COMMA) { token = scan_token(scan_state, &token_attr); if (token == T_DOT) { token = scan_token(scan_state, &token_attr); if (token == T_MINUS) { token = scan_token(scan_state, &token_attr); if (token == T_SYMBOL && strcmp(token_attr.text, stmt->u.symbol.name) == 0) { token = scan_token(scan_state, &token_attr); if (token == T_NEWLINE) { stmt->tag = S_DOT_SIZE; return 1; } } } } } } return error(scan_state, "junk after .size directive", token, &token_attr); } static int parse_dot_text(struct scan_state *scan_state, struct stmt *stmt) { enum token token; union token_attribute token_attr; token = scan_token(scan_state, &token_attr); if (token == T_NEWLINE) { stmt->tag = S_DOT_TEXT; return 1; } return error(scan_state, "junk after .text directive", token, &token_attr); } static int parse_dot_type(struct scan_state *scan_state, struct stmt *stmt) { enum token token; union token_attribute token_attr; token = scan_token(scan_state, &token_attr); if (token == T_SYMBOL) { stmt->u.symbol.name = token_attr.text; token = scan_token(scan_state, &token_attr); if (token == T_COMMA) { token = scan_token(scan_state, &token_attr); if (token == T_AT) { token = scan_token(scan_state, &token_attr); if (token == T_SYMBOL && strcmp(token_attr.text, "function") == 0) { token = scan_token(scan_state, &token_attr); if (token == T_NEWLINE) { stmt->tag = S_DOT_TYPE_FUNCTION; return 1; } } } } } return error(scan_state, "junk after .type directive", token, &token_attr); } /* * Recognize: * *