/* Parse beginning of type definition * type 'avar ident = * or * type ('var1, 'var2) ident = */ static void typeDecl (vString * const ident, ocaToken what) { switch (what) { /* parameterized */ case Tok_Prime: comeAfter = &typeDecl; toDoNext = &ignoreToken; break; /* LOTS of parameters */ case Tok_PARL: comeAfter = &typeDecl; waitedToken = Tok_PARR; toDoNext = &tillToken; break; case OcaIDENTIFIER: addTag (ident, K_TYPE); pushStrongContext (ident, ContextType); requestStrongPoping (); waitedToken = Tok_EQ; comeAfter = &typeSpecification; toDoNext = &tillTokenOrFallback; break; default: globalScope (ident, what); } }
void SymbolTable::checkAmbiguity(const Symbol& s) { // f(a : inteiro) // f(b : inteiro, ... resto) // -> declaracao ambigua if (!s.type()->isSubprogram()) { return; } SymbolList list = _table[globalScope()].findAllByLexeme(s.lexeme()); if (list.size() == 0) { return; } for (SymbolList::iterator it = list.begin(); it != list.end(); ++it) { if (!(*it).type()->isSubprogram()) { continue; } int size = (*it).type()->paramTypes().size(); if ((size + 1) == s.type()->paramTypes().size()) { Type *sss = s.type()->paramTypes().back(); bool bn = sss->isReticences(); if (s.type()->paramTypes().back()->isReticences()) { throw AmbiguousDeclarationException(s, *it); } } else if ((size - 1) == s.type()->paramTypes().size()) { if ((*it).type()->paramTypes().back()->isReticences()) { throw AmbiguousDeclarationException(s, *it); } } } }
/* Wait for waitedToken and jump to comeAfter or let * the globalScope handle declarations */ static void tillTokenOrFallback (vString * const ident, ocaToken what) { if (what == waitedToken) toDoNext = comeAfter; else globalScope (ident, what); }
/* parse : * | pattern pattern -> ... * or * pattern apttern apttern -> ... * we ignore all identifiers declared in the pattern, * because their scope is likely to be even more limited * than the let definitions. * Used after a match ... with, or a function ... or fun ... * because their syntax is similar. */ static void matchPattern (vString * const ident, ocaToken what) { /* keep track of [], as it * can be used in patterns and can * mean the end of match expression in * revised syntax */ static int braceCount = 0; switch (what) { case Tok_To: pushEmptyContext (&matchPattern); toDoNext = &mayRedeclare; break; case Tok_BRL: braceCount++; break; case OcaKEYWORD_value: popLastNamed (); globalScope (ident, what); break; case OcaKEYWORD_in: popLastNamed (); break; default: break; } }
/* handle : * exception ExceptionName of ... */ static void exceptionDecl (vString * const ident, ocaToken what) { if (what == OcaIDENTIFIER) { addTag (ident, K_EXCEPTION); } else /* probably ill-formed, give back to global scope */ { globalScope (ident, what); } toDoNext = &globalScope; }
QList<QgsExpressionContextScope*> QgsExpressionContextUtils::globalProjectLayerScopes( const QgsMapLayer* layer ) { QList<QgsExpressionContextScope*> scopes; scopes << globalScope(); QgsProject* project = QgsProject::instance(); // TODO: use project associated with layer if ( project ) scopes << projectScope( project ); if ( layer ) scopes << layerScope( layer ); return scopes; }
const Symbol& SymbolTable::getFirstSymbol(const std::string& lexeme) { //buscar primeiro no escopo atual, depois no global if (isInGlobalScope()) { return getFirstSymbol(lexeme, _scope); } else { try { return getFirstSymbol(lexeme, _scope); } catch( ... ) { return getFirstSymbol(lexeme, globalScope()); } } }
void CPPLexer::lexInput(std::string input, StyleDatabase& sdb) { str = &input; sdb.styleSegment.clear(); // Relex everything // TODO - lex from a position forward? styleDb = &sdb; pos = 0; try { globalScope(); } catch (std::out_of_range&) { // g_debug << "Parsing terminated!"; } }
/* Ensure a constructor is not a type path beginning * with a module */ static void constructorValidation (vString * const ident, ocaToken what) { switch (what) { case Tok_Op: /* if we got a '.' which is an operator */ toDoNext = &globalScope; popStrongContext (); needStrongPoping = FALSE; break; case OcaKEYWORD_of: /* OK, it must be a constructor :) */ if (vStringLength (tempIdent) > 0) { makeTagEntry (&tempTag); vStringClear (tempIdent); } toDoNext = &tillTokenOrFallback; comeAfter = &typeSpecification; waitedToken = Tok_Pipe; break; case Tok_Pipe: /* OK, it was a constructor :) */ if (vStringLength (tempIdent) > 0) { makeTagEntry (&tempTag); vStringClear (tempIdent); } toDoNext = &typeSpecification; break; default: /* and mean that we're not facing a module name */ if (vStringLength (tempIdent) > 0) { makeTagEntry (&tempTag); vStringClear (tempIdent); } toDoNext = &tillTokenOrFallback; comeAfter = &typeSpecification; waitedToken = Tok_Pipe; /* nothing in the context, discard it */ popStrongContext (); /* to be sure we use this token */ globalScope (ident, what); } }
QualifiedName Symbol::fullyQualifiedName() const { if (!isResolved()) resolve(); if (!scope()) return name(); String qname; const Symbol* g = globalScope(); for (const Symbol *s = this; s && s->scope(); s = s->scope()) { qname.insert(0, s->name().c_str()); if (s->scope() != g) qname.insert(0, "."); } return context()->internName(qname); }
/* Used at the beginning of a new scope (begin of a * definition, parenthesis...) to catch inner let * definition that may be in. */ static void mayRedeclare (vString * const ident, ocaToken what) { switch (what) { case OcaKEYWORD_value: /* let globalScope handle it */ globalScope (ident, what); break; case OcaKEYWORD_let: case OcaKEYWORD_val: toDoNext = localLet; break; case OcaKEYWORD_object: vStringClear (lastClass); pushContext (ContextStrong, ContextClass, &localScope, NULL /*voidName */ ); needStrongPoping = FALSE; toDoNext = &globalScope; break; case OcaKEYWORD_for: case OcaKEYWORD_while: toDoNext = &tillToken; waitedToken = OcaKEYWORD_do; comeAfter = &mayRedeclare; break; case OcaKEYWORD_try: toDoNext = &mayRedeclare; pushSoftContext (matchPattern, ident, ContextFunction); break; case OcaKEYWORD_fun: toDoNext = &matchPattern; break; /* Handle the special ;; from the OCaml * Top level */ case Tok_semi: default: toDoNext = &localScope; localScope (ident, what); } }
const Symbol& SymbolTable::getSymbol(const std::string& lexeme, const TypeList& params) { //deve considerar promocao de tipos // função f(a:real) ... // f(1); //resolve para a função "f_real" //checar: // f(a : inteiro) // f(b : real) // f(2); //primeira versão, sempre! SymbolList list = _table[globalScope()].findAllByLexeme(lexeme); if (list.size() == 0) { throw UndeclaredSymbolException(lexeme); } //try exact version for (SymbolList::iterator it = list.begin(); it != list.end(); ++it) { if ((*it).type()->isSubprogram() && (*it).type()->paramTypes().equals(params)) { return (*it); } } //tentando promocoes... for (SymbolList::iterator it = list.begin(); it != list.end(); ++it) { if ((*it).type()->isSubprogram() && (*it).type()->paramTypes().isLValueFor(params)) { return (*it); } } throw UnmatchedException(lexeme); // std::string id = Symbol::buildIdentifier(lexeme, params); // SymbolList::const_iterator it = _table[globalScope()].findByIdentifier(id); // if (it == _table[globalScope()].end()) { // throw UndeclaredSymbolException(id); // } // return (*it); }
String Symbol::mangledName() const { if (!scope()) return Context::encodeName(name()); String qname; const Symbol* g = globalScope(); if (g == this) return ""; if (scope()) { if (scope() != g) { qname = scope()->mangledName(); qname += "_"; } qname += context()->encodeName(name()); } return qname; }
void FuncDeclaration::semantic3reference(::FuncDeclaration *fd, Scope *sc) { if (fd->semanticRun >= PASSsemantic3) return; fd->semanticRun = PASSsemantic3; fd->semantic3Errors = false; auto FD = getFD(fd); if (!FD) return; const clang::FunctionDecl *Def; if (!FD->isInvalidDecl() && FD->hasBody(Def)) { auto globalSc = globalScope(sc->instantiatingModule()); declReferencer.Traverse(fd->loc, globalSc, Def->getBody()); if (auto Ctor = dyn_cast<clang::CXXConstructorDecl>(FD)) for (auto& Init: Ctor->inits()) declReferencer.Traverse(fd->loc, globalSc, Init->getInit()); } fd->semanticRun = PASSsemantic3done; }
Module* Symbol::globalModule() { return static_cast<Module*>(globalScope()); }
const Module* Symbol::globalModule() const { return static_cast<const Module*>(globalScope()); }
/* Parse expression. Well ignore it is more the case, * ignore all tokens except "shocking" keywords */ static void localScope (vString * const ident, ocaToken what) { switch (what) { case Tok_Pipe: case Tok_PARR: case Tok_BRR: case Tok_CurlR: popSoftContext (); break; /* Everything that `begin` has an `end` * as end is overloaded and signal many end * of things, we add an empty strong context to * avoid problem with the end. */ case OcaKEYWORD_begin: pushContext (ContextStrong, ContextBlock, &mayRedeclare, NULL); toDoNext = &mayRedeclare; break; case OcaKEYWORD_in: popLastNamed (); break; /* Ok, we got a '{', which is much likely to create * a record. We cannot treat it like other [ && (, * because it may contain the 'with' keyword and screw * everything else. */ case Tok_CurlL: toDoNext = &contextualTillToken; waitedToken = Tok_CurlR; comeAfter = &localScope; contextualTillToken (ident, what); break; /* Yeah imperative feature of OCaml, * a ';' like in C */ case Tok_semi: toDoNext = &mayRedeclare; break; case Tok_PARL: case Tok_BRL: pushEmptyContext (&localScope); toDoNext = &mayRedeclare; break; case OcaKEYWORD_and: popSoftContext (); if (toDoNext != &mayRedeclare) toDoNext(ident, what); else { pushEmptyContext(localScope); toDoNext = &localLet; } break; case OcaKEYWORD_else: case OcaKEYWORD_then: popSoftContext (); pushEmptyContext (&localScope); toDoNext = &mayRedeclare; break; case OcaKEYWORD_if: pushEmptyContext (&localScope); toDoNext = &mayRedeclare; break; case OcaKEYWORD_match: pushEmptyContext (&localScope); toDoNext = &mayRedeclare; break; case OcaKEYWORD_with: popSoftContext (); toDoNext = &matchPattern; pushEmptyContext (&matchPattern); break; case OcaKEYWORD_end: killCurrentState (); break; case OcaKEYWORD_fun: comeAfter = &mayRedeclare; toDoNext = &tillToken; waitedToken = Tok_To; break; case OcaKEYWORD_done: case OcaKEYWORD_val: /* doesn't care */ break; default: requestStrongPoping (); globalScope (ident, what); break; } }
std::unique_ptr<Stmt> FlowParser::callStmt() { // callStmt ::= NAME ['(' exprList ')' | exprList] (';' | LF) // | NAME '=' expr [';' | LF] // NAME may be a builtin-function, builtin-handler, handler-name, or variable. FNTRACE(); FlowLocation loc(location()); std::string name = stringValue(); nextToken(); // IDENT std::unique_ptr<Stmt> stmt; Symbol* callee = scope()->lookup(name, Lookup::All); if (!callee) { // XXX assume that given symbol is a auto forward-declared handler. callee = (Handler*) globalScope()->appendSymbol(std::make_unique<Handler>(name, loc)); } bool callArgs = false; switch (callee->type()) { case Symbol::Variable: { // var '=' expr (';' | LF) if (!consume(FlowToken::Assign)) return nullptr; std::unique_ptr<Expr> value = expr(); if (!value) return nullptr; stmt = std::make_unique<AssignStmt>(static_cast<Variable*>(callee), std::move(value), loc.update(end())); break; } case Symbol::BuiltinHandler: case Symbol::BuiltinFunction: stmt = std::make_unique<CallStmt>(loc, (Callable*) callee); callArgs = true; break; case Symbol::Handler: stmt = std::make_unique<CallStmt>(loc, (Callable*) callee); break; default: break; } if (callArgs) { CallStmt* callStmt = static_cast<CallStmt*>(stmt.get()); if (token() == FlowToken::RndOpen) { nextToken(); ExprList args; bool rv = listExpr(args); consume(FlowToken::RndClose); if (!rv) return nullptr; callStmt->setArgs(std::move(args)); } else if (lexer_->line() == loc.begin.line) { ExprList args; if (!listExpr(args)) return nullptr; callStmt->setArgs(std::move(args)); } // match call parameters FlowVM::Signature sig; sig.setName(name); sig.setReturnType(callStmt->callee()->signature().returnType()); // XXX cheetah std::vector<FlowType> argTypes; for (const auto& arg: callStmt->args()) { argTypes.push_back(arg->getType()); } sig.setArgs(argTypes); if (sig != callStmt->callee()->signature()) { reportError("Callee parameter type signature mismatch: %s passed, but %s expected.\n", sig.to_s().c_str(), callStmt->callee()->signature().to_s().c_str()); return nullptr; } } switch (token()) { case FlowToken::If: case FlowToken::Unless: return postscriptStmt(std::move(stmt)); case FlowToken::Semicolon: // stmt ';' nextToken(); stmt->location().update(end()); return stmt; default: if (stmt->location().end.line != lexer_->line()) return stmt; reportUnexpectedToken(); return nullptr; } }
// primaryExpr ::= NUMBER // | STRING // | variable // | function '(' exprList ')' // | '(' expr ')' std::unique_ptr<Expr> FlowParser::primaryExpr() { FNTRACE(); static struct { const char* ident; long long nominator; long long denominator; } units[] = { { "byte", 1, 1 }, { "kbyte", 1024llu, 1 }, { "mbyte", 1024llu * 1024, 1 }, { "gbyte", 1024llu * 1024 * 1024, 1 }, { "tbyte", 1024llu * 1024 * 1024 * 1024, 1 }, { "bit", 1, 8 }, { "kbit", 1024llu, 8 }, { "mbit", 1024llu * 1024, 8 }, { "gbit", 1024llu * 1024 * 1024, 8 }, { "tbit", 1024llu * 1024 * 1024 * 1024, 8 }, { "sec", 1, 1 }, { "min", 60llu, 1 }, { "hour", 60llu * 60, 1 }, { "day", 60llu * 60 * 24, 1 }, { "week", 60llu * 60 * 24 * 7, 1 }, { "month", 60llu * 60 * 24 * 30, 1 }, { "year", 60llu * 60 * 24 * 365, 1 }, { nullptr, 1, 1 } }; FlowLocation loc(location()); switch (token()) { case FlowToken::Ident: { std::string name = stringValue(); nextToken(); Symbol* symbol = scope()->lookup(name, Lookup::All); if (!symbol) { // XXX assume that given symbol is a auto forward-declared handler. Handler* href = (Handler*) globalScope()->appendSymbol(std::make_unique<Handler>(name, loc)); return std::make_unique<HandlerRefExpr>(href, loc); } if (auto variable = dynamic_cast<Variable*>(symbol)) return std::make_unique<VariableExpr>(variable, loc); if (auto handler = dynamic_cast<Handler*>(symbol)) return std::make_unique<HandlerRefExpr>(handler, loc); if (symbol->type() == Symbol::BuiltinFunction) { if (token() != FlowToken::RndOpen) return std::make_unique<FunctionCallExpr>((BuiltinFunction*) symbol, ExprList()/*args*/, loc); nextToken(); ExprList args; bool rv = listExpr(args); consume(FlowToken::RndClose); if (!rv) return nullptr; return std::make_unique<FunctionCallExpr>((BuiltinFunction*) symbol, std::move(args), loc); } reportError("Unsupported symbol type of '%s' in expression.", name.c_str()); return nullptr; } case FlowToken::Boolean: { std::unique_ptr<BoolExpr> e = std::make_unique<BoolExpr>(booleanValue(), loc); nextToken(); return std::move(e); } case FlowToken::RegExp: { std::unique_ptr<RegExpExpr> e = std::make_unique<RegExpExpr>(RegExp(stringValue()), loc); nextToken(); return std::move(e); } case FlowToken::InterpolatedStringFragment: return interpolatedStr(); case FlowToken::String: case FlowToken::RawString: { std::unique_ptr<StringExpr> e = std::make_unique<StringExpr>(stringValue(), loc); nextToken(); return std::move(e); } case FlowToken::Number: { // NUMBER [UNIT] auto number = numberValue(); nextToken(); if (token() == FlowToken::Ident) { std::string sv(stringValue()); for (size_t i = 0; units[i].ident; ++i) { if (sv == units[i].ident || (sv[sv.size() - 1] == 's' && sv.substr(0, sv.size() - 1) == units[i].ident)) { nextToken(); // UNIT number = number * units[i].nominator / units[i].denominator; loc.update(end()); break; } } } return std::make_unique<NumberExpr>(number, loc); } case FlowToken::IP: { std::unique_ptr<IPAddressExpr> e = std::make_unique<IPAddressExpr>(lexer_->ipValue(), loc); nextToken(); return std::move(e); } case FlowToken::Cidr: { std::unique_ptr<CidrExpr> e = std::make_unique<CidrExpr>(lexer_->cidr(), loc); nextToken(); return std::move(e); } case FlowToken::StringType: case FlowToken::NumberType: case FlowToken::BoolType: return castExpr(); case FlowToken::Begin: { // lambda-like inline function ref char name[64]; static unsigned long i = 0; ++i; snprintf(name, sizeof(name), "__lambda_%lu", i); FlowLocation loc = location(); auto st = std::make_unique<SymbolTable>(scope(), name); enter(st.get()); std::unique_ptr<Stmt> body = compoundStmt(); leave(); if (!body) return nullptr; loc.update(body->location().end); Handler* handler = new Handler(name, std::move(st), std::move(body), loc); // TODO (memory leak): add handler to unit's global scope, i.e. via: // - scope()->rootScope()->insert(handler); // - unit_->scope()->insert(handler); // to get free'd return std::make_unique<HandlerRefExpr>(handler, loc); } case FlowToken::RndOpen: { nextToken(); std::unique_ptr<Expr> e = expr(); consume(FlowToken::RndClose); e->setLocation(loc.update(end())); return e; } default: TRACE(1, "Expected primary expression. Got something... else."); reportUnexpectedToken(); return nullptr; } }
bool SymbolTable::isInGlobalScope() { return globalScope() == _scope; }
void StreamType::load() { USING_MU_FUNCTION_SYMBOLS; Symbol *s = scope(); MuLangContext* context = (MuLangContext*)globalModule()->context(); Context* c = context; String tname = fullyQualifiedName(); String rname = tname + "&"; const char* tn = tname.c_str(); const char* rn = rname.c_str(); s->addSymbols( new ReferenceType(c, "stream&", this), new Function(c, "stream", BaseFunctions::dereference, Cast, Return, tn, Args, rn, End), EndArguments); globalScope()->addSymbols( new Function(c, "print", StreamType::print, None, Return, "void", Args, tn, End), new Function(c, "=", BaseFunctions::assign, AsOp, Return, rn, Args, rn, tn, End), new Function(c, "!", StreamType::eval, None, Return, "bool", Args, tn, End), new Function(c, "bool", StreamType::toBool, None, Return, "bool", Args, tn, End), EndArguments); addSymbols( new SymbolicConstant(c, "GoodBit", "int", Value(int(ios::goodbit))), new SymbolicConstant(c, "BadBit", "int", Value(int(ios::badbit))), new SymbolicConstant(c, "FailBit", "int", Value(int(ios::failbit))), new SymbolicConstant(c, "EofBit", "int", Value(int(ios::eofbit))), new SymbolicConstant(c, "Beginning", "int", Value(int(ios::beg))), new SymbolicConstant(c, "Current", "int", Value(int(ios::cur))), new SymbolicConstant(c, "End", "int", Value(int(ios::end))), new SymbolicConstant(c, "Append", "int", Value(int(ios::app))), new SymbolicConstant(c, "AtEnd", "int", Value(int(ios::ate))), new SymbolicConstant(c, "Binary", "int", Value(int(ios::binary))), new SymbolicConstant(c, "In", "int", Value(int(ios::in))), new SymbolicConstant(c, "Out", "int", Value(int(ios::out))), new SymbolicConstant(c, "Truncate", "int", Value(int(ios::trunc))), new Function(c, "bad", StreamType::bad, None, Return, "bool", Args, tn, End), new Function(c, "eof", StreamType::eof, None, Return, "bool", Args, tn, End), new Function(c, "fail", StreamType::fail, None, Return, "bool", Args, tn, End), new Function(c, "good", StreamType::good, None, Return, "bool", Args, tn, End), new Function(c, "clear", StreamType::clear, None, Return, "void", Args, tn, End), new Function(c, "clear", StreamType::clear, None, Return, "void", Args, tn, "int", End), new Function(c, "rdstate", StreamType::rdstate, None, Return, "int", Args, tn, End), new Function(c, "setstate", StreamType::setstate, None, Return, "void", Args, tn, "int", End), EndArguments ); }
void SymbolTable::setGlobalScope() { _scope = globalScope(); }
SymbolList SymbolTable::getSymbols(const std::string& lexeme) { return _table[globalScope()].findAllByLexeme(lexeme); }