Node<TypeNode>::Link TypeParser::type() { skip(); // Skip "type" expect(TT::IDENTIFIER, "Expected identifier after 'type' token"); Node<TypeNode>::Link tn; Token identTok = current(); skip(); if (accept(TT::INHERITS)) { skip(); if (accept(TT::FROM)) skip(); // Having "from" after "inherits" is optional tn = Node<TypeNode>::make(identTok.data, getTypeList()); } else { tn = Node<TypeNode>::make(identTok.data); } tn->setTrace(identTok.trace); expect(TT::DO, "Expected type body"); skip(); while (!accept(TT::END)) { if (accept(TT::FILE_END)) { skip(-1); // Go back to get a prettier trace throw Error("SyntaxError", "Type body is not closed by 'end'", current().trace); } bool isStatic = false; bool isForeign = false; Visibility visibility = INVALID; // Expect to see a visibility_specifier or static or foreign while (accept(TT::PUBLIC) || accept(TT::PRIVATE) || accept(TT::PROTECT) || accept(TT::STATIC) || accept(TT::FOREIGN)) { if (accept(TT::STATIC)) { if (isStatic == true) throw Error("SyntaxError", "Cannot specify 'static' more than once", current().trace); isStatic = true; } else if (accept(TT::FOREIGN)) { if (isForeign == true) throw Error("SyntaxError", "Cannot specify 'foreign' more than once", current().trace); isForeign = true; } else { if (visibility != INVALID) throw Error("SyntaxError", "Cannot have more than one visibility specifier", current().trace); visibility = fromToken(current()); } skip(); } // Handle things that go in the body if (accept(TT::CONSTR)) { if (isStatic) throw Error("SyntaxError", "Constructors can't be static", current().trace); tn->addChild(constructor(visibility, isForeign)); } else if (accept(TT::METHOD)) { if (visibility == INVALID) throw Error("SyntaxError", "Methods require a visibility specifier", current().trace); tn->addChild(method(visibility, isStatic, isForeign)); } else { if (isForeign) throw Error("SyntaxError", "Member fields can't be foreign", current().trace); tn->addChild(member(visibility, isStatic)); expectSemi(); } } return tn; }
template<> int fromToken<double>(double * dst, int size, int stride, const std::string& src){ return fromToken(dst,size,stride, src, "0123456789-+.","%lg"); }
template<> int fromToken<int>(int * dst, int size, int stride, const std::string& src){ return fromToken(dst,size,stride, src, "0123456789-+","%i"); }
template<> int fromToken<float>(float * dst, int size, int stride, const std::string& src){ return fromToken(dst,size,stride, src, "0123456789-+.","%g"); }
template<> int fromToken<bool>(bool * dst, int size, int stride, const std::string& src){ return fromToken(dst,size,stride, src, "01","%hhi"); }