X-Git-Url: https://jxself.org/git/?p=zilutils.git;a=blobdiff_plain;f=zilasm%2Fparser.cpp;fp=zilasm%2Fparser.cpp;h=31e257fd444623db965366e8b293d130f8b79032;hp=0000000000000000000000000000000000000000;hb=82b0f84ab797141758929d16894d42e12ef79af7;hpb=37d32bd49e745a5c1686b6495f60172b24222361 diff --git a/zilasm/parser.cpp b/zilasm/parser.cpp new file mode 100644 index 0000000..31e257f --- /dev/null +++ b/zilasm/parser.cpp @@ -0,0 +1,313 @@ +/* + * parser.c -- part of ZilUtils/ZilAsm + * + * Copyright (C) 2016, 2019 Jason Self + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +#include +#include /* fopen, fgets */ +#include /* strlen */ +#include +#include +using namespace std; + + +#include "header.h" +#include "parser.h" + +extern "C" +{ +#include "directives.h" +#include "opcodes.h" +} +#include "labels.h" +#include "string_table.h" + + +#define iscomment(c) ((c) == ';') +#define isbindigit(c) ((c) == '0' || (c) == '1') + +/* !!! TODO !!! */ +#define fatal_error(errmsg) printf(errmsg) +#define PC NULL + +unsigned g_numberOfInstructions = 0; + + +ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]); + + +void +checksep (const char *p) +{ + if (!*p || iscomment (*p) || isspace (*p)) + return; + fatal_error ("wrong chars"); +} + + +const char * +pass_spaces (const char *p) +{ + while (p && isspace (*p)) + p++; + return (p && *p) ? p : NULL; +} + + +const char * +pass_alnums (const char *p) +{ + while (p && isalnum (*p)) + p++; + return (p && *p) ? p : NULL; +} + + +int tryparse_instruction (const char *a); + +int +tryparse_directive (const char *p) +{ + if (*p != '.') + return 0; + const char *a = p + 1; + const char *b = pass_alnums (a); + checksep (b); + Directive_handler f = directive_lookup (a, b - a); + if (!f) + return 0; + return (*f) (b); +} + + +int +tryparse_assignment (const char *a, const char *b, const char *c) +{ + return 0; +} + + +int +tryparse_label (const char *a, const char *b, const char *c) +{ + if (*(c + 1) != ':') + { + symtable_add2 (Local_labels, a, b - a, PC); + } + else if (*(c + 2) != ':') + { + symtable_add2 (Global_labels, a, b - a, PC); + } + else + { + fatal_error ("wrong label type"); + } + + while (*c++ == ':'); + if (*c && ((c = pass_spaces (c)) != NULL) && *c) + return tryparse_instruction (c); + return 1; +} + + +int +tryparse_name (const char *a) +{ + const char *b = pass_alnums (a); + const char *c = pass_spaces (b); + + if (!c) + return 0; + if (*c == '=') + return tryparse_assignment (a, b, c + 1); + if (*c == ':') + return tryparse_label (a, b, c); + return 0; +} + + +int +tryparse_instruction (const char *a) +{ + const char *b = pass_alnums (a); + if (b != a) + { + int len = b ? b - a : strlen (a); + ZOpcode *op = (ZOpcode *) symtable_lookup2 (Opcodes, a, len); + if (!op) + return 0; + ZOpcode_flags flags = op->flags; + /* !!! TODO !!! */ + + + ZMemblock *mem_additional = NULL; + + switch (op->opcode) + { + case Opcode_CRLF: + case Opcode_PRINT: + case Opcode_QUIT: + break; + + case Opcode_PRINTI: + case Opcode_PRINTR: + { + char *p = (char *) a + len; + p = (char *) pass_spaces (p); + if (*p == '\"') + { + p++; + string str; + while (*p != '\"') + { + str += *p; + ++p; + } + len = p - a; + mem_additional = + String_table::encrypt_string (str.c_str (), NULL); + } + break; + } + default: + fatal_error ("error! instruction not supported"); + return 0; + } + + int instruction_size = 1; + if (mem_additional) + instruction_size += mem_additional->used_size; + //printf("instruction %s", a); + + g_codes[g_numberOfInstructions] = zmem_init (instruction_size); + zmem_putbyte (g_codes[g_numberOfInstructions], op->opcode); + + if (mem_additional) + { + for (int i = 0; i < mem_additional->used_size; ++i) + zmem_putbyte (g_codes[g_numberOfInstructions], + mem_additional->contents[i]); + zmem_destroy (mem_additional); + } + + ++g_numberOfInstructions; + return len; + } + + return 0; +} + + +/* + * Line can be one from: Comment, Global label, Local label, Directive, Name=Value, Instruction + */ +int +parse_line (const char *p) +{ + for (; *p; p++) + { + char c = *p; + int n; + if (isspace (c)) + continue; + if (iscomment (c)) + return 0; + if (n = tryparse_directive (p)) + return n; + if (n = tryparse_name (p)) + return n; // ..label or assignment + if (n = tryparse_instruction (p)) + return n; + fatal_error ("wrong line"); + } + return 0; +} + +#define MAX_LINESIZE 1024 + +int +parse_file (const char *filename) +{ + FILE *fp = fopen (filename, "r"); + if (!fp) + fatal_error ("wrong file"); + + //const int MAX_LINESIZE = 1024; + char line[MAX_LINESIZE]; + int newline_missing = 0; + + while (fgets (line, MAX_LINESIZE, fp)) + { + if (newline_missing) + fatal_error ("line too long"); + + int n = strlen (line); + if (!n) + continue; + + parse_line (line); + + newline_missing = (line[n - 1] != '\n'); + } + + fclose (fp); + return 0; +} + +/* + +line_passed() { + skip_spaces(); + return (current_token == LINE_END || current_token == LINE_COMMENT); +} + +if (line_passed()) continue; +if (current_token == DIRECTIVE) { + if (!try_next_token(NAME)) + fatal_error("directive contains incorrect chars") + handler = get_directive_handler(current_token); + if (!handler) + fatal error("unknown directive"); + (*handler)(remaining_line); + if (line_passed()) continue; + fatal_error("unexpected line tail"); +} else if (current_token == NAME) { + skip_spaces(); + if (current_token == ASSIGNMENT) +} + + +*/ + + +void +init_parser () +{ + g_numberOfInstructions = 0; +} + + +void +relase_parser () +{ + for (int i = 0; i < g_numberOfInstructions; ++i) + { + zmem_destroy (g_codes[i]); + } + g_numberOfInstructions = 0; +}