本文整理汇总了C++中ParseNode类的典型用法代码示例。如果您正苦于以下问题:C++ ParseNode类的具体用法?C++ ParseNode怎么用?C++ ParseNode使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了ParseNode类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: CloneParseTree
/*
* This function assumes the cloned tree is for use in the same statement and
* binding context as the original tree.
*/
static ParseNode *
CloneParseTree(ParseNode *opn, Parser *parser)
{
TreeContext *tc = parser->tc;
JS_CHECK_RECURSION(tc->sc->context, return NULL);
ParseNode *pn = parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setInParens(opn->isInParens());
pn->setDefn(opn->isDefn());
pn->setUsed(opn->isUsed());
switch (pn->getArity()) {
#define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
case PN_FUNC:
NULLCHECK(pn->pn_funbox =
parser->newFunctionBox(opn->pn_funbox->object, pn, tc, opn->pn_funbox->strictModeState));
NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, parser));
pn->pn_cookie = opn->pn_cookie;
pn->pn_dflags = opn->pn_dflags;
pn->pn_blockid = opn->pn_blockid;
break;
case PN_LIST:
pn->makeEmpty();
for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
ParseNode *pn2;
NULLCHECK(pn2 = CloneParseTree(opn2, parser));
pn->append(pn2);
}
pn->pn_xflags = opn->pn_xflags;
break;
case PN_TERNARY:
NULLCHECK(pn->pn_kid1 = CloneParseTree(opn->pn_kid1, parser));
NULLCHECK(pn->pn_kid2 = CloneParseTree(opn->pn_kid2, parser));
NULLCHECK(pn->pn_kid3 = CloneParseTree(opn->pn_kid3, parser));
break;
case PN_BINARY:
NULLCHECK(pn->pn_left = CloneParseTree(opn->pn_left, parser));
if (opn->pn_right != opn->pn_left)
NULLCHECK(pn->pn_right = CloneParseTree(opn->pn_right, parser));
else
pn->pn_right = pn->pn_left;
pn->pn_pval = opn->pn_pval;
pn->pn_iflags = opn->pn_iflags;
break;
case PN_UNARY:
NULLCHECK(pn->pn_kid = CloneParseTree(opn->pn_kid, parser));
pn->pn_hidden = opn->pn_hidden;
break;
case PN_NAME:
// PN_NAME could mean several arms in pn_u, so copy the whole thing.
pn->pn_u = opn->pn_u;
if (opn->isUsed()) {
/*
* The old name is a use of its pn_lexdef. Make the clone also be a
* use of that definition.
*/
Definition *dn = pn->pn_lexdef;
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
} else if (opn->pn_expr) {
NULLCHECK(pn->pn_expr = CloneParseTree(opn->pn_expr, parser));
/*
* If the old name is a definition, the new one has pn_defn set.
* Make the old name a use of the new node.
*/
if (opn->isDefn()) {
opn->setDefn(false);
LinkUseToDef(opn, (Definition *) pn);
}
}
break;
case PN_NAMESET:
pn->pn_names = opn->pn_names;
NULLCHECK(pn->pn_tree = CloneParseTree(opn->pn_tree, parser));
break;
case PN_NULLARY:
// Even PN_NULLARY may have data (xmlpi for E4X -- what a botch).
pn->pn_u = opn->pn_u;
break;
#undef NULLCHECK
}
//.........这里部分代码省略.........
示例2: doParse
// pre: root != NULL
void doParse(ParseNode *root, std::string inFileName, std::string outBaseName)
{
std::map<std::string, std::string> firstManualToken;
FaSymbolTable symTab;
FaRuleIr ruleIr(&symTab);
// Iterate thru children of start symbol.
for(ParseNode::iterator_type i = root->begin(); i != root->end(); ++i)
{
ParseNode *statement = *i;
ParseNode *statementHead = *statement->begin();
std::string statementHeadText = statementHead->getTokenText();
if(statementHeadText.empty())
{
// name "::=" alternate { '|' alternate } ';'
// name ::= IDENT | "start" ;
///std::cout << "[name]" << std::endl;
std::string ruleName = (*statementHead->begin())->getTokenText();
ParseNode::iterator_type j = statement->begin();
++j; // skip ruleName
++j; // skip "::="
for(;;)
{
ParseNode *alternate = *j;
parseAlternate(symTab, ruleIr, alternate, ruleName);
++j; // skip alternate
if((*j)->getTokenText() != "|")
break; // found ';' at end
++j; // skip '|'
}
}
else
if(statementHeadText == "token")
{
for(ParseNode::iterator_type j = ++statement->begin(); j != statement->end(); ++j)
{
std::string s = (*j)->getTokenText();
if(s == ";")
break;
ruleIr.addToken(s);
}
}
else
if(statementHeadText == "keyword")
{
std::string s1 = (*(++statement->begin()))->getTokenText();
std::string s2 = (*(++(++statement->begin())))->getTokenText();
ruleIr.addKeyword(s1, s2);
}
else
if(statementHeadText == "copyright")
{
ruleIr.setCopyright(unquote((*(++statement->begin()))->getTokenText()));
}
else
if(statementHeadText == "prefix")
{
ruleIr.setPrefix(unquote((*(++statement->begin()))->getTokenText()));
}
else
if(statementHeadText == "manual")
{
ParseNode::iterator_type j = ++statement->begin();
std::string s0 = (*j)->getTokenText();
++j;
std::string s1 = unquote((*j)->getTokenText());
++j;
ruleIr.addToken(s0);
firstManualToken[s0] = s1;
if(s1.empty() || (s1.size() & 1) != 0)
{
std::string msg = "invalid manual token definition (both string literals must be nonempty and even in length)";
throw ParseSpecificError((*i)->getLine(), (*i)->getFile(), msg);
}
}
}
std::string err = ruleIr.convertGrammar();
if(!err.empty())
{
std::cerr << "error: " << inFileName << ": " << err << std::endl;
throw ParseError();
}
std::string fn1 = "out_" + outBaseName + "_parser.h";
std::string fn2 = "out_" + outBaseName + "_header.h";
std::string fn3 = "out_" + outBaseName + "_lexer.h";
std::ofstream fo1(fn1.c_str());
ruleIr.writeParser(fo1, fn1);
std::ofstream fo2(fn2.c_str());
ruleIr.writeHeader(fo2, fn2);
std::ofstream fo3(fn3.c_str());
ruleIr.writeLexer(fo3, fn3, firstManualToken);
}
示例3: FindFunArgs
/*
* Mark as funargs any functions that reach up to one or more upvars across an
* already-known funarg. The parser will flag the o_m lambda as a funarg in:
*
* function f(o, p) {
* o.m = function o_m(a) {
* function g() { return p; }
* function h() { return a; }
* return g() + h();
* }
* }
*
* but without this extra marking phase, function g will not be marked as a
* funarg since it is called from within its parent scope. But g reaches up to
* f's parameter p, so if o_m escapes f's activation scope, g does too and
* cannot assume that p's stack slot is still alive. In contast function h
* neither escapes nor uses an upvar "above" o_m's level.
*
* If function g itself contained lambdas that contained non-lambdas that reach
* up above its level, then those non-lambdas would have to be marked too. This
* process is potentially exponential in the number of functions, but generally
* not so complex. But it can't be done during a single recursive traversal of
* the funbox tree, so we must use a work queue.
*
* Return the minimal "skipmin" for funbox and its siblings. This is the delta
* between the static level of the bodies of funbox and its peers (which must
* be funbox->level + 1), and the static level of the nearest upvar among all
* the upvars contained by funbox and its peers. If there are no upvars, return
* FREE_STATIC_LEVEL. Thus this function never returns 0.
*/
static uintN
FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue)
{
uintN allskipmin = UpvarCookie::FREE_LEVEL;
do {
ParseNode *fn = funbox->node;
JS_ASSERT(fn->isArity(PN_FUNC));
int fnlevel = level;
/*
* An eval can leak funbox, functions along its ancestor line, and its
* immediate kids. Since FindFunArgs uses DFS and the parser propagates
* TCF_FUN_HEAVYWEIGHT bottom up, funbox's ancestor function nodes have
* already been marked as funargs by this point. Therefore we have to
* flag only funbox->node and funbox->kids' nodes here.
*
* Generators need to be treated in the same way. Even if the value
* of a generator function doesn't escape, anything defined or referred
* to inside the generator can escape through a call to the generator.
* We could imagine doing static analysis to track the calls and see
* if any iterators or values returned by iterators escape, but that
* would be hard, so instead we just assume everything might escape.
*/
if (funbox->tcflags & (TCF_FUN_HEAVYWEIGHT | TCF_FUN_IS_GENERATOR)) {
fn->setFunArg();
for (FunctionBox *kid = funbox->kids; kid; kid = kid->siblings)
kid->node->setFunArg();
}
/*
* Compute in skipmin the least distance from fun's static level up to
* an upvar, whether used directly by fun, or indirectly by a function
* nested in fun.
*/
uintN skipmin = UpvarCookie::FREE_LEVEL;
ParseNode *pn = fn->pn_body;
if (pn->isKind(PNK_UPVARS)) {
AtomDefnMapPtr &upvars = pn->pn_names;
JS_ASSERT(upvars->count() != 0);
for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
Definition *defn = r.front().value();
Definition *lexdep = defn->resolve();
if (!lexdep->isFreeVar()) {
uintN upvarLevel = lexdep->frameLevel();
if (int(upvarLevel) <= fnlevel)
fn->setFunArg();
uintN skip = (funbox->level + 1) - upvarLevel;
if (skip < skipmin)
skipmin = skip;
}
}
}
/*
* If this function escapes, whether directly (the parser detects such
* escapes) or indirectly (because this non-escaping function uses an
* upvar that reaches across an outer function boundary where the outer
* function escapes), enqueue it for further analysis, and bump fnlevel
* to trap any non-escaping children.
*/
if (fn->isFunArg()) {
queue->push(funbox);
fnlevel = int(funbox->level);
}
//.........这里部分代码省略.........
示例4: ssh
// Compile a JS function body, which might appear as the value of an event
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
bool
frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length,
bool isAsmJSRecompile)
{
if (!CheckLength(cx, length))
return false;
ScriptSource *ss = cx->new_<ScriptSource>();
if (!ss)
return false;
if (options.filename && !ss->setFilename(cx, options.filename))
return false;
ScriptSourceHolder ssh(ss);
SourceCompressionToken sct(cx);
JS_ASSERT(options.sourcePolicy != CompileOptions::LAZY_SOURCE);
if (options.sourcePolicy == CompileOptions::SAVE_SOURCE) {
if (!ss->setSourceCopy(cx, chars, length, true, &sct))
return false;
}
options.setCompileAndGo(false);
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true);
if (!parser.init())
return false;
parser.sct = &sct;
JS_ASSERT(fun);
fun->setArgCount(formals.length());
/* FIXME: make Function format the source for a function definition. */
ParseNode *fn = CodeNode::create(PNK_FUNCTION, &parser.handler);
if (!fn)
return false;
fn->pn_body = NULL;
fn->pn_funbox = NULL;
fn->pn_cookie.makeFree();
ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &parser.handler);
if (!argsbody)
return false;
argsbody->setOp(JSOP_NOP);
argsbody->makeEmpty();
fn->pn_body = argsbody;
Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), false, options,
/* staticLevel = */ 0, ss,
/* sourceStart = */ 0, length));
if (!script)
return false;
// If the context is strict, immediately parse the body in strict
// mode. Otherwise, we parse it normally. If we see a "use strict"
// directive, we backup and reparse it as strict.
TokenStream::Position start;
parser.tokenStream.tell(&start);
bool initiallyStrict = StrictModeFromContext(cx);
bool becameStrict;
FunctionBox *funbox;
ParseNode *pn = parser.standaloneFunctionBody(fun, formals, script, fn, &funbox,
initiallyStrict, &becameStrict);
if (!pn) {
if (initiallyStrict || !becameStrict || parser.tokenStream.hadError())
return false;
// Reparse in strict mode.
parser.tokenStream.seek(start);
pn = parser.standaloneFunctionBody(fun, formals, script, fn, &funbox,
/* strict = */ true);
if (!pn)
return false;
}
if (!NameFunctions(cx, pn))
return false;
if (fn->pn_body) {
JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
fn->pn_body->append(pn);
fn->pn_body->pn_pos = pn->pn_pos;
pn = fn->pn_body;
}
bool generateBytecode = true;
#ifdef JS_ION
JS_ASSERT_IF(isAsmJSRecompile, fn->pn_funbox->useAsm);
if (fn->pn_funbox->useAsm && !isAsmJSRecompile) {
RootedFunction moduleFun(cx);
if (!CompileAsmJS(cx, parser.tokenStream, fn, options,
ss, /* bufStart = */ 0, /* bufEnd = */ length,
&moduleFun))
return false;
if (moduleFun) {
funbox->object = moduleFun;
fun.set(moduleFun); // replace the existing function with the LinkAsmJS native
generateBytecode = false;
//.........这里部分代码省略.........
示例5: source
//.........这里部分代码省略.........
if (!bce.init())
return UnrootedScript(NULL);
/* If this is a direct call to eval, inherit the caller's strictness. */
if (callerFrame && callerFrame->script()->strict)
globalsc.strict = true;
if (options.compileAndGo) {
if (source) {
/*
* Save eval program source in script->atoms[0] for the
* eval cache (see EvalCacheLookup in jsobj.cpp).
*/
JSAtom *atom = AtomizeString(cx, source);
jsatomid _;
if (!atom || !bce.makeAtomIndex(atom, &_))
return UnrootedScript(NULL);
}
if (callerFrame && callerFrame->isFunctionFrame()) {
/*
* An eval script in a caller frame needs to have its enclosing
* function captured in case it refers to an upvar, and someone
* wishes to decompile it while it's running.
*/
JSFunction *fun = callerFrame->fun();
ObjectBox *funbox = parser.newFunctionBox(fun, &pc, fun->strict());
if (!funbox)
return UnrootedScript(NULL);
bce.objectList.add(funbox);
}
}
ParseNode *pn;
#if JS_HAS_XML_SUPPORT
pn = NULL;
bool onlyXML;
onlyXML = true;
#endif
TokenStream &tokenStream = parser.tokenStream;
bool canHaveDirectives = true;
for (;;) {
TokenKind tt = tokenStream.peekToken(TSF_OPERAND);
if (tt <= TOK_EOF) {
if (tt == TOK_EOF)
break;
JS_ASSERT(tt == TOK_ERROR);
return UnrootedScript(NULL);
}
pn = parser.statement();
if (!pn)
return UnrootedScript(NULL);
if (canHaveDirectives) {
if (!parser.maybeParseDirective(pn, &canHaveDirectives))
return UnrootedScript(NULL);
}
if (!FoldConstants(cx, pn, &parser))
return UnrootedScript(NULL);
if (!NameFunctions(cx, pn))
return UnrootedScript(NULL);
if (!EmitTree(cx, &bce, pn))
示例6: parser
// Compile a JS function body, which might appear as the value of an event
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
bool
frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
JSPrincipals *principals, JSPrincipals *originPrincipals,
Bindings *bindings, const jschar *chars, size_t length,
const char *filename, unsigned lineno, JSVersion version)
{
Parser parser(cx, principals, originPrincipals, chars, length, filename, lineno, version,
/* callerFrame = */ NULL, /* foldConstants = */ true,
/* compileAndGo = */ false);
if (!parser.init())
return false;
JS_ASSERT(fun);
SharedContext funsc(cx, /* scopeChain = */ NULL, fun, /* funbox = */ NULL);
unsigned staticLevel = 0;
TreeContext funtc(&parser, &funsc, staticLevel);
if (!funtc.init())
return false;
GlobalObject *globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
Rooted<JSScript*> script(cx);
script = JSScript::Create(cx, /* savedCallerFun = */ false, principals, originPrincipals,
/* compileAndGo = */ false, /* noScriptRval = */ false,
globalObject, version, staticLevel);
if (!script)
return false;
BytecodeEmitter funbce(&parser, &funsc, script, lineno);
if (!funbce.init())
return false;
funsc.bindings.transfer(cx, bindings);
fun->setArgCount(funsc.bindings.numArgs());
if (!GenerateBlockId(&funsc, funsc.bodyid))
return false;
/* FIXME: make Function format the source for a function definition. */
ParseNode *fn = FunctionNode::create(PNK_NAME, &parser);
if (!fn)
return false;
fn->pn_body = NULL;
fn->pn_cookie.makeFree();
ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &parser);
if (!argsbody)
return false;
argsbody->setOp(JSOP_NOP);
argsbody->makeEmpty();
fn->pn_body = argsbody;
unsigned nargs = fun->nargs;
if (nargs) {
/*
* NB: do not use AutoLocalNameArray because it will release space
* allocated from cx->tempLifoAlloc by DefineArg.
*/
BindingNames names(cx);
if (!funsc.bindings.getLocalNameArray(cx, &names))
return false;
for (unsigned i = 0; i < nargs; i++) {
if (!DefineArg(fn, names[i].maybeAtom, i, &parser))
return false;
}
}
/*
* After we're done parsing, we must fold constants, analyze any nested
* functions, and generate code for this function, including a stop opcode
* at the end.
*/
ParseNode *pn = parser.functionBody(Parser::StatementListBody);
if (!pn)
return false;
if (!parser.tokenStream.matchToken(TOK_EOF)) {
parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
return false;
}
if (!FoldConstants(cx, pn, &parser))
return false;
if (!AnalyzeFunctions(&parser))
return false;
if (fn->pn_body) {
JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
fn->pn_body->append(pn);
fn->pn_body->pn_pos = pn->pn_pos;
pn = fn->pn_body;
}
if (!EmitFunctionScript(cx, &funbce, pn))
return false;
//.........这里部分代码省略.........
示例7: SetFunctionKinds
static void
SetFunctionKinds(FunctionBox *funbox, bool *isHeavyweight, bool topInFunction, bool isDirectEval)
{
for (; funbox; funbox = funbox->siblings) {
ParseNode *fn = funbox->node;
if (!fn)
continue;
ParseNode *pn = fn->pn_body;
if (!pn)
continue;
if (funbox->kids)
SetFunctionKinds(funbox->kids, isHeavyweight, topInFunction, isDirectEval);
JSFunction *fun = funbox->function();
JS_ASSERT(fun->kind() == JSFUN_INTERPRETED);
if (funbox->funIsHeavyweight()) {
/* nothing to do */
} else if (isDirectEval || funbox->inAnyDynamicScope()) {
/*
* Either we are in a with-block or a function scope that is
* subject to direct eval; or we are compiling strict direct eval
* code.
*
* In either case, fun may reference names that are not bound but
* are not necessarily global either. (In the strict direct eval
* case, we could bind them, but currently do not bother; see
* the comment about strict mode code in BindTopLevelVar.)
*/
JS_ASSERT(!fun->isNullClosure());
} else {
bool hasUpvars = false;
if (pn->isKind(PNK_UPVARS)) {
AtomDefnMapPtr upvars = pn->pn_names;
JS_ASSERT(!upvars->empty());
/* Determine whether the this function contains upvars. */
for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
if (!r.front().value()->resolve()->isFreeVar()) {
hasUpvars = true;
break;
}
}
}
if (!hasUpvars) {
/* No lexical dependencies => null closure, for best performance. */
fun->setKind(JSFUN_NULL_CLOSURE);
}
}
if (fun->kind() == JSFUN_INTERPRETED && pn->isKind(PNK_UPVARS)) {
/*
* We loop again over all upvars, and for each non-free upvar,
* ensure that its containing function has been flagged as
* heavyweight.
*
* The emitter must see funIsHeavyweight() accurately before
* generating any code for a tree of nested functions.
*/
AtomDefnMapPtr upvars = pn->pn_names;
JS_ASSERT(!upvars->empty());
for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
Definition *defn = r.front().value();
Definition *lexdep = defn->resolve();
if (!lexdep->isFreeVar())
FlagHeavyweights(lexdep, funbox, isHeavyweight, topInFunction);
}
}
}
}
示例8: printHelp
void printHelp(ParseNode const& p) {
printf(" %12s %s\n", p.token(), p.helpString().c_str());
}
示例9: node_decl
NodeDeclPtr XmlSceneParser::Impl::PrepareNode (const ParseNode& decl)
{
try
{
//попытка найти параметры в кеше
if (NodeDeclPtr* node_decl_ptr = cache.FindValue<NodeDeclPtr> (decl))
return *node_decl_ptr;
NodeDeclPtr node_decl (new NodeDecl, false);
//парсинг базовых свойств
node_decl->name = get<const char*> (decl, "id", "");
//парсинг точки поворота
if (decl.First ("pivot"))
{
stl::auto_ptr<NodeDecl::Pivot> pivot (new NodeDecl::Pivot);
ParseAttribute (decl, "pivot", pivot->position);
pivot->has_orientation_pivot = strcmp (get<const char*> (decl, "orientation_pivot", "true"), "true") == 0;
pivot->has_scale_pivot = strcmp (get<const char*> (decl, "scale_pivot", "true"), "true") == 0;
node_decl->pivot = pivot;
}
//парсинг трансформаций
node_decl->is_world_transform = strcmp (get<const char*> (decl, "bind_space", "local"), "world") == 0;
if (ParseNode tm_node = decl.First ("transform"))
{
math::mat4f tm;
ParseAttribute (tm_node, "", tm);
affine_decompose (tm, node_decl->position, node_decl->orientation, node_decl->scale);
}
else
{
ParseAttribute (decl, "position", node_decl->position);
ParseAttribute (decl, "scale", node_decl->scale);
if (ParseNode rotation_node = decl.First ("rotation"))
{
float rotation [3] = {0.0f, 0.0f, 0.0f};
ParseAttribute (rotation_node, "", 3, &rotation [0]);
node_decl->orientation = to_quat (degree (rotation [0]), degree (rotation [1]), degree (rotation [2]));
}
else
{
ParseAttribute (decl, "orientation", node_decl->orientation);
}
}
node_decl->orientation_inherit = strcmp (get<const char*> (decl, "orientation_inherit", "true"), "true") == 0;
node_decl->scale_inherit = strcmp (get<const char*> (decl, "scale_inherit", "true"), "true") == 0;
//парсинг пользовательских свойств
PropertyMap* properties = 0;
if (decl.First ("property"))
node_decl->properties.reset (properties = new PropertyMap);
for (Parser::NamesakeIterator iter = decl.First ("property"); iter; ++iter)
{
ParseNode property_decl = *iter;
const char* name = get<const char*> (property_decl, "name");
PropertyType type = get_property_type (property_decl.First ("type"));
size_t property_index = properties->AddProperty (name, type, 1);
stl::string value = get<const char*> (property_decl, "value");
properties->SetProperty (property_index, value.c_str ());
}
//парсинг after node
if (ParseNode before_node_decl = decl.First ("before_node"))
{
node_decl->before_node.reset (new stl::string);
*node_decl->before_node = get<const char*> (before_node_decl, "");
}
//парсинг привязки к родителю
if (ParseNode parent_name_decl = decl.First ("parent"))
{
node_decl->parent_name.reset (new stl::string);
*node_decl->parent_name = get<const char*> (parent_name_decl, "");
//.........这里部分代码省略.........
示例10: gen_stmt
ParseNode gen_stmt(const ParseNode & content, const std::string & rules) {
sprintf(codegen_buf, rules.c_str() , content.fs.CurrentTerm.what.c_str());
ParseNode newnode = ParseNode(gen_flex(Term{ TokenMeta::NT_STATEMENT, string(codegen_buf) }), nullptr);
newnode.addchild(new ParseNode(content));
return newnode;
}
示例11: skip
// Compile a JS function body, which might appear as the value of an event
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
bool
frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
const AutoNameVector &formals, const jschar *chars, size_t length,
bool isAsmJSRecompile)
{
SkipRoot skip(cx, &chars);
if (!CheckLength(cx, length))
return false;
ScriptSource *ss = cx->new_<ScriptSource>();
if (!ss)
return false;
if (options.filename && !ss->setFilename(cx, options.filename))
return false;
JS::RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, ss));
if (!sourceObject)
return false;
SourceCompressionToken sct(cx);
JS_ASSERT(options.sourcePolicy != CompileOptions::LAZY_SOURCE);
if (options.sourcePolicy == CompileOptions::SAVE_SOURCE) {
if (!ss->setSourceCopy(cx, chars, length, true, &sct))
return false;
}
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (options.canLazilyParse) {
syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false,
(Parser<SyntaxParseHandler> *) NULL,
(LazyScript *) NULL);
}
JS_ASSERT(!options.forEval);
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true,
options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
parser.sct = &sct;
JS_ASSERT(fun);
fun->setArgCount(formals.length());
/* FIXME: make Function format the source for a function definition. */
ParseNode *fn = CodeNode::create(PNK_FUNCTION, &parser.handler);
if (!fn)
return false;
fn->pn_body = NULL;
fn->pn_funbox = NULL;
fn->pn_cookie.makeFree();
ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &parser.handler);
if (!argsbody)
return false;
argsbody->setOp(JSOP_NOP);
argsbody->makeEmpty();
fn->pn_body = argsbody;
Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), false, options,
/* staticLevel = */ 0, sourceObject,
/* sourceStart = */ 0, length));
if (!script)
return false;
// If the context is strict, immediately parse the body in strict
// mode. Otherwise, we parse it normally. If we see a "use strict"
// directive, we backup and reparse it as strict.
TokenStream::Position start(parser.keepAtoms);
parser.tokenStream.tell(&start);
bool strict = StrictModeFromContext(cx);
bool becameStrict;
FunctionBox *funbox;
ParseNode *pn;
while (true) {
pn = parser.standaloneFunctionBody(fun, formals, script, fn, &funbox,
strict, &becameStrict);
if (pn)
break;
if (parser.hadAbortedSyntaxParse()) {
// Hit some unrecoverable ambiguity during an inner syntax parse.
// Syntax parsing has now been disabled in the parser, so retry
// the parse.
parser.clearAbortedSyntaxParse();
} else {
// If the function became strict, reparse in strict mode.
if (strict || !becameStrict || parser.tokenStream.hadError())
return false;
strict = true;
}
parser.tokenStream.seek(start);
}
if (!NameFunctions(cx, pn))
return false;
if (fn->pn_body) {
JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
//.........这里部分代码省略.........
示例12: gen_paramtable
ParseNode gen_paramtable(ParseNode & paramtable_elem, ParseNode & paramtable) {
ParseNode newnode = ParseNode(gen_flex(Term{ TokenMeta::NT_PARAMTABLE, "" }), nullptr);
bool dimen1 = false, dimen2 = false, arg1 = false, arg2 = false, va1 = false, va2 = false;;
if (paramtable_elem.fs.CurrentTerm.token == TokenMeta::NT_DIMENSLICE) {
dimen1 = true;
}
if (paramtable_elem.fs.CurrentTerm.token == TokenMeta::NT_ARGTABLE_PURE) {
arg1 = true;
}
if (TokenMeta::iselement(paramtable_elem.fs.CurrentTerm.token)) {
va1 = true;
}
if (paramtable.fs.CurrentTerm.token == TokenMeta::NT_PARAMTABLE_DIMENSLICE) {
dimen2 = true;
}
if (paramtable.fs.CurrentTerm.token == TokenMeta::NT_ARGTABLE_PURE) {
arg2 = true;
}
if (TokenMeta::iselement(paramtable.fs.CurrentTerm.token)) {
va2 = true;
}
if (paramtable_elem.fs.CurrentTerm.token == TokenMeta::NT_KEYVALUE && paramtable.fs.CurrentTerm.token == TokenMeta::NT_PARAMTABLE) {
// all keyvalue pair
newnode = gen_flattern(paramtable_elem, paramtable, "%s, %s", TokenMeta::NT_PARAMTABLE);
}
else if(paramtable.fs.CurrentTerm.token == TokenMeta::NT_PARAMTABLE){
// there is keyvalue pair
// this is possible because of rule `dimen_slice : exp ',' paramtable `
// there is keyvalue
if (dimen1) {
// promote dimen_slice to paramtable
for (int i = 0; i < paramtable_elem.child.size(); i++)
{
newnode.addchild(new ParseNode(*paramtable_elem.child[i]));
}
}
else {
// do not promote exp to keyvalue
// TODO
newnode.addchild(new ParseNode(paramtable_elem));
}
// assume paramtable is flatterned
for (int i = 0; i < paramtable.child.size(); i++)
{
newnode.addchild(new ParseNode(*paramtable.child[i]));
}
sprintf(codegen_buf, "%s, %s", paramtable_elem.fs.CurrentTerm.what.c_str(), paramtable.fs.CurrentTerm.what.c_str());
newnode.fs.CurrentTerm.what = string(codegen_buf);
}
else if ((dimen1 || arg1 || va1) && (dimen2 || arg2 || va2)) {
// all dimen_slice or argument_pure or variable
newnode = ParseNode(gen_flex(Term{ (dimen1 || dimen2) ? TokenMeta::NT_PARAMTABLE_DIMENSLICE : TokenMeta::NT_ARGTABLE_PURE, "" }), nullptr);
if (dimen1 || arg1) {
for (int i = 0; i < paramtable_elem.child.size(); i++)
{
newnode.addchild(new ParseNode(*paramtable_elem.child[i]));
}
}
else {
newnode.addchild(new ParseNode(paramtable_elem));
}
// assume paramtable is flatterned
if (dimen2 || arg2) {
for (int i = 0; i < paramtable.child.size(); i++)
{
newnode.addchild(new ParseNode(*paramtable.child[i]));
}
}
else {
newnode.addchild(new ParseNode(paramtable));
}
sprintf(codegen_buf, "%s, %s", paramtable_elem.fs.CurrentTerm.what.c_str(), paramtable.fs.CurrentTerm.what.c_str());
newnode.fs.CurrentTerm.what = string(codegen_buf);
}
else {
print_error("bad param table");
}
return newnode;
}
示例13: SetFunctionKinds
static void
SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool isDirectEval)
{
for (; funbox; funbox = funbox->siblings) {
ParseNode *fn = funbox->node;
ParseNode *pn = fn->pn_body;
if (funbox->kids)
SetFunctionKinds(funbox->kids, tcflags, isDirectEval);
JSFunction *fun = funbox->function();
JS_ASSERT(fun->kind() == JSFUN_INTERPRETED);
if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
/* nothing to do */
} else if (isDirectEval || funbox->inAnyDynamicScope()) {
/*
* Either we are in a with-block or a function scope that is
* subject to direct eval; or we are compiling strict direct eval
* code.
*
* In either case, fun may reference names that are not bound but
* are not necessarily global either. (In the strict direct eval
* case, we could bind them, but currently do not bother; see
* the comment about strict mode code in BindTopLevelVar.)
*/
JS_ASSERT(!fun->isNullClosure());
} else {
bool hasUpvars = false;
bool canFlatten = true;
if (pn->isKind(PNK_UPVARS)) {
AtomDefnMapPtr upvars = pn->pn_names;
JS_ASSERT(!upvars->empty());
/*
* For each lexical dependency from this closure to an outer
* binding, analyze whether it is safe to copy the binding's
* value into a flat closure slot when the closure is formed.
*/
for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
Definition *defn = r.front().value();
Definition *lexdep = defn->resolve();
if (!lexdep->isFreeVar()) {
hasUpvars = true;
if (!CanFlattenUpvar(lexdep, funbox, *tcflags)) {
/*
* Can't flatten. Enclosing functions holding
* variables used by this function will be flagged
* heavyweight below. FIXME bug 545759: re-enable
* partial flat closures.
*/
canFlatten = false;
break;
}
}
}
}
/*
* Top-level functions, and (extension) functions not at top level
* which are also not directly within other functions, aren't
* flattened.
*/
if (fn->isOp(JSOP_DEFFUN))
canFlatten = false;
if (!hasUpvars) {
/* No lexical dependencies => null closure, for best performance. */
fun->setKind(JSFUN_NULL_CLOSURE);
} else if (canFlatten) {
fun->setKind(JSFUN_FLAT_CLOSURE);
switch (fn->getOp()) {
case JSOP_DEFLOCALFUN:
fn->setOp(JSOP_DEFLOCALFUN_FC);
break;
case JSOP_LAMBDA:
fn->setOp(JSOP_LAMBDA_FC);
break;
default:
/* js::frontend::EmitTree's PNK_FUNCTION case sets op. */
JS_ASSERT(fn->isOp(JSOP_NOP));
}
}
}
if (fun->kind() == JSFUN_INTERPRETED && pn->isKind(PNK_UPVARS)) {
/*
* One or more upvars cannot be safely snapshot into a flat
* closure's non-reserved slot (see JSOP_GETFCSLOT), so we loop
* again over all upvars, and for each non-free upvar, ensure that
* its containing function has been flagged as heavyweight.
*
* The emitter must see TCF_FUN_HEAVYWEIGHT accurately before
* generating any code for a tree of nested functions.
*/
AtomDefnMapPtr upvars = pn->pn_names;
JS_ASSERT(!upvars->empty());
//.........这里部分代码省略.........
示例14: MarkFunArgs
static bool
MarkFunArgs(JSContext *cx, FunctionBox *funbox, uint32_t functionCount)
{
FunctionBoxQueue queue;
if (!queue.init(functionCount)) {
js_ReportOutOfMemory(cx);
return false;
}
FindFunArgs(funbox, -1, &queue);
while ((funbox = queue.pull()) != NULL) {
ParseNode *fn = funbox->node;
JS_ASSERT(fn->isFunArg());
ParseNode *pn = fn->pn_body;
if (pn->isKind(PNK_UPVARS)) {
AtomDefnMapPtr upvars = pn->pn_names;
JS_ASSERT(!upvars->empty());
for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
Definition *defn = r.front().value();
Definition *lexdep = defn->resolve();
if (!lexdep->isFreeVar() &&
!lexdep->isFunArg() &&
(lexdep->kind() == Definition::FUNCTION ||
lexdep->isOp(JSOP_CALLEE))) {
/*
* Mark this formerly-Algol-like function as an escaping
* function (i.e., as a funarg), because it is used from
* another funarg.
*
* Progress is guaranteed because we set the funarg flag
* here, which suppresses revisiting this function (thanks
* to the !lexdep->isFunArg() test just above).
*/
lexdep->setFunArg();
FunctionBox *afunbox;
if (lexdep->isOp(JSOP_CALLEE)) {
/*
* A named function expression will not appear to be a
* funarg if it is immediately applied. However, if its
* name is used in an escaping function nested within
* it, then it must become flagged as a funarg again.
* See bug 545980.
*/
afunbox = funbox;
uintN calleeLevel = lexdep->pn_cookie.level();
uintN staticLevel = afunbox->level + 1U;
while (staticLevel != calleeLevel) {
afunbox = afunbox->parent;
--staticLevel;
}
JS_ASSERT(afunbox->level + 1U == calleeLevel);
afunbox->node->setFunArg();
} else {
afunbox = lexdep->pn_funbox;
}
queue.push(afunbox);
/*
* Walk over nested functions again, now that we have
* changed the level across which it is unsafe to access
* upvars using the runtime dynamic link (frame chain).
*/
if (afunbox->kids)
FindFunArgs(afunbox->kids, afunbox->level, &queue);
}
}
}
}
return true;
}
示例15: JS_ASSERT
/*
* Used by Parser::forStatement and comprehensionTail to clone the TARGET in
* for (var/const/let TARGET in EXPR)
*
* opn must be the pn_head of a node produced by Parser::variables, so its form
* is known to be LHS = NAME | [LHS] | {id:LHS}.
*
* The cloned tree is for use only in the same statement and binding context as
* the original tree.
*/
ParseNode *
js::CloneLeftHandSide(ParseNode *opn, Parser *parser)
{
ParseNode *pn = parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
opn->pn_pos);
if (!pn)
return NULL;
pn->setInParens(opn->isInParens());
pn->setDefn(opn->isDefn());
pn->setUsed(opn->isUsed());
#if JS_HAS_DESTRUCTURING
if (opn->isArity(PN_LIST)) {
JS_ASSERT(opn->isKind(PNK_RB) || opn->isKind(PNK_RC));
pn->makeEmpty();
for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
ParseNode *pn2;
if (opn->isKind(PNK_RC)) {
JS_ASSERT(opn2->isArity(PN_BINARY));
JS_ASSERT(opn2->isKind(PNK_COLON));
ParseNode *tag = CloneParseTree(opn2->pn_left, parser);
if (!tag)
return NULL;
ParseNode *target = CloneLeftHandSide(opn2->pn_right, parser);
if (!target)
return NULL;
pn2 = parser->new_<BinaryNode>(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target);
} else if (opn2->isArity(PN_NULLARY)) {
JS_ASSERT(opn2->isKind(PNK_COMMA));
pn2 = CloneParseTree(opn2, parser);
} else {
pn2 = CloneLeftHandSide(opn2, parser);
}
if (!pn2)
return NULL;
pn->append(pn2);
}
pn->pn_xflags = opn->pn_xflags;
return pn;
}
#endif
JS_ASSERT(opn->isArity(PN_NAME));
JS_ASSERT(opn->isKind(PNK_NAME));
/* If opn is a definition or use, make pn a use. */
pn->pn_u.name = opn->pn_u.name;
pn->setOp(JSOP_SETNAME);
if (opn->isUsed()) {
Definition *dn = pn->pn_lexdef;
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
} else {
pn->pn_expr = NULL;
if (opn->isDefn()) {
/* We copied some definition-specific state into pn. Clear it out. */
pn->pn_cookie.makeFree();
pn->pn_dflags &= ~PND_BOUND;
pn->setDefn(false);
LinkUseToDef(pn, (Definition *) opn);
}
}
return pn;
}