void Expect(int t) { if (lex.token != t) lex.Error(lex.TokStr(t) + " expected, found: " + lex.TokStr()); lex.Next(); }
Value ParseElems(TType end, type_elem_t typeoff, int numelems = -1) // Vector or struct. { Gobble(T_LINEFEED); vector<Value> elems; auto &ti = g_vm->GetTypeInfo(typeoff); if (lex.token == end) lex.Next(); else { for (;;) { if ((int)elems.size() == numelems) { ParseFactor(TYPE_ELEM_ANY).DECRT(); // Ignore the value. } else { elems.push_back(ParseFactor(ti.t == V_VECTOR ? ti.subt : ti.elems[elems.size()])); } bool haslf = lex.token == T_LINEFEED; if (haslf) lex.Next(); if (lex.token == end) break; if (!haslf) Expect(T_COMMA); } lex.Next(); } if (numelems >= 0) { while ((int)elems.size() < numelems) { switch (ti.elems[elems.size()]) { case V_INT: elems.push_back(Value(0)); break; case V_FLOAT: elems.push_back(Value(0.0f)); break; case V_NIL: elems.push_back(Value()); break; default: lex.Error("no default value possible for missing struct elements"); } } } auto vec = g_vm->NewVector((int)elems.size(), (int)elems.size(), ti); vec->Inc(); allocated.push_back(vec); int i = 0; for (auto &e : elems) vec->At(i++) = e; return Value(vec); }
void ExpectType(ValueType given, ValueType needed) { if (given != needed) { lex.Error(string("type ") + BaseTypeName(needed) + " required, " + BaseTypeName(given) + " given"); } }
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(); } }
Value ParseFactor(type_elem_t typeoff) { auto &ti = g_vm->GetTypeInfo(typeoff); auto vt = ti.t; // TODO: also support boxed parsing as V_ANY. // means boxing int/float, deducing runtime type for V_VECTOR, and finding the existing struct. switch (lex.token) { case T_INT: { ExpectType(V_INT, vt); int i = atoi(lex.sattr.c_str()); lex.Next(); return Value(i); } case T_FLOAT: { ExpectType(V_FLOAT, vt); double f = atof(lex.sattr.c_str()); lex.Next(); return Value((float)f); } case T_STR: { ExpectType(V_STRING, vt); string s = lex.sattr; lex.Next(); auto str = g_vm->NewString(s); str->Inc(); allocated.push_back(str); return Value(str); } case T_NIL: { ExpectType(V_NIL, vt); lex.Next(); return Value(); } case T_MINUS: { lex.Next(); Value v = ParseFactor(typeoff); switch (typeoff) { case TYPE_ELEM_INT: v.setival(v.ival() * -1); break; case TYPE_ELEM_FLOAT: v.setfval(v.fval() * -1); break; default: lex.Error("unary minus: numeric value expected"); } return v; } case T_LEFTBRACKET: { ExpectType(V_VECTOR, vt); lex.Next(); return ParseElems(T_RIGHTBRACKET, typeoff); } case T_IDENT: { ExpectType(V_STRUCT, vt); string sname = lex.sattr; lex.Next(); Expect(T_LEFTCURLY); auto name = g_vm->StructName(ti); if (name != sname) lex.Error("struct type " + name + " required, " + sname + " given"); return ParseElems(T_RIGHTCURLY, typeoff, ti.len); } default: lex.Error("illegal start of expression: " + lex.TokStr()); return Value(); } }