253 lines
6.2 KiB
C++
253 lines
6.2 KiB
C++
// -*- c-basic-offset: 4; related-file-name: "../../lib/lexer.cc" -*-
|
|
#ifndef CLICK_LEXER_HH
|
|
#define CLICK_LEXER_HH
|
|
#include <click/hashtable.hh>
|
|
#include <click/router.hh>
|
|
#include <click/glue.hh>
|
|
#include <click/variableenv.hh>
|
|
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<String> &) 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<Compound*>(thunk);
|
|
else
|
|
return 0;
|
|
}
|
|
};
|
|
HashTable<String, int> _element_type_map;
|
|
Vector<ElementType> _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<TunnelEnd *> _tunnels;
|
|
|
|
// compound elements
|
|
int _anonymous_offset;
|
|
|
|
// requirements
|
|
Vector<String> _requirements;
|
|
Vector<String> _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<int> &);
|
|
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<int> &x, bool isoutput);
|
|
static void yconnection_analyze_ports(const Vector<int> &x, bool isoutput,
|
|
int &min_ports, int &expandable);
|
|
void yconnection_connect_all(Vector<int> &outputs, Vector<int> &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<Port> &);
|
|
|
|
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
|