/*
* 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:
*
*