1 // -*- c-basic-offset: 4; related-file-name: "../../lib/lexer.cc" -*- 2 #ifndef CLICK_LEXER_HH 3 #define CLICK_LEXER_HH 4 #include <click/hashtable.hh> 5 #include <click/router.hh> 6 #include <click/glue.hh> 7 #include <click/variableenv.hh> 8 CLICK_DECLS 9 class LexerExtra; 10 11 enum Lexemes { 12 lexEOF = 0, 13 lexIdent = 256, // see also Lexer::lexeme_string 14 lexVariable, 15 lexArrow, 16 lex2Arrow, 17 lex2Colon, 18 lex2Bar, 19 lex3Dot, 20 lexElementclass, 21 lexRequire, 22 lexProvide, 23 lexDefine 24 }; 25 26 class Lexeme { public: 27 Lexeme()28 Lexeme() 29 : _kind(lexEOF) { 30 } Lexeme(int k,const String & s,bool compact=false)31 Lexeme(int k, const String &s, bool compact = false) 32 : _kind(k), _s(compact ? s.compact() : s) { 33 } 34 kind() const35 int kind() const { return _kind; } is(int k) const36 bool is(int k) const { return _kind == k; } 37 string() const38 const String &string() const { return _s; } string()39 String &string() { return _s; } 40 41 private: 42 43 int _kind; 44 String _s; 45 46 }; 47 48 class Lexer { public: 49 50 enum { TUNNEL_TYPE = 0, ERROR_TYPE = 1 }; 51 52 class TunnelEnd; 53 class Compound; 54 typedef Router::Port Port; 55 typedef Router::Connection Connection; 56 57 Lexer(); 58 virtual ~Lexer(); 59 60 int begin_parse(const String &data, const String &filename, LexerExtra *, ErrorHandler * = 0); 61 void end_parse(int); 62 global_scope()63 VariableEnvironment &global_scope() { return _global_scope; } errh() const64 ErrorHandler *errh() const { return _errh; } 65 66 String remaining_text() const; 67 void set_remaining_text(const String &); 68 lex()69 Lexeme lex() { 70 return _unlex_pos ? _unlex[--_unlex_pos] : next_lexeme(); 71 } unlex(const Lexeme & t)72 void unlex(const Lexeme &t) { 73 assert(_unlex_pos < UNLEX_SIZE); 74 _unlex[_unlex_pos++] = t; 75 } lex_config()76 String lex_config() { 77 assert(!_unlex_pos); 78 return _file.lex_config(this); 79 } 80 81 bool expect(int, bool no_error = false); 82 83 typedef Element *(*ElementFactory)(uintptr_t); 84 #ifdef CLICK_LINUXMODULE 85 int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, struct module *module, bool scoped = false); 86 #else 87 int add_element_type(const String &, ElementFactory factory, uintptr_t thunk, bool scoped = false); 88 #endif element_type(const String & name) const89 int element_type(const String &name) const { 90 return _element_type_map[name]; 91 } 92 int force_element_type(String name, bool report_error = true); 93 94 void element_type_names(Vector<String> &) const; 95 remove_element_type(int t)96 int remove_element_type(int t) { return remove_element_type(t, 0); } 97 98 String element_name(int) const; 99 String element_landmark(int) const; 100 101 void add_tunnels(String name, int *eidexes); 102 ydone() const103 bool ydone() const { return !_ps; } 104 void ystep(); 105 106 Router *create_router(Master *); 107 108 private: 109 110 enum { 111 max_depth = 50 112 }; 113 114 struct FileState { 115 String _big_string; 116 const char *_end; 117 const char *_pos; 118 String _filename; 119 String _original_filename; 120 unsigned _lineno; 121 122 FileState(const String &data, const String &filename); 123 const char *skip_line(const char *s); 124 const char *skip_slash_star(const char *s); 125 const char *skip_backslash_angle(const char *s); 126 const char *skip_quote(const char *s, char end_c); 127 const char *process_line_directive(const char *s, Lexer *lexer); 128 Lexeme next_lexeme(Lexer *lexer); 129 String lex_config(Lexer *lexer); 130 String landmark() const; 131 }; 132 133 struct ElementState; 134 struct ParseState; 135 136 // lexer 137 FileState _file; 138 bool _compact_config; 139 LexerExtra *_lextra; 140 next_lexeme()141 Lexeme next_lexeme() { 142 return _file.next_lexeme(this); 143 } 144 static String lexeme_string(int); 145 146 // parser 147 enum { UNLEX_SIZE = 2 }; 148 Lexeme _unlex[2]; 149 int _unlex_pos; 150 151 // element types 152 struct ElementType { 153 ElementFactory factory; 154 uintptr_t thunk; 155 #ifdef CLICK_LINUXMODULE 156 struct module *module; 157 #endif 158 String name; 159 int next; 160 }; 161 HashTable<String, int> _element_type_map; 162 Vector<ElementType> _element_types; 163 enum { ET_SCOPED = 0x80000000, ET_TMASK = 0x7FFFFFFF, ET_NULL = 0x7FFFFFFF }; 164 int _last_element_type; 165 int _free_element_type; 166 VariableEnvironment _global_scope; 167 168 // elements 169 Compound *_c; 170 ParseState *_ps; 171 int _group_depth; 172 173 Vector<TunnelEnd *> _tunnels; 174 175 // compound elements 176 int _anonymous_offset; 177 178 // requirements 179 Vector<String> _requirements; 180 Vector<String> _libraries; 181 182 // errors 183 ErrorHandler *_errh; 184 185 int lerror(const char *, ...); 186 int lerror_syntax(const Lexeme &t); 187 188 String anon_element_name(const String &) const; 189 int get_element(String name, int etype, 190 const String &configuration = String(), 191 const String &filename = String(), unsigned lineno = 0); 192 int lexical_scoping_in() const; 193 void lexical_scoping_out(int); 194 int remove_element_type(int, int *); 195 int make_compound_element(int); 196 void expand_compound_element(int, VariableEnvironment &); 197 void add_router_connections(int, const Vector<int> &); 198 199 void yport(bool isoutput); 200 void yelement_name(); 201 void yelement_type(int type, bool this_ident, bool this_implicit); 202 void yelement_config(ElementState *e, bool this_implicit); 203 void yelement_next(); 204 205 void yconnection_connector(); 206 void yconnection_check_useless(const Vector<int> &x, bool isoutput); 207 static void yconnection_analyze_ports(const Vector<int> &x, bool isoutput, 208 int &min_ports, int &expandable); 209 void yconnection_connect_all(Vector<int> &outputs, Vector<int> &inputs, int connector); 210 211 void ycompound_arguments(Compound *ct); 212 void ycompound(); 213 void ycompound_next(); 214 void ycompound_end(const Lexeme &t); 215 void ygroup(); 216 void ygroup_end(); 217 218 void yelementclass(); 219 void yrequire(); 220 void yrequire_library(const String &value); 221 void yvar(); 222 223 void ystatement(); 224 225 TunnelEnd *find_tunnel(const Port &p, bool isoutput, bool insert); 226 void expand_connection(const Port &p, bool isoutput, Vector<Port> &); 227 228 friend class Compound; 229 friend class TunnelEnd; 230 friend struct FileState; 231 232 }; 233 234 class LexerExtra { public: 235 LexerExtra()236 LexerExtra() { } ~LexerExtra()237 virtual ~LexerExtra() { } 238 239 virtual void require(String type, String value, ErrorHandler *errh); 240 241 }; 242 243 CLICK_ENDDECLS 244 #endif 245