VbCodeExpressionPtr VbCodeExpressionFactory::CreateDefaultValue(const optional<Sentence>& sentence) { if (!sentence) return nullptr; VbDefaultValue defaultValue{ *sentence }; return CreateExpression(defaultValue.expression); }
Expression ESolver::CreateExpression(const ConcreteValueBase* TheValue) { // Create an anonymous constant operator for this value vector<const ESFixedTypeBase*> EmptyVec; auto FuncType = TypeMgr->CreateType<ESFunctionType>(EmptyVec, TheValue->GetType()); auto Op = ConstMgr->GetOp(TheValue, FuncType); return CreateExpression(Op); }
NS_IMETHODIMP nsXPathEvaluator::CreateExpression(const nsAString & aExpression, nsIDOMXPathNSResolver *aResolver, nsIDOMXPathExpression **aResult) { return CreateExpression(aExpression, aResolver, (nsTArray<int32_t>*)nullptr, nullptr, nullptr, aResult); }
PHPExpression::PHPExpression(const wxString& fulltext, const wxString& exprText) : m_type(kNone) , m_text(fulltext) { if(exprText.IsEmpty()) { // use the full text to extract the expression m_expression = CreateExpression(fulltext); } else { wxString phpExprText = exprText; if(!exprText.StartsWith("<?php")) { // without this, the parser will refuse to work :) phpExprText.Prepend("<?php "); } m_expression = CreateExpression(phpExprText); } }
already_AddRefed<nsIDOMXPathExpression> XPathEvaluator::CreateExpression(const nsAString& aExpression, nsIDOMXPathNSResolver* aResolver, ErrorResult& rv) { nsCOMPtr<nsIDOMXPathExpression> expr; rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); return expr.forget(); }
Expression ESolver::CreateAuxVarExpression(uint64 AuxID, const ESFixedTypeBase* Type) { auto Op = CreateAuxVariable(AuxID, Type); if (Op->GetEvalType() != Type) { throw TypeException((string)"Aux Var with ID " + to_string(AuxID) + " has already " + "been declared with a different type!"); } return CreateExpression(Op); }
Expression ESolver::CreateExpression(const string& OperatorName, const Expression& Exp1, const Expression& Exp2) { vector<Expression> Children(2); Children[0] = Exp1; Children[1] = Exp2; return CreateExpression(OperatorName, Children); }
XPathExpression* XPathEvaluator::CreateExpression(const nsAString& aExpression, nsINode* aResolver, ErrorResult& aRv) { nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument); XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTMLDocument())); return CreateExpression(aExpression, &pContext, doc, aRv); }
already_AddRefed<XPathResult> XPathEvaluator::Evaluate(JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode, XPathNSResolver* aResolver, uint16_t aType, JS::Handle<JSObject*> aResult, ErrorResult& rv) { nsAutoPtr<XPathExpression> expression(CreateExpression(aExpression, aResolver, rv)); if (rv.Failed()) { return nullptr; } return expression->Evaluate(aCx, aContextNode, aType, aResult, rv); }
Expression ESolver::CreateExpression(const string& OperatorName, const Expression& Exp1, const Expression& Exp2, const Expression& Exp3) { // special case for bv extract if (OperatorName == "bvextract") { if (Exp2->As<UserConstExpression>() == nullptr || Exp3->As<UserConstExpression>() == nullptr) { throw TypeException((string)"bvextract can only be applied to constant indices"); } if (Exp2->GetType() != IntType || Exp3->GetType() != IntType) { throw TypeException((string)"bvextract can only be applied to constant integer indices"); } auto OpName = BVLogic::GetExtractOpName(Exp1->GetType(), Exp2->GetOp()->As<ConstOperator>()->GetConstantValue()->GetValue(), Exp3->GetOp()->As<ConstOperator>()->GetConstantValue()->GetValue()); // recurse with new name auto Op = LookupOperator(OpName); if (Op == nullptr) { LoadedBVLogic->InstantiateExtractOperator(Exp1->GetType(), Exp2->GetOp()->As<ConstOperator>()->GetConstantValue()->GetValue(), Exp3->GetOp()->As<ConstOperator>()->GetConstantValue()->GetValue()); Op = LookupOperator(OpName); } vector<Expression> Children = { Exp1 }; return CreateExpression(Op, Children); } vector<Expression> Children(3); Children[0] = Exp1; Children[1] = Exp2; Children[2] = Exp3; return CreateExpression(OperatorName, Children); }
Expression ESolver::CreateExpression(const string& OperatorName, const vector<Expression>& Children) { vector<const ESFixedTypeBase*> ArgTypes; for(uint32 i = 0; i < Children.size(); ++i) { ArgTypes.push_back(Children[i]->GetType()); } const OperatorBase* OpInfo = LookupOperator(OperatorName, ArgTypes); if(OpInfo == NULL) { throw TypeException((string)"No overloaded operator found for operator name: \"" + OperatorName + "\""); } return CreateExpression(OpInfo, Children); }
NS_IMETHODIMP nsXPathEvaluator::Evaluate(const nsAString & aExpression, nsIDOMNode *aContextNode, nsIDOMXPathNSResolver *aResolver, uint16_t aType, nsISupports *aInResult, nsISupports **aResult) { nsCOMPtr<nsIDOMXPathExpression> expression; nsresult rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expression)); NS_ENSURE_SUCCESS(rv, rv); return expression->Evaluate(aContextNode, aType, aInResult, aResult); }
VbCodeExpressionPtr VbCodeExpressionFactory::CreatePrimaryExpression(const Sentence& sentence) { VbPrimaryExpression expression{ sentence }; if (expression.literal) return CreateConstantExpression(*expression.literal); if (expression.wsDot) return std::make_shared<VbCodeWithExpression>(ToDotType(*expression.wsDot), expression.id->GetValue()); if (expression.expression2) throw std::runtime_error("Not implemented: (expression, expression)"); if (expression.expression1) return std::make_shared<VbCodeParenthesisExpression>(CreateExpression(*expression.expression1)); if (*expression.id == "me") return std::make_shared<VbCodeMeExpression>(); return std::make_shared<VbCodeIdExpression>(expression.id->GetValue()); }
Expression ESolver::CreateOrExpression(const vector<Expression>& Disjuncts) { if(Disjuncts.size() == 0) { return Expression::NullObject; } if(Disjuncts.size() == 1) { return Disjuncts[0]; } Expression Current = CreateOrExpression(Disjuncts[0], Disjuncts[1]); uint32 NumDisjuncts = Disjuncts.size(); for(uint32 i = 2; i < NumDisjuncts; ++i) { Current = CreateOrExpression(Current, Disjuncts[i]); } return CreateExpression("or", Current->GetChildren()); }
Expression ESolver::CreateAndExpression(const vector<Expression>& Conjuncts) { if(Conjuncts.size() == 0) { return Expression::NullObject; } if(Conjuncts.size() == 1) { return Conjuncts[0]; } Expression Current = CreateAndExpression(Conjuncts[0], Conjuncts[1]); uint32 NumConjuncts = Conjuncts.size(); for(uint32 i = 2; i < NumConjuncts; ++i) { Current = CreateAndExpression(Current, Conjuncts[i]); } return CreateExpression("and", Current->GetChildren()); }
Expression ESolver::CreateExpression(const string& VariableName) { vector<Expression> Args; const OperatorBase* Op = ScopeMgr->LookupOperator(VariableName)->As<VarOperatorBase>(); if (Op == nullptr) { Op = ScopeMgr->LookupOperator(VariableName)->As<ConstOperator>(); } // audupa: it might just be a constant macro if (Op == nullptr) { Op = ScopeMgr->LookupOperator(VariableName)->As<MacroOperator>(); } if(Op == NULL) { throw UndefinedVarException((string)"Variable or constant \"" + VariableName + + "\" not found to create expression"); } return CreateExpression(Op, Args); }
NS_IMETHODIMP nsXPathEvaluator::Evaluate(const nsAString & aExpression, nsIDOMNode *aContextNode, nsIDOMXPathNSResolver *aResolver, PRUint16 aType, nsISupports *aInResult, nsISupports **aResult) { // XXX Need to check document of aContextNode if created by // QI'ing a document. nsCOMPtr<nsIDOMXPathExpression> expression; nsresult rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expression)); NS_ENSURE_SUCCESS(rv, rv); return expression->Evaluate(aContextNode, aType, aInResult, aResult); }
std::vector<VbCodeExpressionPtr> VbCodeExpressionFactory::CreateExpressionList(const Sentence& sentence) { std::vector<VbCodeExpressionPtr> expressions; VbExpressionList expressionList{ sentence }; if (expressionList.separator && *expressionList.separator != ",") throw std::runtime_error("';' statement separator not yet implemented."); for (auto& expressionItemSentence : expressionList.expressionItems) { VbExpressionItem expressionItem{ expressionItemSentence }; if (!expressionItem.expression) expressions.push_back(std::make_shared<VbCodeMissingExpression>()); else { if (expressionItem.passBy) throw std::runtime_error("Pass-by on expression item not yet implemented."); if (expressionItem.name) throw std::runtime_error("Named expression items not yet implemented."); expressions.push_back(CreateExpression(*expressionItem.expression)); } } return expressions; }
wxString PHPExpression::DoSimplifyExpression(int depth, PHPSourceFile::Ptr_t sourceFile) { if(depth > 5 || sourceFile == NULL) { // avoid infinite recursion, by limiting the nest level to 5 return ""; } // Use the provided sourceFile if 'm_sourceFile' is NULL if(!m_sourceFile) { m_sourceFile = sourceFile; } // Parse the input source file PHPEntityBase::Ptr_t scope = sourceFile->CurrentScope(); const PHPEntityBase* innerClass = sourceFile->Class(); // Check the first token // Phase 1: // Loop over the expression and resolve as much as we can here for the first token // (mainly, replace $this, self, static, $variable) phpLexerToken token; wxString newExpr; wxString firstToken; int firstTokenType = wxNOT_FOUND; for(size_t i = 0; i < m_expression.size(); ++i) { token = m_expression.at(i); if(i == 0) { // Perform basic replacements that we can conduct here without the need of the global // lookup table if(token.type == kPHP_T_PARENT) { if(!innerClass) return ""; firstToken = innerClass->GetFullName(); firstTokenType = kPHP_T_PARENT; } else if(token.type == kPHP_T_THIS) { // the first token is $this // replace it with the current class absolute path if(!innerClass) return ""; firstToken = innerClass->GetFullName(); // Is always in absolute path } else if(token.type == kPHP_T_SELF) { // Same as $this: replace it with the current class absolute path if(!innerClass) return ""; firstToken = innerClass->GetFullName(); // Is always in absolute path firstTokenType = kPHP_T_SELF; } else if(token.type == kPHP_T_STATIC) { // Same as $this: replace it with the current class absolute path if(!innerClass) return ""; firstToken = innerClass->GetFullName(); // Is always in absolute path firstTokenType = kPHP_T_STATIC; } else if(token.type == kPHP_T_VARIABLE) { // the expression being evaluated starts with a variable (e.g. $a->something()->) // in this case, use the current scope ('scope') and replace it with the real type // Note that the type can be another expression // e.g.: // $a = $this->getQuery(); // $b = $a->fetchAll()-> // so if the expression being evaluated is "$a->fetchAll()->" // we first replace $a with '$this->getQuery()' so it becomes: // $this->getQuery()->fetchAll()-> // However, $this also need a replacement so eventually, it becomes like this: // \MyClass->getQuery->fetchAll-> and this is something that we can evaluate easily using // our lookup tables (note that the parenthessis are missing on purpose) PHPEntityBase::Ptr_t local = scope->FindChild(token.text); if(local && local->Cast<PHPEntityVariable>()) { if(!local->Cast<PHPEntityVariable>()->GetTypeHint().IsEmpty()) { // we have type hint! - use it firstToken = local->Cast<PHPEntityVariable>()->GetTypeHint(); } else if(!local->Cast<PHPEntityVariable>()->GetExpressionHint().IsEmpty()) { // we have an expression hint - use it // append the "->" to the expression to make sure that the parser will understand it // as an expression PHPExpression e(m_text, local->Cast<PHPEntityVariable>()->GetExpressionHint() + "->"); firstToken = e.DoSimplifyExpression(depth + 1, m_sourceFile); if(firstToken.EndsWith("->")) { // remove the last 2 characters firstToken.RemoveLast(2); } } } else { // this local variable does not exist in the current scope // This is probably a word-completion for local variable m_filter = token.text; return ""; } } else if(token.type == kPHP_T_IDENTIFIER) { // an identifier, convert it to the fullpath firstToken = sourceFile->MakeIdentifierAbsolute(token.text); } } if(!firstToken.IsEmpty()) { newExpr = firstToken; firstToken.Clear(); } else { newExpr << " " << token.text; } } // Phase 2: // Now break the tokens from the lexers into something that we can work with // when using the lookup table. // The split in this phase is done by searching for kPHP_T_OBJECT_OPERATOR and kPHP_T_PAAMAYIM_NEKUDOTAYIM // separators m_expression = CreateExpression("<?php " + newExpr); Part part; wxString currentText; for(size_t i = 0; i < m_expression.size(); ++i) { token = m_expression.at(i); // Remove any braces and split by object kPHP_T_OBJECT_OPERATOR and kPHP_T_PAAMAYIM_NEKUDOTAYIM switch(token.type) { case kPHP_T_OPEN_TAG: break; case '(': if(!currentText.IsEmpty()) { part.m_text = currentText; } break; case ')': // skip it break; case kPHP_T_PAAMAYIM_NEKUDOTAYIM: case kPHP_T_OBJECT_OPERATOR: if(!currentText.IsEmpty() && part.m_text.IsEmpty()) { if(m_parts.empty() && token.type == kPHP_T_PAAMAYIM_NEKUDOTAYIM) { // The first token in the "parts" list has a scope resolving operator ("::") // we need to make sure that the indetifier is provided in fullpath part.m_text = sourceFile->MakeIdentifierAbsolute(currentText); } else { part.m_text = currentText; } } if(m_parts.empty()) { // If the first token before the simplication was 'parent' // keyword, we need to carry this over part.m_textType = firstTokenType; } part.m_operator = token.type; part.m_operatorText = token.text; m_parts.push_back(part); // cleanup currentText.clear(); part.m_text.clear(); part.m_operatorText.clear(); part.m_operator = wxNOT_FOUND; break; case kPHP_T_THIS: case kPHP_T_SELF: case kPHP_T_STATIC: part.m_textType = token.type; currentText << token.text; break; default: currentText << token.text; break; } } if(!currentText.IsEmpty()) { m_filter = currentText; } wxString simplified; List_t::iterator iter = m_parts.begin(); for(; iter != m_parts.end(); ++iter) { simplified << iter->m_text << iter->m_operatorText; } return simplified.Trim().Trim(false); }
Expression ESolver::CreateNotExpression(const Expression& Exp) { return CreateExpression("not", Exp); }
Expression ESolver::CreateOrExpression(const Expression& Exp1, const Expression& Exp2) { return CreateExpression("or", Exp1, Exp2); }
Expression ESolver::CreateExpression(const ESFixedTypeBase* Type, const string& ConstantString) { const ConcreteValueBase* TheValue = CreateValue(Type, ConstantString); return CreateExpression(TheValue); }
Expression ESolver::CreateTrueExpression() { return CreateExpression(TrueValue); }
Expression ESolver::CreateExpression(const OperatorBase* OpInfo) { vector<Expression> ArgTypes; return CreateExpression(OpInfo, ArgTypes); }
Expression ESolver::CreateAndExpression(const Expression& Exp1, const Expression& Exp2) { return CreateExpression("and", Exp1, Exp2); }
Expression ESolver::CreateFalseExpression() { return CreateExpression(FalseValue); }
Expression ESolver::CreateFreshLetBoundVarExpression(const string& VarName, const ESFixedTypeBase* Type) { auto Op = CreateLetBoundVariable(VarName, Type); return CreateExpression(Op); }