X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=zilasm%2Fparser.c;fp=zilasm%2Fparser.c;h=7f8af7ec16fe1932c30e2c5c74cc23e4271a9a74;hb=fd453701e368225dd15e9df2e5b1752aebe454e8;hp=0000000000000000000000000000000000000000;hpb=093225c7cb864aaa31567969301eb5f36bd9a5f4;p=zilutils.git diff --git a/zilasm/parser.c b/zilasm/parser.c new file mode 100644 index 0000000..7f8af7e --- /dev/null +++ b/zilasm/parser.c @@ -0,0 +1,171 @@ +/* + * parser.c -- part of ZilUtils/ZilAsm + * + * Copyright (C) 2016 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 + */ + +#include /* fopen, fgets */ +#include /* strlen */ + +#include "parser.h" +#include "directives.h" +#include "opcodes.h" +#include "labels.h" + +#define iscomment(c) ((c) == '#') +#define isbindigit(c) ((c) == '0' || (c) == '1') + +/* !!! TODO !!! */ +#define fatal_error(errmsg) +#define PC NULL + +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_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); + ZOpcode *op = symtable_lookup2(Opcodes, a, b - a); + if (!op) return 0; + ZOpcode_flags flags = op->flags; + /* !!! TODO !!! */ + 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; +} + +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'); + } + + close(fp); +} + +/* + +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) +} + + +*/