// -*- c-basic-offset: 4; related-file-name: "../../lib/lexer.cc" -*- #ifndef CLICK_LEXER_HH #define CLICK_LEXER_HH #include #include #include #include CLICK_DECLS class LexerExtra; enum Lexemes { lexEOF = 0, lexIdent = 256, // see also Lexer::lexeme_string lexVariable, lexArrow, lex2Arrow, lex2Colon, lex2Bar, lex3Dot, lexElementclass, lexRequire, lexProvide, lexDefine }; class Lexeme { public: Lexeme() : _kind(lexEOF) { } Lexeme(int k, const String &s, bool compact = false) : _kind(k), _s(compact ? s.compact() : s) { } int kind() const { return _kind; } bool is(int k) const { return _kind == k; } const String &string() const { return _s; } String &string() { return _s; } private: int _kind; String _s; }; class Lexer { public: enum { TUNNEL_TYPE = 0, ERROR_TYPE = 1 }; class TunnelEnd; class Compound; typedef Router::Port Port; typedef Router::Connection Connection; Lexer(); virtual ~Lexer(); int begin_parse(const String &data, const String &filename, LexerExtra *, ErrorHandler * = 0); void end_parse(int); VariableEnvironment &global_scope() { return _global_scope; } ErrorHandler *errh() const { return _errh; } String remaining_text() const; void set_remaining_text(const String &); Lexeme lex() { return _unlex_pos ? _unlex[--_unlex_pos] : next_lexeme(); } void unlex(const Lexeme &t) { assert(_unlex_pos < UNLEX_SIZE); _unlex[_unlex_pos++] = t; } String lex_config() { assert(!_unlex_pos); return _file.lex_config(this); } bool expect(int, bool no_error = false); typedef Element *(*ElementFactory)(uintptr_t); #ifdef CLICK_LINUXMODULE int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, struct module *module, bool scoped = false); #else int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, bool scoped = false); #endif int element_type(const String &name) const { return _element_type_map[name]; } int force_element_type(String name, bool report_error = true); void element_type_names(Vector &) const; int remove_element_type(int t) { return remove_element_type(t, 0); } String element_name(int) const; String element_landmark(int) const; void add_tunnels(String name, int *eidexes); bool ydone() const { return !_ps; } void ystep(); Router *create_router(Master *); private: enum { max_depth = 50 }; struct FileState { String _big_string; const char *_end; const char *_pos; String _filename; String _original_filename; unsigned _lineno; FileState(const String &data, const String &filename); const char *skip_line(const char *s); const char *skip_slash_star(const char *s); const char *skip_backslash_angle(const char *s); const char *skip_quote(const char *s, char end_c); const char *process_line_directive(const char *s, Lexer *lexer); Lexeme next_lexeme(Lexer *lexer); String lex_config(Lexer *lexer); String landmark() const; }; struct ElementState; struct ParseState; // lexer FileState _file; bool _compact_config; LexerExtra *_lextra; Lexeme next_lexeme() { return _file.next_lexeme(this); } static String lexeme_string(int); // parser enum { UNLEX_SIZE = 2 }; Lexeme _unlex[2]; int _unlex_pos; // element types struct ElementType { ElementFactory factory; uintptr_t thunk; #ifdef CLICK_LINUXMODULE struct module *module; #endif String name; int next; inline Compound* compound() const { if (factory == compound_element_factory) return reinterpret_cast(thunk); else return 0; } }; HashTable _element_type_map; Vector _element_types; enum { ET_SCOPED = 0x80000000, ET_TMASK = 0x7FFFFFFF, ET_NULL = 0x7FFFFFFF }; int _last_element_type; int _free_element_type; VariableEnvironment _global_scope; // elements Compound *_c; ParseState *_ps; int _group_depth; Vector _tunnels; // compound elements int _anonymous_offset; // requirements Vector _requirements; Vector _libraries; // errors ErrorHandler *_errh; int lerror(const char *, ...); int lerror_syntax(const Lexeme &t); String anon_element_name(const String &) const; int get_element(String name, int etype, const String &configuration = String(), const String &filename = String(), unsigned lineno = 0); int lexical_scoping_in() const; void lexical_scoping_out(int); int remove_element_type(int, int *); int make_compound_element(int); void expand_compound_element(int, VariableEnvironment &); void add_router_connections(int, const Vector &); static Element* compound_element_factory(uintptr_t); void yport(bool isoutput); void yelement_name(); void yelement_type(int type, bool this_ident, bool this_implicit); void yelement_config(ElementState *e, bool this_implicit); void yelement_next(); void yconnection_connector(); void yconnection_check_useless(const Vector &x, bool isoutput); static void yconnection_analyze_ports(const Vector &x, bool isoutput, int &min_ports, int &expandable); void yconnection_connect_all(Vector &outputs, Vector &inputs, int connector); void ycompound_arguments(Compound *ct); void ycompound(); void ycompound_next(); void ycompound_end(const Lexeme &t); void ygroup(); void ygroup_end(); void yelementclass(); void yrequire(); void yrequire_library(const String &value); void yvar(); void ystatement(); TunnelEnd *find_tunnel(const Port &p, bool isoutput, bool insert); void expand_connection(const Port &p, bool isoutput, Vector &); friend class Compound; friend class TunnelEnd; friend struct FileState; }; class LexerExtra { public: LexerExtra() { } virtual ~LexerExtra() { } virtual void require(String type, String value, ErrorHandler *errh); }; CLICK_ENDDECLS #endif