⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lexert.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- c-basic-offset: 4 -*-/* * lexert.{cc,hh} -- configuration file parser for tools * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2001-2003 International Computer Science Institute * Copyright (c) 2004 Regents of the University of California * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "lexert.hh"#include "lexertinfo.hh"#include "routert.hh"#include <click/confparse.hh>#include <ctype.h>#include <stdlib.h>static LexerTInfo *stub_lexinfo = 0;LexerT::LexerT(ErrorHandler *errh, bool ignore_line_directives)  : _data(0), _len(0), _pos(0), _lineno(1),    _ignore_line_directives(ignore_line_directives),    _tpos(0), _tfull(0), _router(0), _base_type_map(0), _errh(errh){    if (!_errh)	_errh = ErrorHandler::default_handler();    if (!stub_lexinfo)	stub_lexinfo = new LexerTInfo;    _lexinfo = stub_lexinfo;    clear();}LexerT::~LexerT(){    clear();}voidLexerT::reset(const String &data, const String &filename){    clear();      _big_string = data;    _data = _big_string.data();    _len = _big_string.length();    if (!filename)	_filename = "line ";    else if (filename.back() != ':' && !isspace(filename.back()))	_filename = filename + ":";    else	_filename = filename;    _original_filename = _filename;    _lineno = 1;}voidLexerT::clear(){    if (_router)	_router->unuse();    _router = new RouterT;    _router->use();		// hold a reference to the router    _big_string = "";    // _data was freed by _big_string    _data = 0;    _len = 0;    _pos = 0;    _filename = "";    _lineno = 0;    _tpos = 0;    _tfull = 0;    _base_type_map.clear();    _anonymous_offset = 0;}voidLexerT::set_lexinfo(LexerTInfo *li){    _lexinfo = (li ? li : stub_lexinfo);}// LEXING: LOWEST LEVELStringLexerT::remaining_text() const{  return _big_string.substring(_pos);}voidLexerT::set_remaining_text(const String &s){  _big_string = s;  _data = s.data();  _pos = 0;  _len = s.length();}unsignedLexerT::skip_line(unsigned pos){  _lineno++;  for (; pos < _len; pos++)    if (_data[pos] == '\n')      return pos + 1;    else if (_data[pos] == '\r') {      if (pos < _len - 1 && _data[pos+1] == '\n')	return pos + 2;      else	return pos + 1;    }  _lineno--;  return _len;}unsignedLexerT::skip_slash_star(unsigned pos){  for (; pos < _len; pos++)    if (_data[pos] == '\n')      _lineno++;    else if (_data[pos] == '\r') {      if (pos < _len - 1 && _data[pos+1] == '\n') pos++;      _lineno++;    } else if (_data[pos] == '*' && pos < _len - 1 && _data[pos+1] == '/')      return pos + 2;  return _len;}unsignedLexerT::skip_backslash_angle(unsigned pos){  for (; pos < _len; pos++)    if (_data[pos] == '\n')      _lineno++;    else if (_data[pos] == '\r') {      if (pos < _len - 1 && _data[pos+1] == '\n') pos++;      _lineno++;    } else if (_data[pos] == '/' && pos < _len - 1) {      if (_data[pos+1] == '/')	pos = skip_line(pos + 2) - 1;      else if (_data[pos+1] == '*')	pos = skip_slash_star(pos + 2) - 1;    } else if (_data[pos] == '>')      return pos + 1;  return _len;}unsignedLexerT::skip_quote(unsigned pos, char endc){  for (; pos < _len; pos++)    if (_data[pos] == '\n')      _lineno++;    else if (_data[pos] == '\r') {      if (pos < _len - 1 && _data[pos+1] == '\n') pos++;      _lineno++;    } else if (_data[pos] == '\\' && endc == '\"' && pos < _len - 1) {      if (_data[pos+1] == '<')	pos = skip_backslash_angle(pos + 2) - 1;      else if (_data[pos+1] == '\"')	pos++;    } else if (_data[pos] == endc)      return pos + 1;  return _len;}unsignedLexerT::process_line_directive(unsigned pos){  const char *data = _data;  unsigned len = _len;  unsigned first_pos = pos;    for (pos++; pos < len && (data[pos] == ' ' || data[pos] == '\t'); pos++)    /* nada */;  if (pos < len - 4 && data[pos] == 'l' && data[pos+1] == 'i'      && data[pos+2] == 'n' && data[pos+3] == 'e'      && (data[pos+4] == ' ' || data[pos+4] == '\t')) {    for (pos += 5; pos < len && (data[pos] == ' ' || data[pos] == '\t'); pos++)      /* nada */;  }  if (pos >= len || !isdigit(data[pos])) {    // complain about bad directive    lerror(first_pos, pos, "unknown preprocessor directive");    return skip_line(pos);  } else if (_ignore_line_directives)    return skip_line(pos);    // parse line number  for (_lineno = 0; pos < len && isdigit(data[pos]); pos++)    _lineno = _lineno * 10 + data[pos] - '0';  _lineno--;			// account for extra line    for (; pos < len && (data[pos] == ' ' || data[pos] == '\t'); pos++)    /* nada */;  if (pos < len && data[pos] == '\"') {    // parse filename    unsigned first_in_filename = pos;    for (pos++; pos < len && data[pos] != '\"' && data[pos] != '\n' && data[pos] != '\r'; pos++)      if (data[pos] == '\\' && pos < len - 1 && data[pos+1] != '\n' && data[pos+1] != '\r')	pos++;    _filename = cp_unquote(_big_string.substring(first_in_filename, pos - first_in_filename) + "\":");    // an empty filename means return to the input file's name    if (_filename == ":")      _filename = _original_filename;  }  // reach end of line  for (; pos < len && data[pos] != '\n' && data[pos] != '\r'; pos++)    /* nada */;  if (pos < len - 1 && data[pos] == '\r' && data[pos+1] == '\n')    pos++;  return pos;}LexemeLexerT::next_lexeme(){  unsigned pos = _pos;  while (true) {    while (pos < _len && isspace(_data[pos])) {      if (_data[pos] == '\n')	_lineno++;      else if (_data[pos] == '\r') {	if (pos < _len - 1 && _data[pos+1] == '\n') pos++;	_lineno++;      }      pos++;    }    unsigned opos = pos;    if (pos >= _len) {      _pos = _len;      return Lexeme();    } else if (_data[pos] == '/' && pos < _len - 1) {      if (_data[pos+1] == '/')	pos = skip_line(pos + 2);      else if (_data[pos+1] == '*')	pos = skip_slash_star(pos + 2);      else	break;      _lexinfo->notify_comment(opos, pos);    } else if (_data[pos] == '#' && (pos == 0 || _data[pos-1] == '\n' || _data[pos-1] == '\r')) {      pos = process_line_directive(pos);      _lexinfo->notify_line_directive(opos, pos);    } else      break;  }    unsigned word_pos = pos;    // find length of current word  if (isalnum(_data[pos]) || _data[pos] == '_' || _data[pos] == '@') {   more_word_characters:    pos++;    while (pos < _len && (isalnum(_data[pos]) || _data[pos] == '_' || _data[pos] == '@'))      pos++;    if (pos < _len - 1 && _data[pos] == '/' && (isalnum(_data[pos+1]) || _data[pos+1] == '_' || _data[pos+1] == '@'))      goto more_word_characters;    _pos = pos;    String word = _big_string.substring(word_pos, pos - word_pos);    if (word.length() == 16 && word == "connectiontunnel") {      _lexinfo->notify_keyword(word, word_pos, pos);      return Lexeme(lexTunnel, word, word_pos);    } else if (word.length() == 12 && word == "elementclass") {      _lexinfo->notify_keyword(word, word_pos, pos);      return Lexeme(lexElementclass, word, word_pos);    } else if (word.length() == 7 && word == "require") {      _lexinfo->notify_keyword(word, word_pos, pos);      return Lexeme(lexRequire, word, word_pos);    } else      return Lexeme(lexIdent, word, word_pos);  }  // check for variable  if (_data[pos] == '$') {    pos++;    while (pos < _len && (isalnum(_data[pos]) || _data[pos] == '_'))      pos++;    if (pos > word_pos + 1) {      _pos = pos;      return Lexeme(lexVariable, _big_string.substring(word_pos, pos - word_pos), word_pos);    } else      pos--;  }  if (pos < _len - 1) {    if (_data[pos] == '-' && _data[pos+1] == '>') {      _pos = pos + 2;      return Lexeme(lexArrow, _big_string.substring(word_pos, 2), word_pos);    } else if (_data[pos] == ':' && _data[pos+1] == ':') {      _pos = pos + 2;      return Lexeme(lex2Colon, _big_string.substring(word_pos, 2), word_pos);    } else if (_data[pos] == '|' && _data[pos+1] == '|') {      _pos = pos + 2;      return Lexeme(lex2Bar, _big_string.substring(word_pos, 2), word_pos);    }  }  if (pos < _len - 2 && _data[pos] == '.' && _data[pos+1] == '.' && _data[pos+2] == '.') {    _pos = pos + 3;    return Lexeme(lex3Dot, _big_string.substring(word_pos, 3), word_pos);  }    _pos = pos + 1;  return Lexeme(_data[word_pos], _big_string.substring(word_pos, 1), word_pos);}LexemeLexerT::lex_config(){  unsigned config_pos = _pos;  unsigned pos = _pos;  unsigned paren_depth = 1;    for (; pos < _len; pos++)    if (_data[pos] == '(')      paren_depth++;    else if (_data[pos] == ')') {      paren_depth--;      if (!paren_depth) break;    } else if (_data[pos] == '\n')      _lineno++;    else if (_data[pos] == '\r') {      if (pos < _len - 1 && _data[pos+1] == '\n') pos++;      _lineno++;    } else if (_data[pos] == '/' && pos < _len - 1) {      if (_data[pos+1] == '/')	pos = skip_line(pos + 2) - 1;      else if (_data[pos+1] == '*')	pos = skip_slash_star(pos + 2) - 1;    } else if (_data[pos] == '\'' || _data[pos] == '\"')      pos = skip_quote(pos + 1, _data[pos]) - 1;    else if (_data[pos] == '\\' && pos < _len - 1 && _data[pos+1] == '<')      pos = skip_backslash_angle(pos + 2) - 1;    _pos = pos;  _lexinfo->notify_config_string(config_pos, pos);  return Lexeme(lexConfig, _big_string.substring(config_pos, pos - config_pos),		config_pos);}StringLexerT::lexeme_string(int kind){  char buf[12];  if (kind == lexIdent)    return "identifier";  else if (kind == lexVariable)    return "variable";  else if (kind == lexArrow)    return "'->'";  else if (kind == lex2Colon)    return "'::'";  else if (kind == lex2Bar)    return "'||'";  else if (kind == lex3Dot)    return "'...'";  else if (kind == lexTunnel)    return "'connectiontunnel'";  else if (kind == lexElementclass)    return "'elementclass'";  else if (kind == lexRequire)    return "'require'";  else if (kind >= 32 && kind < 127) {    sprintf(buf, "'%c'", kind);    return buf;  } else {    sprintf(buf, "'\\%03d'", kind);    return buf;  }}// LEXING: MIDDLE LEVEL (WITH PUSHBACK)const Lexeme &LexerT::lex(){  int p = _tpos;  if (_tpos == _tfull) {    _tcircle[p] = next_lexeme();    _tfull = (_tfull + 1) % TCIRCLE_SIZE;  }  _tpos = (_tpos + 1) % TCIRCLE_SIZE;  return _tcircle[p];}voidLexerT::unlex(const Lexeme &t){  _tpos = (_tpos + TCIRCLE_SIZE - 1) % TCIRCLE_SIZE;  _tcircle[_tpos] = t;  assert(_tfull != _tpos);}boolLexerT::expect(int kind, bool report_error){    // Never adds anything to '_tcircle'. This requires a nonobvious    // implementation.    if (_tpos != _tfull) {	if (_tcircle[_tpos].is(kind)) {	    _tpos = (_tpos + 1) % TCIRCLE_SIZE;	    return true;	}	if (report_error)	    lerror(_tcircle[_tpos], "expected %s", lexeme_string(kind).cc());    } else {	unsigned old_pos = _pos;	if (next_lexeme().is(kind))	    return true;	if (report_error)	    lerror(old_pos, _pos, "expected %s", lexeme_string(kind).cc());	_pos = old_pos;    }    return false;}intLexerT::next_pos() const{    if (_tpos != _tfull)	return _tcircle[_tpos].pos1();    else	return _pos;}// ERRORSStringLexerT::landmark() const{    return _filename + String(_lineno);}voidLexerT::vlerror(int pos1, int pos2, const String &lm, const char *format, va_list val){    String text = _errh->make_text(ErrorHandler::ERR_ERROR, format, val);    _lexinfo->notify_error(text, pos1, pos2);    text = _errh->decorate_text(ErrorHandler::ERR_ERROR, lm, text);    _errh->handle_text(ErrorHandler::ERR_ERROR, text);}intLexerT::lerror(int pos1, int pos2, const char *format, ...){    va_list val;    va_start(val, format);    vlerror(pos1, pos2, landmark(), format, val);    va_end(val);    return -1;}intLexerT::lerror(const Lexeme &t, const char *format, ...){    va_list val;    va_start(val, format);    vlerror(t.pos1(), t.pos2(), landmark(), format, val);    va_end(val);    return -1;}// ELEMENT TYPESElementClassT *LexerT::element_type(const Lexeme &t) const{    assert(t.is(lexIdent));    String name = t.string();    ElementClassT *type = _router->declared_type(name);    if (!type)	type = _base_type_map[name];    if (type)	_lexinfo->notify_class_reference(type, t.pos1(), t.pos2());    return type;}ElementClassT *LexerT::force_element_type(const Lexeme &t){    assert(t.is(lexIdent));    String name = t.string();    ElementClassT *type = _router->declared_type(name);    if (!type)	type = _base_type_map[name];    if (!type) {	if (_router->eindex(name) >= 0)	    lerror(t, "'%s' was previously used as an element name", name.c_str());	type = ElementClassT::base_type(name);	_base_type_map.insert(name, type);    }    _lexinfo->notify_class_reference(type, t.pos1(), t.pos2());    return type;}// ELEMENTSStringLexerT::anon_element_name(const String &class_name) const{    int anonymizer = _router->nelements() - _anonymous_offset + 1;    return ";" + class_name + "@" + String(anonymizer);}intLexerT::make_element(String name, const Lexeme &location, int decl_pos2,		     ElementClassT *type, const String &conf, const String &lm){    // check 'name' for validity    for (int i = 0; i < name.length(); i++) {	bool ok = false;	for (; i < name.length() && name[i] != '/'; i++)	    if (!isdigit(name[i]))		ok = true;	if (!ok) {	    lerror(location, "element name '%s' has all-digit component", name.cc());	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -