Value Parse() { Value v = ParseFactor(); Gobble('LF'); Expect('EOF'); return v; }
Value Parse() { Value v = ParseFactor(); Gobble(T_LINEFEED); Expect(T_ENDOFFILE); return v; }
Value ParseFactor() { switch (lex.token) { case 'INT': { int i = atoi(lex.sattr.c_str()); lex.Next(); return Value(i); } case 'FLT': { double f = atof(lex.sattr.c_str()); lex.Next(); return Value((float)f); } case 'STR': { string s = lex.sattr; lex.Next(); auto str = g_vm->NewString(s); allocated.push_back(str); return Value(str); } case 'NIL': { lex.Next(); return Value(0, V_NIL); } case '-': { lex.Next(); Value v = ParseFactor(); switch (v.type) { case V_INT: v.ival *= -1; break; case V_FLOAT: v.fval *= -1; break; default: lex.Error("numeric value expected"); } return v; } case '[': { lex.Next(); Gobble('LF'); vector<Value> elems; if (lex.token == ']') lex.Next(); else { for (;;) { elems.push_back(ParseFactor()); bool haslf = lex.token == 'LF'; if (haslf) lex.Next(); if (lex.token == ']') break; if (!haslf) Expect(','); } lex.Next(); } int type = -1; if (lex.token == ':') { lex.Next(); string sname = lex.sattr; Expect('ID'); size_t reqargs = 0; int idx = g_vm->StructIdx(sname, reqargs); if (idx >= 0) // if unknown type, becomes regular vector { while (elems.size() < reqargs) { elems.push_back(Value(0, V_NIL)); } // pad with NIL if current type has more fields while (elems.size() > reqargs) { elems.back().DEC(); elems.pop_back(); } // drop elements if current type has less fields type = idx; } } auto vec = g_vm->NewVector(elems.size(), type); allocated.push_back(vec); for (auto &e : elems) vec->push(e.INC()); return Value(vec); } default: lex.Error("illegal start of expression: " + lex.TokStr()); return Value(); } }