📄 lexert.cc
字号:
lerror(location, "element name %<%s%> has all-digit component", name.c_str()); break; } } const char *end_decl = (decl_pos2 ? decl_pos2 : location.pos2()); ElementT *e = _router->get_element(name, type, conf, landmarkt(location.pos1(), location.pos2())); _lexinfo->notify_element_declaration(e, location.pos1(), location.pos2(), end_decl); return e->eindex();}intLexerT::make_anon_element(const Lexeme &what, const char *decl_pos2, ElementClassT *type, const String &conf){ return make_element(anon_element_name(type->name()), what, decl_pos2, type, conf);}voidLexerT::connect(int element1, int port1, int port2, int element2, const char *pos1, const char *pos2){ if (port1 < 0) port1 = 0; if (port2 < 0) port2 = 0; _router->add_connection (PortT(_router->element(element1), port1), PortT(_router->element(element2), port2), landmarkt(pos1, pos2));}// PARSINGboolLexerT::yport(int &port, const char *&pos1, const char *&pos2){ const Lexeme &tlbrack = lex(); pos1 = tlbrack.pos1(); if (!tlbrack.is('[')) { unlex(tlbrack); pos2 = pos1; return false; } const Lexeme &tword = lex(); if (tword.is(lexIdent)) { String p = tword.string(); const char *ps = p.c_str(); if (isdigit((unsigned char) 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; const char *decl_pos2 = 0; 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; const Lexeme &tparen = lex(); if (tparen.is('(')) { 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()); 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()); } 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; } } 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); const char *decl_pos2 = (decls.size() == 1 ? next_pos() : 0); 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.get(name)) lerror(decls[i], "class %<%s%> used as element name", name.c_str()); else make_element(name, decls[i], decl_pos2, etype, configuration.string()); }}boolLexerT::yconnection(){ int element1 = -1, port1 = -1; const char *last_element_pos = next_pos(), *port1_pos1 = 0, *port1_pos2 = 0; Lexeme t; while (true) { int element2, port2 = -1; const char *port2_pos1, *port2_pos2, *next_element_pos; // get element yport(port2, port2_pos1, port2_pos2); next_element_pos = next_pos(); 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, last_element_pos, next_pos()); else if (port2 >= 0) lerror(port2_pos1, port2_pos2, "input port useless at start of chain"); port1 = -1; port1_pos1 = port1_pos2 = 0; last_element_pos = next_element_pos; 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 lexElementclass: case lexRequire: case lexDefine: 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(const char *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.c_str()); 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::ydefine(RouterT *r, const String &fname, const String &ftype, bool isformal, const Lexeme &t, bool &scope_order_error){ if (!r->define(fname, ftype, isformal)) lerror(t, "parameter %<$%s%> multiply defined", fname.c_str()); else if (isformal) { if (ftype) for (int i = 0; i < r->scope().size() - 1; i++) if (r->scope().value(i) == ftype) { lerror(t, "repeated keyword parameter %<%s%> in compound element", ftype.c_str()); break; } if (!scope_order_error && r->nformals() > 1 && ((!ftype && r->scope().value(r->nformals() - 2)) || r->scope().value(r->nformals() - 2) == "__REST__")) { lerror(t, "compound element parameters out of order\n(The correct order is %<[positional], [keywords], [__REST__]%>.)"); scope_order_error = true; } }}voidLexerT::ycompound_arguments(RouterT *comptype){ Lexeme t1, t2; bool scope_order_error = false; 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; } ydefine(comptype, varname, vartype, true, t1, scope_order_error); const Lexeme &tsep = lex(); if (tsep.is('|')) break; else if (!tsep.is(',')) { lerror(tsep, "expected %<,%> or %<|%>"); unlex(tsep); break; } }}ElementClassT *LexerT::ycompound(String name, const char *decl_pos1, const char *name_pos1){ bool anonymous = (name.length() == 0); String printable_name = name; if (anonymous) printable_name = "<anonymous" + String(++_anonymous_class_count) + ">"; // '{' was already read RouterT *old_router = _router; int old_offset = _anonymous_offset; RouterT *first = 0, *last = 0; ElementClassT *extension = 0; const char *class_pos1 = name_pos1; const char *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, landmarkt(class_pos1, dots.pos1()), old_router); compound_class->set_printable_name(printable_name); _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(); compound_class->set_landmarkt(landmarkt(class_pos1, t.pos2())); class_pos1 = t.pos1(); 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); } }}voidLexerT::yvar(){ if (expect('(')) { Lexeme vars = lex_config(); expect(')'); Vector<String> args; String word; cp_argvec(vars.string(), args); for (int i = 0; i < args.size(); i++) if (args[i]) { String var = cp_shift_spacevec(args[i]); const char *s = var.begin(); if (s != var.end() && *s == '$') for (s++; s != var.end() && (isalnum((unsigned char) *s) || *s == '_'); s++) /* nada */; if (var.length() < 2 || s != var.end()) lerror(vars, "bad %<var%> declaration: not a variable"); else { var = var.substring(1); if (!_router->define(var, args[i], false)) lerror(vars, "parameter %<%s%> multiply defined", var.c_str()); } } }}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 lexRequire: yrequire(); return true; case lexDefine: yvar(); 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(const VariableEnvironment &global_scope){ RouterT *r = _router; _router = 0; r->redefine(global_scope); // resolve anonymous element names r->deanonymize_elements(); // returned router has one reference count return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -