📄 lexert.cc
字号:
} } ElementT *e = _router->get_element(name, type, conf, lm ? lm : landmark()); _lexinfo->notify_element_declaration(e, location.pos1(), location.pos2(), (decl_pos2 < 0 ? location.pos2() : decl_pos2)); return e->eindex();}intLexerT::make_anon_element(const Lexeme &what, int decl_pos2, ElementClassT *type, const String &conf, const String &lm){ return make_element(anon_element_name(type->name()), what, decl_pos2, type, conf, lm);}voidLexerT::connect(int element1, int port1, int port2, int element2){ if (port1 < 0) port1 = 0; if (port2 < 0) port2 = 0; _router->add_connection (PortT(_router->element(element1), port1), PortT(_router->element(element2), port2), landmark());}// PARSINGboolLexerT::yport(int &port, int &pos1, int &pos2){ const Lexeme &tlbrack = lex(); if (!tlbrack.is('[')) { unlex(tlbrack); return false; } pos1 = tlbrack.pos1(); const Lexeme &tword = lex(); if (tword.is(lexIdent)) { String p = tword.string(); const char *ps = p.cc(); if (isdigit(ps[0]) || ps[0] == '-') port = strtol(ps, (char **)&ps, 0); if (*ps != 0) { lerror(tword, "syntax error: port number should be integer"); port = 0; } expect(']'); pos2 = next_pos(); return true; } else if (tword.is(']')) { lerror(tword, "syntax error: expected port number"); port = 0; pos2 = tword.pos2(); return true; } else { lerror(tword, "syntax error: expected port number"); unlex(tword); return false; }}boolLexerT::yelement(int &element, bool comma_ok){ Lexeme tname = lex(); String name; ElementClassT *etype; int decl_pos2 = -1; if (tname.is(lexIdent)) { etype = element_type(tname); name = tname.string(); decl_pos2 = tname.pos2(); } else if (tname.is('{')) { etype = ycompound(String(), tname.pos1(), tname.pos1()); name = etype->name(); decl_pos2 = next_pos(); } else { unlex(tname); return false; } Lexeme configuration; String lm; const Lexeme &tparen = lex(); if (tparen.is('(')) { lm = landmark(); // report landmark from before config string if (!etype) etype = force_element_type(tname); configuration = lex_config(); expect(')'); decl_pos2 = next_pos(); } else unlex(tparen); if (etype) element = make_anon_element(tname, decl_pos2, etype, configuration.string(), lm); else { const Lexeme &t2colon = lex(); unlex(t2colon); if (t2colon.is(lex2Colon) || (t2colon.is(',') && comma_ok)) { ydeclaration(tname); element = _router->eindex(name); } else { element = _router->eindex(name); if (element < 0) { // assume it's an element type etype = force_element_type(tname); element = make_anon_element(tname, tname.pos2(), etype, configuration.string(), lm); } else _lexinfo->notify_element_reference(_router->element(element), tname.pos1(), tname.pos2()); } } return true;}voidLexerT::ydeclaration(const Lexeme &first_element){ Vector<Lexeme> decls; Lexeme t; if (first_element) { decls.push_back(first_element); goto midpoint; } while (true) { t = lex(); if (!t.is(lexIdent)) lerror(t, "syntax error: expected element name"); else decls.push_back(t); midpoint: const Lexeme &tsep = lex(); if (tsep.is(',')) /* do nothing */; else if (tsep.is(lex2Colon)) break; else { lerror(tsep, "syntax error: expected '::' or ','"); unlex(tsep); return; } } String lm = landmark(); ElementClassT *etype; Lexeme etypet = lex(); if (etypet.is(lexIdent)) etype = force_element_type(etypet); else if (etypet.is('{')) etype = ycompound(String(), etypet.pos1(), etypet.pos1()); else { lerror(etypet, "missing element type in declaration"); return; } Lexeme configuration; t = lex(); if (t.is('(')) { configuration = lex_config(); expect(')'); } else unlex(t); int decl_pos2 = (decls.size() == 1 ? next_pos() : -1); for (int i = 0; i < decls.size(); i++) { String name = decls[i].string(); if (ElementT *old_e = _router->element(name)) ElementT::redeclaration_error(_errh, "element", name, landmark(), old_e->landmark()); else if (_router->declared_type(name) || _base_type_map[name]) lerror(decls[i], "class '%s' used as element name", name.c_str()); else make_element(name, decls[i], decl_pos2, etype, configuration.string(), lm); }}boolLexerT::yconnection(){ int element1 = -1; int port1 = -1, port1_pos1 = -1, port1_pos2 = -1; Lexeme t; while (true) { int element2; int port2 = -1, port2_pos1, port2_pos2; // get element yport(port2, port2_pos1, port2_pos2); if (!yelement(element2, element1 < 0)) { if (port1 >= 0) lerror(port1_pos1, port1_pos2, "output port useless at end of chain"); return element1 >= 0; } if (element1 >= 0) connect(element1, port1, port2, element2); else if (port2 >= 0) lerror(port2_pos1, port2_pos2, "input port useless at start of chain"); port1 = -1; relex: t = lex(); switch (t.kind()) { case ',': case lex2Colon: if (router()->element(element2)->anonymous()) // type used as name lerror(t, "class '%s' used as element name", router()->etype_name(element2).c_str()); else lerror(t, "syntax error before '%s'", t.string().c_str()); goto relex; case lexArrow: break; case '[': unlex(t); yport(port1, port1_pos1, port1_pos2); goto relex; case lexIdent: case '{': case '}': case lex2Bar: case lexTunnel: case lexElementclass: case lexRequire: unlex(t); // FALLTHRU case ';': case lexEOF: if (port1 >= 0) lerror(port1_pos1, port1_pos2, "output port useless at end of chain", port1); return true; default: lerror(t, "syntax error near '%#s'", t.string().c_str()); if (t.kind() >= lexIdent) // save meaningful tokens unlex(t); return true; } // have 'x ->' element1 = element2; }}voidLexerT::yelementclass(int pos1){ Lexeme tname = lex(); String eclass_name; if (!tname.is(lexIdent)) { unlex(tname); lerror(tname, "expected element type name"); } else { String n = tname.string(); if (_router->eindex(n) >= 0) lerror(tname, "'%s' already used as an element name", n.cc()); else eclass_name = n; } Lexeme tnext = lex(); if (tnext.is('{')) (void) ycompound(eclass_name, pos1, tname.pos1()); else if (tnext.is(lexIdent)) { ElementClassT *ec = force_element_type(tnext); if (eclass_name) { ElementClassT *new_ec = new SynonymElementClassT(eclass_name, ec, _router); _router->add_declared_type(new_ec, false); _lexinfo->notify_class_declaration(new_ec, false, pos1, tname.pos1(), tnext.pos2()); } } else lerror(tnext, "syntax error near '%#s'", tnext.string().c_str());}voidLexerT::ytunnel(){ Lexeme tname1 = lex(); if (!tname1.is(lexIdent)) { unlex(tname1); lerror(tname1, "expected tunnel input name"); } expect(lexArrow); Lexeme tname2 = lex(); if (!tname2.is(lexIdent)) { unlex(tname2); lerror(tname2, "expected tunnel output name"); } if (tname1.is(lexIdent) && tname2.is(lexIdent)) _router->add_tunnel(tname1.string(), tname2.string(), landmark(), _errh);}voidLexerT::ycompound_arguments(RouterT *comptype){ Lexeme t1, t2; while (1) { String vartype, varname; // read "IDENTIFIER $VARIABLE" or "$VARIABLE" t1 = lex(); if (t1.is(lexIdent)) { t2 = lex(); if (t2.is(lexVariable)) { vartype = t1.string(); varname = t2.string(); } else { if (comptype->nformals() > 0) lerror(t2, "expected variable"); unlex(t2); unlex(t1); break; } } else if (t1.is(lexVariable)) varname = t1.string(); else if (t1.is('|')) break; else { if (comptype->nformals() > 0) lerror(t1, "expected variable"); unlex(t1); break; } comptype->add_formal(varname, vartype); const Lexeme &tsep = lex(); if (tsep.is('|')) break; else if (!tsep.is(',')) { lerror(tsep, "expected ',' or '|'"); unlex(tsep); break; } } // check argument types bool positional = true, error = false; for (int i = 0; i < comptype->nformals(); i++) if (const String &ftype = comptype->formal_types()[i]) { positional = false; if (ftype == "__REST__") { if (i < comptype->nformals() - 1) error = true; } else for (int j = i + 1; j < comptype->nformals(); j++) if (comptype->formal_types()[j] == ftype) { lerror(t1, "repeated keyword parameter '%s' in compound element", ftype.c_str()); break; } } else if (!positional) error = true; if (error) lerror(t1, "compound element parameters out of order\n(The correct order is '[positional], [keywords], [__REST__]'.)");}ElementClassT *LexerT::ycompound(String name, int decl_pos1, int name_pos1){ bool anonymous = (name.length() == 0); // '{' was already read RouterT *old_router = _router; int old_offset = _anonymous_offset; RouterT *first = 0, *last = 0; ElementClassT *extension = 0; int pos2 = name_pos1; while (1) { Lexeme dots = lex(); if (dots.is(lex3Dot)) { // '...' marks an extension type if (anonymous) { lerror(dots, "cannot extend anonymous compound element class"); extension = ElementClassT::base_type("Error"); } else { extension = force_element_type(Lexeme(lexIdent, name, name_pos1)); _lexinfo->notify_class_extension(extension, dots.pos1(), dots.pos2()); } dots = lex(); if (!first || !dots.is('}')) lerror(dots.pos1(), dots.pos2(), "'...' should occur last, after one or more compounds"); if (dots.is('}') && first) break; } unlex(dots); // create a compound RouterT *compound_class = new RouterT(name, landmark(), old_router); _router = compound_class->cast_router(); _anonymous_offset = 2; ycompound_arguments(compound_class); while (ystatement(true)) /* nada */; compound_class->finish_type(_errh); if (last) last->set_overload_type(compound_class); else first = compound_class; last = compound_class; // check for '||' or '}' const Lexeme &t = lex(); if (!t.is(lex2Bar)) { pos2 = t.pos2(); break; } } _anonymous_offset = old_offset; _router = old_router; if (extension) last->set_overload_type(extension); old_router->add_declared_type(first, anonymous); _lexinfo->notify_class_declaration(first, anonymous, decl_pos1, name_pos1, pos2); return first;}voidLexerT::yrequire(){ if (expect('(')) { Lexeme requirement = lex_config(); expect(')'); // pre-read ';' to make it easier to write parsing extensions expect(';', false); Vector<String> args; String word; cp_argvec(requirement.string(), args); for (int i = 0; i < args.size(); i++) { Vector<String> words; cp_spacevec(args[i], words); if (words.size() == 0) /* do nothing */; else if (!cp_word(words[0], &word)) lerror(requirement, "bad requirement: not a word"); else if (words.size() > 1) lerror(requirement, "bad requirement: too many words"); else _router->add_requirement(word); } }}boolLexerT::ystatement(bool nested){ const Lexeme &t = lex(); switch (t.kind()) { case lexIdent: case '[': case '{': unlex(t); yconnection(); return true; case lexElementclass: yelementclass(t.pos1()); return true; case lexTunnel: ytunnel(); return true; case lexRequire: yrequire(); return true; case ';': return true; case '}': case lex2Bar: if (!nested) goto syntax_error; unlex(t); return false; case lexEOF: if (nested) lerror(t, "expected '}'"); return false; default: syntax_error: lerror(t, "syntax error near '%#s'", t.string().c_str()); return true; }}// COMPLETIONRouterT *LexerT::finish(){ RouterT *r = _router; _router = 0; // resolve anonymous element names r->deanonymize_elements(); // returned router has one reference count return r;}#include <click/vector.cc>#include <click/hashmap.cc>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -