--- /dev/null
+#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;
+}