static void doClassDeclaration(void) { PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data; PINTERFACE pif; gchar *chrTemp=pParseInfo->pCurInterface->chrName; /* Check if we already have a (maybe forward) declaration */ pif=findInterfaceFromName(pParseInfo->pCurInterface->chrName); if(pif) { if(pif->fIsForwardDeclaration) { /* Remove the forward declaration and insert the real thing afterwards. */ deRegisterInterface(pif); } else { /* It˚s the declaration from the *.h file. Save a pointer to this information. */ pParseInfo->pClassDefinition=pif; deRegisterInterface(pif); } } pParseInfo->pCurInterface->chrName=chrTemp; pParseInfo->pCurInterface->chrSourceFileName=g_strdup(pParseInfo->chrCurrentSourceFile); /* It's save to register the interface right here even if the struct is almost empty. If anything goes wrong later we will exit anyway. */ registerInterface(); /* The class definition in *.nom files does not contain all the stuff an interface may define. We use the found interface to fill the gaps. If we don˚t have an interface something went wrong and we quit. */ if(!pParseInfo->pClassDefinition) { g_message("Line %d: Error during class parsing. No class definition found. MAke sure you included the *.ih file.", g_scanner_cur_line(gScanner)); cleanupAndExit(0); } pParseInfo->pCurInterface->chrParent=g_strdup(pParseInfo->pClassDefinition->chrParent); /* Note: We don˚t support subclasses yet. */ if(matchNext(':')) { parseParentClassIdent(); } parseClassBody(); }
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; } } }