Beispiel #1
0
void ScopeConsistencyChecker::checkConsistent(IHqlExpression * root, const HqlExprArray & _activeTables)
{
    ForEachItemIn(i, _activeTables)
        activeTables.append(OLINK(_activeTables.item(i)));
    if (root->isDataset())
        pushScope();
    analyse(root, 0);
    if (root->isDataset())
        popScope();
}
Beispiel #2
0
void Semantic::traverse(Defn * cur) {
  if (cur->v == Defn::STRUCT_T) {
    newSym(sid, Symbol(cur->id, cur));
    //check struct types and names pairwise to be distinct
    ArgItem * ptr = cur->args;
    std::set<std::string> ids;
    while (ptr != NULL) {
      valSctType(ptr->arg->type);
      if (ids.find(ptr->arg->ID) != ids.end())
	error("struct field names must be pairwise distinct");
      ptr = ptr->next;
    }
  }
  else if (cur->v == Defn::FUNC_T) {
    //check ret type
    valRetType(cur->type);

    newSym(vid.back(), Symbol(cur->id, cur));
    curF = cur->id;
    pushScope();
    
    //check args types and names
    ArgItem * ptr = cur->args;
    std::set<std::string> ids;
    while (ptr != NULL) {
      valArgType(ptr->arg->type);
      newSym(vid.back(), Symbol(ptr->arg->ID, cur->type));
      if (ids.find(ptr->arg->ID) != ids.end())
	error("argument names must be pairwise distinct");
      ptr = ptr->next;
    }
    pushScope();
    traverse(cur->stmts);
    popScope();
    popScope();
    curF = "";
  }
  else if (cur->v == Defn::TYPEDEF_T) {
    valArgType(cur->type);
    newSym(aid, Symbol(cur->id, cur));
  }
}
Beispiel #3
0
void TreeResolver::pushParent(Element& element, const RenderStyle& style, Change change)
{
    scope().selectorFilter.pushParent(&element);

    Parent parent(element, style, change);

    if (auto* shadowRoot = element.shadowRoot()) {
        pushScope(*shadowRoot);
        parent.didPushScope = true;
    }
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    else if (is<HTMLSlotElement>(element) && downcast<HTMLSlotElement>(element).assignedNodes()) {
        pushEnclosingScope();
        parent.didPushScope = true;
    }
#endif

    m_parentStack.append(WTFMove(parent));
}
Beispiel #4
0
BlockNode* Parser::parseBlock(bool needBraces, const bool scoped/* = true */) {
    if (needBraces) {
        ensureToken(tLBRACE);
    }

    if (scoped) {
      pushScope();
    }

    BlockNode* block = new BlockNode(_currentTokenIndex,
                                     _currentScope);
    TokenKind sentinel = needBraces ? tRBRACE : tEOF;

     while (currentToken() != sentinel) {
         if (currentToken() == tSEMICOLON) {
             consumeToken();
             continue;
         }
         AstNode* statement = parseStatement();
         // Ignore statements that doesn't result in AST nodes, such
         // as variable or function declaration.
         if (statement != 0) {
             block->add(statement);
         }
     }

    if (scoped) {
      popScope();
    }

     if (needBraces) {
         ensureToken(tRBRACE);
     }

     return block;
}
Beispiel #5
0
/**
 * Implement abstract operation from NativeImportBase.
 */
bool AdaImport::parseStmt()
{
    const int srcLength = m_source.count();
    QString keyword = m_source[m_srcIndex];
    UMLDoc *umldoc = UMLApp::app()->document();
    //uDebug() << '"' << keyword << '"';
    if (keyword == QLatin1String("with")) {
        if (m_inGenericFormalPart) {
            // mapping of generic formal subprograms or packages is not yet implemented
            return false;
        }
        while (++m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(";")) {
            QStringList components = m_source[m_srcIndex].toLower().split(QLatin1Char('.'));
            const QString& prefix = components.first();
            if (prefix == QLatin1String("system")
                || prefix == QLatin1String("ada")
                || prefix == QLatin1String("gnat")
                || prefix == QLatin1String("interfaces")
                || prefix == QLatin1String("text_io")
                || prefix == QLatin1String("unchecked_conversion")
                || prefix == QLatin1String("unchecked_deallocation")) {
                if (advance() != QLatin1String(","))
                    break;
                continue;
            }
            parseStems(components);
            if (advance() != QLatin1String(","))
                break;
        }
        return true;
    }
    if (keyword == QLatin1String("generic")) {
        m_inGenericFormalPart = true;
        return true;
    }
    if (keyword == QLatin1String("package")) {
        const QString& name = advance();
        QStringList parentPkgs = name.toLower().split(QLatin1Char('.'));
        parentPkgs.pop_back();  // exclude the current package
        parseStems(parentPkgs);
        UMLObject *ns = NULL;
        if (advance() == QLatin1String("is")) {
            ns = Import_Utils::createUMLObject(UMLObject::ot_Package, name,
                                               currentScope(), m_comment);
            if (m_source[m_srcIndex + 1] == QLatin1String("new")) {
                m_srcIndex++;
                QString pkgName = advance();
                UMLObject *gp = Import_Utils::createUMLObject(UMLObject::ot_Package, pkgName,
                                                              currentScope());
                gp->setStereotype(QLatin1String("generic"));
                // Add binding from instantiator to instantiatee
                UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, ns, gp);
                assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical));
                assoc->setStereotype(QLatin1String("bind"));
                // Work around missing display of stereotype in AssociationWidget:
                assoc->setName(assoc->stereotype(true));
                umldoc->addAssociation(assoc);
                skipStmt();
            } else {
                pushScope(static_cast<UMLPackage*>(ns));
            }
        } else if (m_source[m_srcIndex] == QLatin1String("renames")) {
            m_renaming[name] = advance();
        } else {
            uError() << "unexpected: " << m_source[m_srcIndex];
            skipStmt(QLatin1String("is"));
        }
        if (m_inGenericFormalPart) {
            if (ns)
                ns->setStereotype(QLatin1String("generic"));
            m_inGenericFormalPart = false;
        }
        return true;
    }
    if (m_inGenericFormalPart)
        return false;  // skip generic formal parameter (not yet implemented)
    if (keyword == QLatin1String("subtype")) {
        QString name = advance();
        advance();  // "is"
        QString base = expand(advance());
        base.remove(QLatin1String("Standard."), Qt::CaseInsensitive);
        UMLObject *type = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope());
        if (type == NULL) {
            type = Import_Utils::createUMLObject(UMLObject::ot_Datatype, base, currentScope());
        }
        UMLObject *subtype = Import_Utils::createUMLObject(type->baseType(), name,
                                                           currentScope(), m_comment);
        UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, subtype, type);
        assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical));
        assoc->setStereotype(QLatin1String("subtype"));
        // Work around missing display of stereotype in AssociationWidget:
        assoc->setName(assoc->stereotype(true));
        umldoc->addAssociation(assoc);
        skipStmt();
        return true;
    }
    if (keyword == QLatin1String("type")) {
        QString name = advance();
        QString next = advance();
        if (next == QLatin1String("(")) {
            uDebug() << name << ": discriminant handling is not yet implemented";
            // @todo Find out how to map discriminated record to UML.
            //       For now, we just create a pro forma empty record.
            Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(),
                                          m_comment, QLatin1String("record"));
            skipStmt(QLatin1String("end"));
            if ((next = advance()) == QLatin1String("case"))
                m_srcIndex += 2;  // skip "case" ";"
            skipStmt();
            return true;
        }
        if (next == QLatin1String(";")) {
            // forward declaration
            Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(),
                                          m_comment);
            return true;
        }
        if (next != QLatin1String("is")) {
            uError() << "expecting \"is\"";
            return false;
        }
        next = advance();
        if (next == QLatin1String("(")) {
            // enum type
            UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Enum,
                            name, currentScope(), m_comment);
            UMLEnum *enumType = static_cast<UMLEnum*>(ns);
            while ((next = advance()) != QLatin1String(")")) {
                Import_Utils::addEnumLiteral(enumType, next, m_comment);
                m_comment.clear();
                if (advance() != QLatin1String(","))
                    break;
            }
            skipStmt();
            return true;
        }
        bool isTaggedType = false;
        if (next == QLatin1String("abstract")) {
            m_isAbstract = true;
            next = advance();
        }
        if (next == QLatin1String("tagged")) {
            isTaggedType = true;
            next = advance();
        }
        if (next == QLatin1String("limited") ||
            next == QLatin1String("task") ||
            next == QLatin1String("protected") ||
            next == QLatin1String("synchronized")) {
            next = advance();  // we can't (yet?) represent that
        }
        if (next == QLatin1String("private") ||
            next == QLatin1String("interface") ||
            next == QLatin1String("record") ||
            (next == QLatin1String("null") &&
             m_source[m_srcIndex+1] == QLatin1String("record"))) {
            UMLObject::ObjectType t = (next == QLatin1String("interface") ? UMLObject::ot_Interface
                                                                          : UMLObject::ot_Class);
            UMLObject *ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment);
            if (t == UMLObject::ot_Interface) {
                while ((next = advance()) == QLatin1String("and")) {
                    UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
                    QString base = expand(advance());
                    UMLObject *p = Import_Utils::createUMLObject(UMLObject::ot_Interface, base, currentScope());
                    UMLClassifier *parent = static_cast<UMLClassifier*>(p);
                    Import_Utils::createGeneralization(klass, parent);
                }
            } else {
                ns->setAbstract(m_isAbstract);
            }
            m_isAbstract = false;
            if (isTaggedType) {
                if (! m_classesDefinedInThisScope.contains(ns))
                    m_classesDefinedInThisScope.append(ns);
            } else {
                ns->setStereotype(QLatin1String("record"));
            }
            if (next == QLatin1String("record"))
                m_klass = static_cast<UMLClassifier*>(ns);
            else
                skipStmt();
            return true;
        }
        if (next == QLatin1String("new")) {
            QString base = expand(advance());
            QStringList baseInterfaces;
            while ((next = advance()) == QLatin1String("and")) {
                baseInterfaces.append(expand(advance()));
            }
            const bool isExtension = (next == QLatin1String("with"));
            UMLObject::ObjectType t;
            if (isExtension || m_isAbstract) {
                t = UMLObject::ot_Class;
            } else {
                base.remove(QLatin1String("Standard."), Qt::CaseInsensitive);
                UMLObject *known = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope());
                t = (known ? known->baseType() : UMLObject::ot_Datatype);
            }
            UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL);
            UMLClassifier *parent = static_cast<UMLClassifier*>(ns);
            ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment);
            if (isExtension) {
                next = advance();
                if (next == QLatin1String("null") || next == QLatin1String("record")) {
                    UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
                    Import_Utils::createGeneralization(klass, parent);
                    if (next == QLatin1String("record")) {
                        // Set the m_klass for attributes.
                        m_klass = klass;
                    }
                    if (baseInterfaces.count()) {
                        t = UMLObject::ot_Interface;
                        QStringList::Iterator end(baseInterfaces.end());
                        for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) {
                             ns = Import_Utils::createUMLObject(t, *bi, currentScope());
                             parent = static_cast<UMLClassifier*>(ns);
                             Import_Utils::createGeneralization(klass, parent);
                        }
                    }
                }
            }
            skipStmt();
            return true;
        }
        // Datatypes: TO BE DONE
        return false;
    }
    if (keyword == QLatin1String("private")) {
        m_currentAccess = Uml::Visibility::Private;
        return true;
    }
    if (keyword == QLatin1String("end")) {
        if (m_klass) {
            if (advance() != QLatin1String("record")) {
                uError() << "end: expecting \"record\" at "
                          << m_source[m_srcIndex];
            }
            m_klass = NULL;
        } else if (scopeIndex()) {
            if (advance() != QLatin1String(";")) {
                QString scopeName = currentScope()->fullyQualifiedName();
                if (scopeName.toLower() != m_source[m_srcIndex].toLower())
                    uError() << "end: expecting " << scopeName << ", found "
                              << m_source[m_srcIndex];
            }
            popScope();
            m_currentAccess = Uml::Visibility::Public;   // @todo make a stack for this
        } else {
            uError() << "importAda: too many \"end\"";
        }
        skipStmt();
        return true;
    }
    // subprogram
    if (keyword == QLatin1String("not"))
        keyword = advance();
    if (keyword == QLatin1String("overriding"))
        keyword = advance();
    if (keyword == QLatin1String("function") || keyword == QLatin1String("procedure")) {
        const QString& name = advance();
        QString returnType;
        if (advance() != QLatin1String("(")) {
            // Unlike an Ada package, a UML package does not support
            // subprograms.
            // In order to map those, we would need to create a UML
            // class with stereotype <<utility>> for the Ada package.
            uDebug() << "ignoring parameterless " << keyword << " " << name;
            skipStmt();
            return true;
        }
        UMLClassifier *klass = NULL;
        UMLOperation *op = NULL;
        const uint MAX_PARNAMES = 16;
        while (m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(")")) {
            QString parName[MAX_PARNAMES];
            uint parNameCount = 0;
            do {
                if (parNameCount >= MAX_PARNAMES) {
                    uError() << "MAX_PARNAMES is exceeded at " << name;
                    break;
                }
                parName[parNameCount++] = advance();
            } while (advance() == QLatin1String(","));
            if (m_source[m_srcIndex] != QLatin1String(":")) {
                uError() << "importAda: expecting ':'";
                skipStmt();
                break;
            }
            const QString &direction = advance();
            QString typeName;
            Uml::ParameterDirection::Enum dir = Uml::ParameterDirection::In;
            if (direction == QLatin1String("access")) {
                // Oops, we have to improvise here because there
                // is no such thing as "access" in UML.
                // So we use the next best thing, "inout".
                // Better ideas, anyone?
                dir = Uml::ParameterDirection::InOut;
                typeName = advance();
            } else if (direction == QLatin1String("in")) {
                if (m_source[m_srcIndex + 1] == QLatin1String("out")) {
                    dir = Uml::ParameterDirection::InOut;
                    m_srcIndex++;
                }
                typeName = advance();
            } else if (direction == QLatin1String("out")) {
                dir = Uml::ParameterDirection::Out;
                typeName = advance();
            } else {
                typeName = direction;  // In Ada, the default direction is "in"
            }
            typeName.remove(QLatin1String("Standard."), Qt::CaseInsensitive);
            typeName = expand(typeName);
            if (op == NULL) {
                // In Ada, the first parameter indicates the class.
                UMLObject *type = Import_Utils::createUMLObject(UMLObject::ot_Class, typeName, currentScope());
                UMLObject::ObjectType t = type->baseType();
                if ((t != UMLObject::ot_Interface &&
                     (t != UMLObject::ot_Class || type->stereotype() == QLatin1String("record"))) ||
                    !m_classesDefinedInThisScope.contains(type)) {
                    // Not an instance bound method - we cannot represent it.
                    skipStmt(QLatin1String(")"));
                    break;
                }
                klass = static_cast<UMLClassifier*>(type);
                op = Import_Utils::makeOperation(klass, name);
                // The controlling parameter is suppressed.
                parNameCount--;
                if (parNameCount) {
                    for (uint i = 0; i < parNameCount; ++i) {
                        parName[i] = parName[i + 1];
                    }
                }
            }
            for (uint i = 0; i < parNameCount; ++i) {
                UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]);
                att->setParmKind(dir);
            }
            if (advance() != QLatin1String(";"))
                break;
        }
        if (keyword == QLatin1String("function")) {
            if (advance() != QLatin1String("return")) {
                if (klass)
                    uError() << "importAda: expecting \"return\" at function "
                        << name;
                return false;
            }
            returnType = expand(advance());
            returnType.remove(QLatin1String("Standard."), Qt::CaseInsensitive);
        }
        bool isAbstract = false;
        if (advance() == QLatin1String("is") && advance() == QLatin1String("abstract"))
            isAbstract = true;
        if (klass != NULL && op != NULL)
            Import_Utils::insertMethod(klass, op, m_currentAccess, returnType,
                                       false, isAbstract, false, false, m_comment);
        skipStmt();
        return true;
    }
    if (keyword == QLatin1String("task") || keyword == QLatin1String("protected")) {
        // Can task and protected objects/types be mapped to UML?
        QString name = advance();
        if (name == QLatin1String("type")) {
            name = advance();
        }
        QString next = advance();
        if (next == QLatin1String("(")) {
            skipStmt(QLatin1String(")"));  // skip discriminant
            next = advance();
        }
        if (next == QLatin1String("is"))
            skipStmt(QLatin1String("end"));
        skipStmt();
        return true;
    }
    if (keyword == QLatin1String("for")) {    // rep spec
        QString typeName = advance();
        QString next = advance();
        if (next == QLatin1String("'")) {
            advance();  // skip qualifier
            next = advance();
        }
        if (next == QLatin1String("use")) {
            if (advance() == QLatin1String("record"))
                skipStmt(QLatin1String("end"));
        } else {
            uError() << "importAda: expecting \"use\" at rep spec of "
                      << typeName;
        }
        skipStmt();
        return true;
    }
    // At this point we're only interested in attribute declarations.
    if (m_klass == NULL || keyword == QLatin1String("null")) {
        skipStmt();
        return true;
    }
    const QString& name = keyword;
    if (advance() != QLatin1String(":")) {
        uError() << "adaImport: expecting \":\" at " << name << " "
                  << m_source[m_srcIndex];
        skipStmt();
        return true;
    }
    QString nextToken = advance();
    if (nextToken == QLatin1String("aliased"))
        nextToken = advance();
    QString typeName = expand(nextToken);
    QString initialValue;
    if (advance() == QLatin1String(":=")) {
        initialValue = advance();
        QString token;
        while ((token = advance()) != QLatin1String(";")) {
            initialValue.append(QLatin1Char(' ') + token);
        }
    }
    UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
                                                 typeName, m_comment);
    if (o) {
        UMLAttribute *attr = static_cast<UMLAttribute*>(o);
        attr->setInitialValue(initialValue);
    }
    skipStmt();
    return true;
}
Beispiel #6
0
FunctionNode* Parser::parseFunction() {
    uint32_t tokenIndex = _currentTokenIndex;
    ensureKeyword("function");

    if (currentToken() != tIDENT) {
        error("identifier expected");
    }
    const string& returnTypeName = currentTokenValue();
    VarType returnType = nameToType(returnTypeName);
    if (returnType == VT_INVALID) {
      error("wrong return type");
    }
    consumeToken();

    if (currentToken() != tIDENT) {
        error("name expected");
    }
    const string& name = currentTokenValue();
    consumeToken();

    Signature signature;
    signature.push_back(SignatureElement(returnType, "return"));

    ensureToken(tLPAREN);
    while (currentToken() != tRPAREN) {
        const string& parameterTypeName = currentTokenValue();
        VarType parameterType = nameToType(parameterTypeName);
        if (parameterType == VT_INVALID) {
            error("wrong parameter type");
        }
        consumeToken();
        const string& parameterName = currentTokenValue();
        if (currentToken() != tIDENT) {
            error("identifier expected");
        }
        consumeToken();
        signature.push_back(SignatureElement(parameterType, parameterName));

        if (currentToken() == tCOMMA) {
            consumeToken();
        }
    }
    ensureToken(tRPAREN);

    BlockNode* body = 0;
    pushScope();
    for (uint32_t i = 1; i < signature.size(); i++) {
      const string& name = signature[i].second;
      VarType type = signature[i].first;
      if (!_currentScope->declareVariable(name, type)) {
          error("Formal \"%s\" already declared", name.c_str());
      }
    }
    if ((currentToken() == tIDENT) && currentTokenValue() == "native") {
      consumeToken();
      if (currentToken() != tSTRING) {
          error("Native name expected, got %s", tokenStr(currentToken()));
      }
      pushScope();
      body = new BlockNode(_currentTokenIndex, _currentScope);
      body->add(new NativeCallNode(tokenIndex, currentTokenValue(), signature));
      consumeToken();
      ensureToken(tSEMICOLON);
      body->add(new ReturnNode(0, 0));
      popScope();
    } else {
      body = parseBlock(true, false);
      if (body->nodes() == 0 ||
          !(body->nodeAt(body->nodes() - 1)->isReturnNode())) {
        body->add(new ReturnNode(0, defaultReturnExpr(returnType)));
      }
    }
    popScope();

    if (_currentScope->lookupFunction(name) != 0) {
        error("Function %s already defined", name.c_str());
    }
    FunctionNode* result = new FunctionNode(tokenIndex, name, signature, body);
    _currentScope->declareFunction(result);

    // We don't add function node into AST.
    return 0;
}
Beispiel #7
0
static void parseValue (tokenInfo *const token)
{
	if (token->type == TOKEN_OPEN_CURLY)
	{
		tokenInfo *name = newToken ();

		do
		{
			readTokenFull (token, TRUE);
			if (token->type == TOKEN_STRING)
			{
				jsonKind tagKind = TAG_NULL; /* default in case of invalid value */

				copyToken (name, token);

				/* skip any possible garbage before the value */
				skipToOneOf3 (token, TOKEN_CLOSE_CURLY, TOKEN_COLON, TOKEN_COMMA);

				if (token->type == TOKEN_COLON)
				{
					readToken (token);
					tagKind = tokenToKind (token->type);

					pushScope (token, name, tagKind);
					parseValue (token);
					popScope (token, name);
				}

				makeJsonTag (name, tagKind);
			}
			/* skip to the end of the construct */
			skipToOneOf2 (token, TOKEN_CLOSE_CURLY, TOKEN_COMMA);
		}
		while (token->type != TOKEN_EOF &&
			   token->type != TOKEN_CLOSE_CURLY);

		if (token->type == TOKEN_CLOSE_CURLY)
			readToken (token);

		deleteToken (name);
	}
	else if (token->type == TOKEN_OPEN_SQUARE)
	{
		tokenInfo *name = newToken ();
		char buf[32];
		unsigned int nth = 0;

		readToken (token);
		while (token->type != TOKEN_EOF &&
			   token->type != TOKEN_CLOSE_SQUARE)
		{
			jsonKind tagKind;

			tagKind = tokenToKind (token->type);

			copyToken (name, token);
			snprintf (buf, sizeof buf, "%u", nth++);
			vStringCopyS (name->string, buf);

			makeJsonTag (name, tagKind);
			pushScope (token, name, tagKind);
			parseValue (token);
			popScope (token, name);

			/* skip to the end of the construct */
			skipToOneOf2 (token, TOKEN_CLOSE_SQUARE, TOKEN_COMMA);
			if (token->type != TOKEN_CLOSE_SQUARE)
				readToken (token);
		}

		if (token->type == TOKEN_CLOSE_SQUARE)
			readToken (token);

		deleteToken (name);
	}
}
Beispiel #8
0
void QSEnv::pushScopeBlock()
{
    QSObject obj;
    pushScope(obj);
    labels.push_front(QString::null);
}
Beispiel #9
0
/*!
 * \brief   Instantiates a new SymbolTable object.
 *
 * Creates a symbol table with an initial, global scope to contain symbols.
 */
SymbolTable::SymbolTable()
    :m_pHeadScope(0), m_Scope(0)
{
    pushScope();
}
Beispiel #10
0
/**
 * Implement abstract operation from NativeImportBase.
 * @return success status of operation
 */
bool PythonImport::parseStmt()
{
    const int srcLength = m_source.count();
    const QString& keyword = m_source[m_srcIndex];
    if (keyword == QLatin1String("class")) {
        const QString& name = advance();
        UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Class, name,
                                                      currentScope(), m_comment);
        pushScope(m_klass = static_cast<UMLClassifier*>(ns));
        m_comment.clear();
        if (advance() == QLatin1String("(")) {
            while (m_srcIndex < srcLength - 1 && advance() != QLatin1String(")")) {
                const QString& baseName = m_source[m_srcIndex];
                Import_Utils::createGeneralization(m_klass, baseName);
                if (advance() != QLatin1String(","))
                    break;
            }
        }
        if (m_source[m_srcIndex] != QLatin1String("{")) {
            skipStmt(QLatin1String("{"));
        }
        log(QLatin1String("class ") + name);
        return true;
    }
    if (keyword == QLatin1String("@")) {
        const QString& annotation = m_source[++m_srcIndex];
        uDebug() << "annotation:" << annotation;
        if (annotation == QLatin1String("staticmethod"))
            m_isStatic = true;
        return true;
    }
    if (keyword == QLatin1String("def")) {
        if (m_klass == NULL) {
            // skip functions outside of a class
            skipBody();
            return true;
        }

        if (!m_klass->hasDoc() && !m_comment.isEmpty()) {
            m_klass->setDoc(m_comment);
            m_comment = QString();
        }

        const QString& name = advance();
        // operation
        UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
        if (advance() != QLatin1String("(")) {
            uError() << "importPython def " << name << ": expecting \"(\"";
            skipBody();
            return true;
        }
        bool firstParam = true;
        while (m_srcIndex < srcLength && advance() != QLatin1String(")")) {
            const QString& parName = m_source[m_srcIndex];
            if (firstParam) {
                if (parName.compare(QLatin1String("self"), Qt::CaseInsensitive) != 0) {
                    m_isStatic = true;
                    Import_Utils::addMethodParameter(op, QLatin1String("string"), parName);
                }
                firstParam = false;
            } else {
                /*UMLAttribute *att =*/ Import_Utils::addMethodParameter(op, QLatin1String("string"), parName);
            }
            if (advance() != QLatin1String(","))
                break;
        }
        Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, QLatin1String("string"),
                                   m_isStatic, false /*isAbstract*/, false /*isFriend*/,
                                   false /*isConstructor*/, m_comment);
        m_isStatic = false;
        op->setSourceCode(skipBody());

        if (!op->hasDoc() && !m_comment.isEmpty()) {
            op->setDoc(m_comment);
            m_comment = QString();
        }
        log(QLatin1String("def ") + name);

        return true;
    }
    if (keyword == QLatin1String("}")) {
        if (scopeIndex()) {
            m_klass = dynamic_cast<UMLClassifier*>(popScope());
        }
        else
            uError() << "parsing: too many }";
        return true;
    }
    return false;  // @todo parsing of attributes
}
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);
    }
}
Beispiel #12
0
/**
 * Implement abstract operation from NativeImportBase.
 * @return success status of operation
 */
bool PythonImport::parseStmt()
{
    const int srcLength = m_source.count();
    QString keyword = m_source[m_srcIndex];
    if (keyword == QLatin1String("class")) {
        const QString& name = advance();
        UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Class, name,
                                                      currentScope(), m_comment);
        pushScope(m_klass = ns->asUMLClassifier());
        m_comment.clear();
        if (advance() == QLatin1String("(")) {
            while (m_srcIndex < srcLength - 1 && advance() != QLatin1String(")")) {
                const QString& baseName = m_source[m_srcIndex];
                Import_Utils::createGeneralization(m_klass, baseName);
                if (advance() != QLatin1String(","))
                    break;
            }
        }
        if (m_source[m_srcIndex] != QLatin1String("{")) {
            skipStmt(QLatin1String("{"));
        }
        log(QLatin1String("class ") + name);
        return true;
    }
    if (keyword == QLatin1String("@")) {
        const QString& annotation = m_source[++m_srcIndex];
        uDebug() << "annotation:" << annotation;
        if (annotation == QLatin1String("staticmethod"))
            m_isStatic = true;
        return true;
    }
    if (keyword == QLatin1String("def")) {
        if (m_klass == 0) {
            // skip functions outside of a class
            skipBody();
            return true;
        }

        if (!m_klass->hasDoc() && !m_comment.isEmpty()) {
            m_klass->setDoc(m_comment);
            m_comment = QString();
        }

        const QString& name = advance();
        // operation
        UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
        if (advance() != QLatin1String("(")) {
            uError() << "importPython def " << name << ": expecting \"(\"";
            skipBody();
            return true;
        }
        bool firstParam = true;
        while (m_srcIndex < srcLength && advance() != QLatin1String(")")) {
            const QString& parName = m_source[m_srcIndex];
            if (firstParam) {
                if (parName.compare(QLatin1String("self"), Qt::CaseInsensitive) != 0) {
                    m_isStatic = true;
                    Import_Utils::addMethodParameter(op, QLatin1String("string"), parName);
                }
                firstParam = false;
            } else {
                /*UMLAttribute *att =*/ Import_Utils::addMethodParameter(op, QLatin1String("string"), parName);
            }
            if (advance() != QLatin1String(","))
                break;
        }
        Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, QLatin1String("string"),
                                   m_isStatic, false /*isAbstract*/, false /*isFriend*/,
                                   false /*isConstructor*/, m_comment);
        m_isStatic = false;
        int srcIndex = m_srcIndex;
        op->setSourceCode(skipBody());

        if (!op->hasDoc() && !m_comment.isEmpty()) {
            op->setDoc(m_comment);
            m_comment = QString();
        }

        // parse instance variables from __init__ method
        if (name == QLatin1String("__init__")) {
            int indexSave = m_srcIndex;
            m_srcIndex = srcIndex;
            advance();
            keyword = advance();
            while (m_srcIndex < indexSave) {
                if (lookAhead() == QLatin1String("=")) {
                    parseAssignmentStmt(keyword);
                    // skip ; inserted by lexer
                    if (lookAhead() == QLatin1String(";")) {
                        advance();
                        keyword = advance();
                    }
                } else {
                    skipStmt(QLatin1String(";"));
                    keyword = advance();
                }
            }
            m_srcIndex = indexSave;
        }
        log(QLatin1String("def ") + name);

        return true;
    }

    // parse class variables
    if (m_klass && lookAhead() == QLatin1String("=")) {
        bool result = parseAssignmentStmt(keyword);
        log(QLatin1String("class attribute ") + keyword);
        return result;
    }

    if (keyword == QLatin1String("}")) {
        if (scopeIndex()) {
            m_klass = popScope()->asUMLClassifier();
        }
        else
            uError() << "parsing: too many }";
        return true;
    }
    return false;  // @todo parsing of attributes
}
Beispiel #13
0
void Semantic::traverse(Stmt * cur) {
  if (cur->v == Stmt::LIST_T) {
    pushScope();
    traverse(cur->list);
    popScope();
  }
  else if (cur->v == Stmt::IF_T || cur->v == Stmt::WHILE_T) {
    if (cur->v == Stmt::WHILE_T) loops.push(cur);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (cur->v == Stmt::WHILE_T) loops.pop();
  }
  else if (cur->v == Stmt::FOR_T) {
    loops.push(cur);
    pushScope();
    traverse(cur->left);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (hasDecl(cur->right))
      error("For loop-end statement must not include declarations");
    traverse(cur->right);
    popScope();
    loops.pop();
  }
  else if (cur->v == Stmt::RETURN_T) {
    //check current function return type and compare it with this
    if (!sameType(expType(cur->exp), *getSym(curF).defn->type))
      error("return expression type differs from function " + curF + " signature");
    if (cur->exp != NULL)
      traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSERT_T) {
    //check argument type to be of bool
    if (!sameType(expType(cur->exp), Type(Type::BOOL_T)))
      error("assert expression type must be bool");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ERROR_T) {
    //call error function with argment string
    if (!sameType(expType(cur->exp), Type(Type::STRING_T)))
      error("error argument must be of type string");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSIGN_T) {
    //check if lhs and rhs same type, ensure rhs and lhs is not a struct
    Type l = lvalType(cur->lval), r = expType(cur->exp);
    traverse(cur->exp);
    
    if (cur->op == "=") {
      if (!sameType(l, r))
	error("lval and expression have different types");
    }
    else if (cur->op == ">>=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from right shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "<<=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from left shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "+=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from add assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from add assign must be of type int or char");
    }
    else if (cur->op == "-=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from sub assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from sub assign must be of type int or char");
    }
    else if (cur->op == "*=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mul assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mul assign must be of type int or char");
    }
    else if (cur->op == "/=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from div assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from div assign must be of type int or char");
    }
    else if (cur->op == "%=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mod assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mod assign must be of type int or char");
    }
    else if (cur->op == "&=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from and assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from and assign must be of type int or char or bool");
    }
    else if (cur->op == "^=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from xor assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from xor assign must be of type int or char or bool");
    }
    else if (cur->op == "|=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from or assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from or assign must be of type int or char or bool");
    }
  }
  else if (cur->v == Stmt::INC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from increment must be of type int or char");
    
  }
  else if (cur->v == Stmt::DEC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from decrement must be of type int or char");
    
  }
  else if (cur->v == Stmt::EXP_T) {
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::DECL_T) {
    //declaring a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::DECLI_T) {
    //declaring and assigning a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::BREAK_T) {
    //check most recent loop
    if (loops.empty())
      error("break statement does not have a loop");
  }
  else if (cur->v == Stmt::CONT_T) {
    if (loops.empty())
      error("continue statement does not have a loop");
  }
}