/*
* parser.c -- part of ZilUtils/ZilAsm
*
- * Copyright (C) 2016, 2019 Jason Self <j@jxself.org>
+ * Copyright (C) 2016, 2019, 2020 Jason Self <j@jxself.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
#include <string.h> /* strlen */
#include <ctype.h>
#include <string>
+#include <stack>
using namespace std;
#include "header.h"
#include "parser.h"
+#include "directives.h"
extern "C"
{
-#include "directives.h"
#include "opcodes.h"
}
#include "labels.h"
#define isbindigit(c) ((c) == '0' || (c) == '1')
/* !!! TODO !!! */
-#define fatal_error(errmsg) printf(errmsg)
+//#define fatal_error(errmsg) printf(errmsg)
#define PC NULL
-unsigned g_numberOfInstructions = 0;
+unsigned g_number_of_instructions = 0;
+
+unsigned g_currentLineNumber = 0;
+//string g_source_directory;
+bool g_haveErrors = false;
+
+stack<Parsing_Context> g_parsing_contexts;
ZMemblock (*g_codes[MAX_NUMBER_OF_INSTRUCTIONS]);
+string
+build_error_message(const char *message)
+{
+ char buff[300];
+ sprintf(buff, "error at %s%s line %d: %s", g_parsing_contexts.top().current_directory.c_str(),
+ g_parsing_contexts.top().current_file_name.c_str(), g_currentLineNumber, message);
+ return string(buff);
+}
+
+
+void
+fatal_error(const char *errmsg)
+{
+ printf( "%s\n", errmsg);
+ g_haveErrors = true;
+}
+
+
void
checksep (const char *p)
{
if (!*p || iscomment (*p) || isspace (*p))
return;
- fatal_error ("wrong chars");
+ fatal_error (build_error_message ("wrong chars").c_str());
}
Directive_handler f = directive_lookup (a, b - a);
if (!f)
return 0;
- return (*f) (b);
+ return (b-a) + (*f) (b);
}
}
else
{
- fatal_error ("wrong label type");
+ fatal_error (build_error_message("wrong label type").c_str());
}
while (*c++ == ':');
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)
+ bool display_error = false;
+ int len = 0;
+ const char *b = pass_alnums(a);
+ if (b != a)
{
- 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;
+ len = b ? b - a : strlen(a);
+ ZOpcode *op = (ZOpcode *)symtable_lookup2(Opcodes, a, len);
+ if (op)
+ {
+ ZOpcode_flags flags = op->flags;
+ 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:
+ {
+ display_error = true;
+ }
+ }
+
+
+ if (display_error == false)
+ {
+
+ int instruction_size = 1;
+ if (mem_additional)
+ instruction_size += mem_additional->used_size;
+
+ g_codes[g_number_of_instructions] = zmem_init(instruction_size);
+ zmem_putbyte(g_codes[g_number_of_instructions], op->opcode);
+
+ if (mem_additional)
+ {
+ for (int i = 0; i < mem_additional->used_size; ++i)
+ zmem_putbyte(g_codes[g_number_of_instructions],
+ mem_additional->contents[i]);
+ zmem_destroy(mem_additional);
+ }
+
+ ++g_number_of_instructions;
+ return len;
+ }
+ }
+ else
+ {
+ //display_error = true;
+ string message = "wrong line \"" + string(a) + string("\"");
+ fatal_error(build_error_message(message.c_str()).c_str());
+ }
}
- 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)
+ if (display_error)
{
- for (int i = 0; i < mem_additional->used_size; ++i)
- zmem_putbyte (g_codes[g_numberOfInstructions],
- mem_additional->contents[i]);
- zmem_destroy (mem_additional);
+ char buff[300];
+ if (len == 0)
+ len = strlen(a);
+ char *instrcution_name = (char *)malloc(len + 1);
+ memcpy(instrcution_name, a, len);
+ instrcution_name[len] = 0;
+ string message = "instruction " + string(instrcution_name) + string(" is not supported yet");
+ fatal_error(build_error_message(message.c_str()).c_str());
+ free(instrcution_name);
}
- ++g_numberOfInstructions;
- return len;
- }
-
- return 0;
+ return strlen(a);
}
return n; // ..label or assignment
if (n = tryparse_instruction (p))
return n;
- fatal_error ("wrong line");
+ //fatal_error ("wrong line");
}
return 0;
}
#define MAX_LINESIZE 1024
int
-parse_file (const char *filename)
+parse_file (/*const char *filename*/)
{
- FILE *fp = fopen (filename, "r");
- if (!fp)
- fatal_error ("wrong file");
+ if (g_parsing_contexts.size() > 0)
+ {
+ string filename = g_parsing_contexts.top().current_directory + g_parsing_contexts.top().current_file_name;
- //const int MAX_LINESIZE = 1024;
- char line[MAX_LINESIZE];
- int newline_missing = 0;
+ FILE *fp = fopen(filename.c_str(), "r");
+ if (fp)
+ {
- while (fgets (line, MAX_LINESIZE, fp))
- {
- if (newline_missing)
- fatal_error ("line too long");
+ g_currentLineNumber = 0;
- int n = strlen (line);
- if (!n)
- continue;
+ //const int MAX_LINESIZE = 1024;
+ char line[MAX_LINESIZE];
+ int newline_missing = 0;
- parse_line (line);
+ while (g_stopParsing == 0 && fgets(line, MAX_LINESIZE, fp))
+ {
+ ++g_currentLineNumber;
- newline_missing = (line[n - 1] != '\n');
- }
+ if (newline_missing)
+ fatal_error(build_error_message("line too long").c_str());
- fclose (fp);
- return 0;
+ int n = strlen(line);
+ if (!n)
+ continue;
+
+ parse_line(line);
+
+ newline_missing = (line[n - 1] != '\n');
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ string message = string("can't open file ") + filename;
+ fatal_error(message.c_str());
+ }
+
+ g_parsing_contexts.pop();
+ }
+ return 0;
}
/*
void
init_parser ()
{
- g_numberOfInstructions = 0;
+ g_number_of_instructions = 0;
}
+
+
+
void
relase_parser ()
{
- for (int i = 0; i < g_numberOfInstructions; ++i)
+ for (int i = 0; i < g_number_of_instructions; ++i)
{
zmem_destroy (g_codes[i]);
}
- g_numberOfInstructions = 0;
+ g_number_of_instructions = 0;
}