started the parser
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Sun, 9 Oct 2016 09:16:14 +0000 (12:16 +0300)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Sun, 9 Oct 2016 09:16:14 +0000 (12:16 +0300)
src/mparser.cc [new file with mode: 0644]
src/mparser.h [new file with mode: 0644]

diff --git a/src/mparser.cc b/src/mparser.cc
new file mode 100644 (file)
index 0000000..b39df1a
--- /dev/null
@@ -0,0 +1,191 @@
+#include <vector>
+#include "mparser.h"
+#include "machine.h"
+
+enum ASTNodeType {
+       AST_MACHINE,
+       AST_GEAR,
+       AST_STATEMENT,
+       AST_IDENT,
+       AST_NUMBER,
+       AST_VECTOR,
+       AST_FCALL
+};
+
+struct ASTNode {
+       std::vector<ASTNode*> children;
+};
+
+struct ParserState {
+       FILE *fp;
+       const char *fname;
+       Machine *mcn;
+
+       int nextc;
+       int savedc;
+
+       bool error;
+};
+
+static bool machine(ParserState *ps);
+static bool expect(ParserState *ps, char c);
+static bool expect_alpha(ParserState *ps);
+static bool expect_digit(ParserState *ps);
+static bool expect_alnum(ParserState *ps);
+static bool match_str(ParserState *ps, const char *str);
+static bool match_char(ParserState *ps, char c);
+static bool mstatement(ParserState *ps);
+static bool ident(ParserState *ps, std::string *s);
+static bool gear(ParserState *ps);
+static bool expression(ParserState *ps);
+
+static bool nextchar(ParserState *ps);
+static void putback(ParserState *ps, char c);
+
+bool parse_machine(Machine *mcn, const char *fname)
+{
+       FILE *fp = fopen(fname, "rb");
+       if(!fp) return false;
+
+       ParserState pstate;
+       pstate.fname = fname;
+       pstate.fp = fp;
+       pstate.mcn = mcn;
+       pstate.savedc = -1;
+       pstate.nextc = fgetc(fp);       // prime the parser
+       pstate.error = false;
+
+       bool res = machine(&pstate);
+       fclose(fp);
+       return res;
+}
+
+static bool machine(ParserState *ps)
+{
+       matchstr(ps, "machine");
+       expect(ps, '{');
+
+       while(mstatement(ps));
+
+       expect(ps, '}');
+       return true;
+}
+
+static bool expect(ParserState *ps, int c)
+{
+       if(c != ps->nextc) {
+               ps->error = true;
+               return false;
+       }
+       nextchar(ps);
+       return true;
+}
+
+static bool expect_alpha(ParserState *ps)
+{
+       if(!isalpha(ps->nextc)) {
+               ps->error = true;
+               return false;
+       }
+       nextchar(ps);
+       return true;
+}
+
+static bool expect_digit(ParserState *ps)
+{
+       if(!isdigit(ps->nextc)) {
+               ps->error = true;
+               return false;
+       }
+       nextchar(ps);
+       return true;
+}
+
+static bool expect_alnum(ParserState *ps)
+{
+       if(!isalnum(ps->nextc)) {
+               ps->error = true;
+               return false;
+       }
+       nextchar(ps);
+       return true;
+}
+
+static bool match_str(ParserState *ps, const char *str)
+{
+       while(*str && match_char(ps, *str++));
+       return !feof(ps->fp);
+}
+
+static bool match_char(ParserState *ps, int c)
+{
+       if(ps->nextc != c) {
+               return false;
+       }
+       nextchar(ps);
+       return true;
+}
+
+static bool expression(ParserState *ps);
+
+#define CHECK(x) if(!(x)) return false
+
+static bool mstatement(ParserState *ps)
+{
+       std::string id;
+
+       CHECK(ident(ps, &id));
+       if(id == "gear") {
+               gear(ps);
+       } else {
+               expect(ps, '=');
+               expression(ps);
+       }
+}
+
+static bool expression(ParserState *ps)
+{
+}
+
+static bool ident(ParserState *ps, std::string *s)
+{
+       CHECK(expect_alpha(ps));
+       while(isalnum(ps->nextc) || ps->nextc == '_') {
+               s->append((char)ps->nextc);
+               CHECK(nextchar(ps));
+       }
+       return true;
+}
+
+static bool skip_line(FILE *fp)
+{
+       int c;
+       while((c = fgetc(fp)) != -1 && c != '\n');
+       return c != -1;
+}
+
+static bool nextchar(ParserState *ps)
+{
+       if(ps->savedc != -1) {
+               ps->nextc = ps->savedc;
+               ps->savedc = -1;
+               return true;
+       }
+
+       while((ps->nextc = fgetc(ps->fp)) != -1) {
+               if(ps->nextc == '#') {
+                       CHECK(skip_line(ps->fp));
+               }
+               if(!isspace(ps->nextc)) {
+                       break;
+               }
+       }
+
+       return ps->nextc != -1;
+}
+
+static void putback(ParserState *ps, char c)
+{
+       ps->savedc = ps->nextc;
+       ps->nextc = c;
+}
diff --git a/src/mparser.h b/src/mparser.h
new file mode 100644 (file)
index 0000000..7fa1b6f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MPARSER_H_
+#define MPARSER_H_
+
+#include <stdio.h>
+
+int parse_machine(Machine *mcn, const char *fname);
+
+#endif /* MPARSER_H_ */