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