void Procedure::checkOverride(Procedure *superProcedure){ if(overriding && !superProcedure){ ecCharToCharStack(name, mn); compilerError(dToken, "%s was declared ✒️ but does not override anything.", mn); } else if(!overriding && superProcedure){ ecCharToCharStack(name, mn); compilerError(dToken, "If you want to override %s add ✒️.", mn); } }
void Package::loadInto(Package *destinationPackage, EmojicodeChar ns, const Token *errorToken) const { for (auto exported : exportedTypes_) { Type type = typeNothingness; if (destinationPackage->fetchRawType(exported.name, ns, false, nullptr, &type)) { ecCharToCharStack(ns, nss); ecCharToCharStack(exported.name, tname); compilerError(errorToken, "Package %s could not be loaded into namespace %s of package %s: %s collides with a type of the same name in the same namespace.", name(), nss, destinationPackage->name(), tname); } destinationPackage->registerType(exported.type, exported.name, ns, false); } }
void reportProcedureInformation(Procedure *p, ReturnManner returnm, bool last, TypeContext tc){ ecCharToCharStack(p->name, nameString); printf("{"); printf("\"name\": \"%s\",", nameString); if (returnm == Return) { reportType("returnType", p->returnType, false, tc); } else if (returnm == CanReturnNothingness) { printf("\"canReturnNothingness\": true,"); } reportGenericArguments(p->genericArgumentVariables, p->genericArgumentConstraints, 0, tc); reportDocumentation(p->documentationToken); printf("\"arguments\": ["); for (int i = 0; i < p->arguments.size(); i++) { printf("{"); Variable variable = p->arguments[i]; const char *varname = variable.name->value.utf8CString(); reportType("type", variable.type, false, tc); printf("\"name\":"); printJSONStringToFile(varname, stdout); printf("}%s", i + 1 == p->arguments.size() ? "" : ","); delete [] varname; } printf("]"); printf("}%s", last ? "" : ","); }
void Procedure::deprecatedWarning(const Token *callToken) { if (deprecated) { ecCharToCharStack(name, mn); if (documentationToken) { char *documentation = documentationToken->value.utf8CString(); compilerWarning(callToken, "%s is deprecated. Please refer to the documentation for further information:\n%s", mn, documentation); delete [] documentation; } else { compilerWarning(callToken, "%s is deprecated.", mn); } } }
void Procedure::checkPromises(Procedure *superProcedure, const char *on, Type contextType) { if(superProcedure->final){ ecCharToCharStack(this->name, mn); compilerError(this->dToken, "%s of %s was marked 🔏.", on, mn); } if (!this->returnType.compatibleTo(superProcedure->returnType, contextType)) { ecCharToCharStack(this->name, mn); auto supername = superProcedure->returnType.toString(contextType, true); auto thisname = this->returnType.toString(contextType, true); compilerError(this->dToken, "Return type %s of %s is not compatible with the return type %s of its %s.", thisname.c_str(), mn, supername.c_str(), on); } if(superProcedure->arguments.size() != this->arguments.size()){ ecCharToCharStack(this->name, mn); compilerError(this->dToken, "%s expects %s arguments than its %s.", mn, (superProcedure->arguments.size() < this->arguments.size()) ? "more" : "less", on); } for (uint8_t i = 0; i < superProcedure->arguments.size(); i++) { //other way, because the method may define a more generic type if (!superProcedure->arguments[i].type.compatibleTo(this->arguments[i].type, contextType)) { auto supertype = superProcedure->arguments[i].type.toString(contextType, true); auto thisname = this->arguments[i].type.toString(contextType, true); compilerError(superProcedure->dToken, "Type %s of argument %d is not compatible with its %s argument type %s.", thisname.c_str(), i + 1, on, supertype.c_str()); } } }
void PackageParser::parseEnum(const EmojicodeString &documentation, bool exported) { EmojicodeChar name, enamespace; parseAndValidateNewTypeName(&name, &enamespace); Enum *eenum = new Enum(name, package_, documentation); package_->registerType(Type(eenum, false), name, enamespace, exported); auto token = stream_.consumeToken(IDENTIFIER); if (token.value[0] != E_GRAPES) { ecCharToCharStack(token.value[0], s); throw CompilerErrorException(token, "Expected 🍇 but found %s instead.", s); } while (stream_.nextTokenIsEverythingBut(E_WATERMELON)) { eenum->addValueFor(stream_.consumeToken().value[0]); } stream_.consumeToken(IDENTIFIER); }
void PackageParser::parseProtocol(const EmojicodeString &documentation, const Token &theToken, bool exported) { EmojicodeChar name, enamespace; parseAndValidateNewTypeName(&name, &enamespace); auto protocol = new Protocol(name, package_, documentation, theToken); parseGenericArgumentList(protocol, Type(protocol, false)); protocol->finalizeGenericArguments(); auto token = stream_.consumeToken(IDENTIFIER); if (token.value[0] != E_GRAPES) { ecCharToCharStack(token.value[0], s); throw CompilerErrorException(token, "Expected 🍇 but found %s instead.", s); } auto protocolType = Type(protocol, false); package_->registerType(protocolType, name, enamespace, exported); while (stream_.nextTokenIsEverythingBut(E_WATERMELON)) { auto documentation = parseDocumentationToken(); auto token = stream_.consumeToken(IDENTIFIER); auto deprecated = Attribute<E_WARNING_SIGN>().parse(&stream_); if (token.value[0] != E_PIG) { throw CompilerErrorException(token, "Only method declarations are allowed inside a protocol."); } auto methodName = stream_.consumeToken(IDENTIFIER); auto method = new Method(methodName.value[0], PUBLIC, false, nullptr, package_, methodName.position(), false, documentation, deprecated.set()); auto a = parseArgumentList(method, protocolType); auto b = parseReturnType(method, protocolType); if (a || b) { protocol->setUsesSelf(); } protocol->addMethod(method); } stream_.consumeToken(IDENTIFIER); }
void PackageParser::parseClassBody(Class *eclass, std::set<EmojicodeChar> *requiredInitializers, bool allowNative) { allowNative = allowNative && package_->requiresBinary(); auto token = stream_.consumeToken(IDENTIFIER); if (token.value[0] != E_GRAPES) { ecCharToCharStack(token.value[0], s); throw CompilerErrorException(token, "Expected 🍇 but found %s instead.", s); } while (stream_.nextTokenIsEverythingBut(E_WATERMELON)) { auto documentation = parseDocumentationToken(); auto deprecated = Attribute<E_WARNING_SIGN>().parse(&stream_); auto final = Attribute<E_LOCK_WITH_INK_PEN>().parse(&stream_); AccessLevel accessLevel = readAccessLevel(&stream_); auto override = Attribute<E_BLACK_NIB>().parse(&stream_); auto staticOnType = Attribute<E_RABBIT>().parse(&stream_); auto required = Attribute<E_KEY>().parse(&stream_); auto canReturnNothingness = Attribute<E_CANDY>().parse(&stream_); auto token = stream_.consumeToken(IDENTIFIER); switch (token.value[0]) { case E_SHORTCAKE: { staticOnType.disallow(); override.disallow(); final.disallow(); required.disallow(); canReturnNothingness.disallow(); deprecated.disallow(); auto &variableName = stream_.consumeToken(VARIABLE); auto type = parseAndFetchType(Type(eclass), GenericTypeVariables); eclass->addInstanceVariable(Argument(variableName, type)); } break; case E_CROCODILE: { staticOnType.disallow(); override.disallow(); final.disallow();
void Procedure::parseBody(bool allowNative) { if(nextToken()->value[0] == E_RADIO){ const Token *t = consumeToken(IDENTIFIER); if(!allowNative){ compilerError(t, "Native code is not allowed in this context."); } native = true; return; } const Token *token = consumeToken(IDENTIFIER); if (token->value[0] != E_GRAPES){ ecCharToCharStack(token->value[0], c); compilerError(token, "Expected 🍇 but found %s instead.", c); } firstToken = currentToken; int d = 0; while ((token = until(E_WATERMELON, E_GRAPES, &d)) != nullptr); }
void PackageParser::reservedEmojis(const Token &token, const char *place) const { EmojicodeChar name = token.value[0]; switch (name) { case E_CUSTARD: case E_DOUGHNUT: case E_SHORTCAKE: case E_CHOCOLATE_BAR: case E_COOKING: case E_COOKIE: case E_LOLLIPOP: case E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS: case E_CLOCKWISE_RIGHTWARDS_AND_LEFTWARDS_OPEN_CIRCLE_ARROWS_WITH_CIRCLED_ONE_OVERLAY: case E_RED_APPLE: case E_BEER_MUG: case E_CLINKING_BEER_MUGS: case E_LEMON: case E_GRAPES: case E_STRAWBERRY: case E_BLACK_SQUARE_BUTTON: case E_LARGE_BLUE_DIAMOND: case E_DOG: case E_HIGH_VOLTAGE_SIGN: case E_CLOUD: case E_BANANA: case E_HONEY_POT: case E_SOFT_ICE_CREAM: case E_ICE_CREAM: case E_TANGERINE: case E_WATERMELON: case E_AUBERGINE: case E_SPIRAL_SHELL: case E_BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE: case E_BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE_WITH_VERTICAL_BAR: { ecCharToCharStack(name, nameString); throw CompilerErrorException(token, "%s is reserved and cannot be used as %s name.", nameString, place); } } }
void stringAppendEc(EmojicodeChar c, std::string *string){ ecCharToCharStack(c, sc); string->append(sc); }
Type Type::parseAndFetchType(Type contextType, EmojicodeChar theNamespace, TypeDynamism dynamism, bool *dynamicType){ if (dynamicType) { *dynamicType = false; } if (dynamism & AllowGenericTypeVariables && contextType.type == TT_CLASS && (nextToken()->type == VARIABLE || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE))) { if (dynamicType) { *dynamicType = true; } bool optional = false; const Token *variableToken = consumeToken(); if (variableToken->value[0] == E_CANDY) { variableToken = consumeToken(); optional = true; } auto it = contextType.eclass->ownGenericArgumentVariables.find(variableToken->value); if (it != contextType.eclass->ownGenericArgumentVariables.end()){ Type type = it->second; type.optional = optional; return type; } else { compilerError(variableToken, "No such generic type variable \"%s\".", variableToken->value.utf8CString()); } } else if (nextToken()->value[0] == E_RAT) { const Token *token = consumeToken(); if(!(dynamism & AllowDynamicClassType)){ compilerError(token, "🐀 not allowed here."); } if (dynamicType) { *dynamicType = true; } return contextType; } else if (nextToken()->value[0] == E_GRAPES || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE)) { bool optional = false; if (nextToken()->value[0] == E_CANDY) { consumeToken(); optional = true; } consumeToken(); Type t(TT_CALLABLE, optional); t.arguments = 0; t.genericArguments.push_back(typeNothingness); while (!(nextToken()->type == IDENTIFIER && (nextToken()->value[0] == E_WATERMELON || nextToken()->value[0] == E_RIGHTWARDS_ARROW))) { t.arguments++; t.genericArguments.push_back(parseAndFetchType(contextType, theNamespace, dynamism, nullptr)); } if(nextToken()->type == IDENTIFIER && nextToken()->value[0] == E_RIGHTWARDS_ARROW){ consumeToken(); t.genericArguments[0] = parseAndFetchType(contextType, theNamespace, dynamism, nullptr); } const Token *token = consumeToken(IDENTIFIER); if (token->value[0] != E_WATERMELON) { compilerError(token, "Expected 🍉."); } return t; } else { EmojicodeChar typeName, typeNamespace; bool optional, existent; const Token *token = parseTypeName(&typeName, &typeNamespace, &optional, theNamespace); Type type = fetchRawType(typeName, typeNamespace, optional, token, &existent); if (!existent) { ecCharToCharStack(typeName, nameString); ecCharToCharStack(typeNamespace, namespaceString); compilerError(token, "Could not find type %s in enamespace %s.", nameString, namespaceString); } type.parseGenericArguments(contextType, theNamespace, dynamism, token); return type; } }
void report(Package *package){ std::list<Enum *> enums; std::list<Class *> classes; std::list<Protocol *> protocols; for (auto exported : package->exportedTypes()) { switch (exported.type.type) { case TT_CLASS: classes.push_back(exported.type.eclass); break; case TT_ENUM: enums.push_back(exported.type.eenum); break; case TT_PROTOCOL: protocols.push_back(exported.type.protocol); break; default: break; } } bool printedClass = false; printf("{"); printf("\"classes\": ["); for(auto eclass : classes){ if (printedClass) { putchar(','); } printedClass = true; printf("{"); ecCharToCharStack(eclass->name, className); printf("\"name\": \"%s\",", className); reportGenericArguments(eclass->ownGenericArgumentVariables, eclass->genericArgumentConstraints, eclass->superGenericArguments.size(), TypeContext(eclass)); reportDocumentation(eclass->documentationToken); if (eclass->superclass) { ecCharToCharStack(eclass->superclass->name, superClassName); printf("\"superclass\": {\"package\": \"%s\", \"name\": \"%s\"},", eclass->superclass->package->name(), superClassName); } printf("\"methods\": ["); for(size_t i = 0; i < eclass->methodList.size(); i++){ Method *method = eclass->methodList[i]; reportProcedureInformation(method, Return, i + 1 == eclass->methodList.size(), TypeContext(eclass, method)); } printf("],"); printf("\"initializers\": ["); for(size_t i = 0; i < eclass->initializerList.size(); i++){ Initializer *initializer = eclass->initializerList[i]; reportProcedureInformation(initializer, initializer->canReturnNothingness ? CanReturnNothingness : NoReturn, i + 1 == eclass->initializerList.size(), TypeContext(eclass, initializer)); } printf("],"); printf("\"classMethods\": ["); for(size_t i = 0; i < eclass->classMethodList.size(); i++){ ClassMethod *classMethod = eclass->classMethodList[i]; reportProcedureInformation((Procedure *)classMethod, Return, eclass->classMethodList.size() == i + 1, TypeContext(eclass, classMethod)); } printf("],"); printf("\"conformsTo\": ["); for(size_t i = 0; i < eclass->protocols().size(); i++){ Protocol *protocol = eclass->protocols()[i]; reportType(nullptr, Type(protocol, false), i + 1 == eclass->protocols().size(), TypeContext(eclass)); } printf("]}"); } printf("],"); printf("\"enums\": ["); bool printedEnum = false; for(auto eenum : enums){ if (printedEnum) { putchar(','); } printf("{"); printedEnum = true; ecCharToCharStack(eenum->name, enumName); printf("\"name\": \"%s\",", enumName); reportDocumentation(eenum->documentationToken); bool printedValue = false; printf("\"values\": ["); for(auto it : eenum->map){ ecCharToCharStack(it.first, value); if (printedValue){ putchar(','); } printf("\"%s\"", value); printedValue = true; } printf("]}"); } printf("],"); printf("\"protocols\": ["); bool printedProtocol = false; for(auto protocol : protocols){ if (printedProtocol) { putchar(','); } printedProtocol = true; printf("{"); ecCharToCharStack(protocol->name, protocolName); printf("\"name\": \"%s\",", protocolName); reportDocumentation(protocol->documentationToken); printf("\"methods\": ["); for(size_t i = 0; i < protocol->methods().size(); i++){ Method *method = protocol->methods()[i]; reportProcedureInformation((Procedure *)method, Return, i + 1 == protocol->methods().size(), TypeContext(Type(protocol, false))); } printf("]}"); } printf("]"); printf("}"); }
void report(const char *packageName){ bool printedClass = false; printf("{"); printf("\"classes\": ["); for(auto eclass : classes){ if (strcmp(eclass->package->name, packageName) != 0) { continue; } if (printedClass) { putchar(','); } printedClass = true; printf("{"); ecCharToCharStack(eclass->name, className); printf("\"name\": \"%s\",", className); reportDocumentation(eclass->documentationToken); if (eclass->superclass) { ecCharToCharStack(eclass->superclass->name, superClassName); printf("\"superclass\": {\"package\": \"%s\", \"name\": \"%s\"},", eclass->superclass->package->name, superClassName); } printf("\"methods\": ["); for(size_t i = 0; i < eclass->methodList.size(); i++){ Method *method = eclass->methodList[i]; reportProcedureInformation(method, Return, i + 1 == eclass->methodList.size()); } printf("],"); printf("\"initializers\": ["); for(size_t i = 0; i < eclass->initializerList.size(); i++){ Initializer *initializer = eclass->initializerList[i]; reportProcedureInformation(initializer, initializer->canReturnNothingness ? CanReturnNothingness : NoReturn, i + 1 == eclass->initializerList.size()); } printf("],"); printf("\"classMethods\": ["); for(size_t i = 0; i < eclass->classMethodList.size(); i++){ ClassMethod *classMethod = eclass->classMethodList[i]; reportProcedureInformation((Procedure *)classMethod, Return, eclass->classMethodList.size() == i + 1); } printf("],"); printf("\"conformsTo\": ["); for(size_t i = 0; i < eclass->protocols().size(); i++){ Protocol *protocol = eclass->protocols()[i]; reportType(nullptr, Type(protocol, false), i + 1 == eclass->protocols().size()); } printf("]}"); } printf("],"); printf("\"enums\": ["); bool printedEnum = false; for(auto it : enumsRegister){ Enum *eenum = it.second; if (strcmp(eenum->package.name, packageName) != 0) { continue; } if (printedEnum) { putchar(','); } printf("{"); printedEnum = true; ecCharToCharStack(eenum->name, enumName); printf("\"name\": \"%s\",", enumName); reportDocumentation(eenum->documentationToken); bool printedValue = false; printf("\"values\": ["); for(auto it : eenum->map){ ecCharToCharStack(it.first, value); if (printedValue){ putchar(','); } printf("\"%s\"", value); printedValue = true; } printf("]}"); } printf("],"); printf("\"protocols\": ["); bool printedProtocol = false; for(auto it : protocolsRegister){ Protocol *protocol = it.second; if (strcmp(protocol->package->name, packageName) != 0) { continue; } if (printedProtocol) { putchar(','); } printedProtocol = true; printf("{"); ecCharToCharStack(protocol->name, protocolName); printf("\"name\": \"%s\",", protocolName); reportDocumentation(protocol->documentationToken); printf("\"methods\": ["); for(size_t i = 0; i < protocol->methods().size(); i++){ Method *method = protocol->methods()[i]; reportProcedureInformation((Procedure *)method, Return, i + 1 == protocol->methods().size()); } printf("]}"); } printf("]"); printf("}"); }
void analyzeClass(Type classType, Writer &writer){ auto eclass = classType.eclass; writer.writeEmojicodeChar(eclass->name); if(eclass->superclass){ writer.writeUInt16(eclass->superclass->index); } else { //If the eclass does not have a superclass the own index gets written writer.writeUInt16(eclass->index); } Scope objectScope(true); //Get the ID offset for this eclass by summing up all superclasses instance variable counts uint16_t offset = 0; for(Class *aClass = eclass->superclass; aClass != nullptr; aClass = aClass->superclass){ offset += aClass->instanceVariables.size(); } writer.writeUInt16(eclass->instanceVariables.size() + offset); //Number of methods inclusive superclass writer.writeUInt16(eclass->nextMethodVti); //Number of eclass methods inclusive superclass writer.writeUInt16(eclass->nextClassMethodVti); //Initializer inclusive superclass writer.writeByte(eclass->inheritsContructors ? 1 : 0); writer.writeUInt16(eclass->nextInitializerVti); writer.writeUInt16(eclass->methodList.size()); writer.writeUInt16(eclass->initializerList.size()); writer.writeUInt16(eclass->classMethodList.size()); for (auto var : eclass->instanceVariables) { CompilerVariable *cv = new CompilerVariable(var->type, offset++, 1, false); cv->variable = var; objectScope.setLocalVariable(var->name, cv); } pushScope(&objectScope); for (auto method : eclass->methodList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*method, writer, classType); } for (auto initializer : eclass->initializerList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*initializer, writer, classType, false, initializer); } popScope(); for (auto classMethod : eclass->classMethodList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*classMethod, writer, classType, true); } if (eclass->instanceVariables.size() > 0 && eclass->initializerList.size() == 0) { auto str = classType.toString(typeNothingness, true); compilerWarning(eclass->classBegin, "Class %s defines %d instances variables but has no initializers.", str.c_str(), eclass->instanceVariables.size()); } writer.writeUInt16(eclass->protocols().size()); if (eclass->protocols().size() > 0) { auto biggestPlaceholder = writer.writePlaceholder<uint16_t>(); auto smallestPlaceholder = writer.writePlaceholder<uint16_t>(); uint_fast16_t smallestProtocolIndex = UINT_FAST16_MAX; uint_fast16_t biggestProtocolIndex = 0; for (auto protocol : eclass->protocols()) { writer.writeUInt16(protocol->index); if (protocol->index > biggestProtocolIndex) { biggestProtocolIndex = protocol->index; } if (protocol->index < smallestProtocolIndex) { smallestProtocolIndex = protocol->index; } writer.writeUInt16(protocol->methods().size()); for (auto method : protocol->methods()) { Method *clm = eclass->getMethod(method->name); if (clm == nullptr) { auto className = classType.toString(typeNothingness, true); auto protocolName = Type(protocol, false).toString(typeNothingness, true); ecCharToCharStack(method->name, ms); compilerError(eclass->classBegin, "Class %s does not agree to protocol %s: Method %s is missing.", className.c_str(), protocolName.c_str(), ms); } writer.writeUInt16(clm->vti); clm->checkPromises(method, "protocol definition", classType); } } biggestPlaceholder.write(biggestProtocolIndex); smallestPlaceholder.write(smallestProtocolIndex); } }
void PackageParser::parse() { while (stream_.hasMoreTokens()) { auto documentation = parseDocumentationToken(); auto exported = Attribute<E_EARTH_GLOBE_EUROPE_AFRICA>().parse(&stream_); auto theToken = stream_.consumeToken(IDENTIFIER); switch (theToken.value[0]) { case E_PACKAGE: { exported.disallow(); auto nameToken = stream_.consumeToken(VARIABLE); auto namespaceToken = stream_.consumeToken(IDENTIFIER); auto name = nameToken.value.utf8CString(); package_->loadPackage(name, namespaceToken.value[0], theToken); continue; } case E_CROCODILE: parseProtocol(documentation, theToken, exported.set()); continue; case E_TURKEY: parseEnum(documentation, exported.set()); continue; case E_RADIO: exported.disallow(); package_->setRequiresBinary(); if (strcmp(package_->name(), "_") == 0) { throw CompilerErrorException(theToken, "You may not set 📻 for the _ package."); } continue; case E_CRYSTAL_BALL: { exported.disallow(); if (package_->validVersion()) { throw CompilerErrorException(theToken, "Package version already declared."); } auto major = stream_.consumeToken(INTEGER).value.utf8CString(); auto minor = stream_.consumeToken(INTEGER).value.utf8CString(); uint16_t majori = strtol(major, nullptr, 0); uint16_t minori = strtol(minor, nullptr, 0); delete [] major; delete [] minor; package_->setPackageVersion(PackageVersion(majori, minori)); if (!package_->validVersion()) { throw CompilerErrorException(theToken, "The provided package version is not valid."); } continue; } case E_WALE: { exported.disallow(); EmojicodeChar className, enamespace; bool optional; auto &classNameToken = parseTypeName(&className, &enamespace, &optional); if (optional) { throw CompilerErrorException(classNameToken, "Optional types are not extendable."); } Type type = typeNothingness; if (!package_->fetchRawType(className, enamespace, optional, theToken, &type)) { throw CompilerErrorException(classNameToken, "Class does not exist."); } if (type.type() != TT_CLASS) { throw CompilerErrorException(classNameToken, "Only classes are extendable."); } // Native extensions are allowed if the class was defined in this package. parseClassBody(type.eclass, nullptr, type.eclass->package() == package_); continue; } case E_RABBIT: parseClass(documentation, theToken, exported.set()); continue; case E_SCROLL: { exported.disallow(); auto pathString = stream_.consumeToken(STRING); auto relativePath = pathString.position().file; auto fileString = pathString.value.utf8CString(); char *str = fileString; const char *lastSlash = strrchr(relativePath, '/'); if (lastSlash != nullptr) { const char *directory = strndup(relativePath, lastSlash - relativePath); asprintf(&str, "%s/%s", directory, fileString); delete [] fileString; delete [] directory; } PackageParser(package_, lex(str)).parse(); delete [] str; continue; } default: ecCharToCharStack(theToken.value[0], f); throw CompilerErrorException(theToken, "Unexpected identifier %s", f); break; } } }