📄 parser.cpp
字号:
// -*-c++-*-/*************************************************************************** parser.cpp Parser for config options ------------------- begin : 15-MAY-2003 copyright : (C) 2003 by The RoboCup Soccer Server Maintenance Group. email : sserver-admin@lists.sourceforge.net***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU LGPL as published by the Free Software * * Foundation; either version 2 of the License, or (at your option) any * * later version. * * * ***************************************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "parser.hpp"#include "builder.hpp"#ifdef HAVE_SSTREAM#include <sstream>#else#include <strstream>#endif#include <iterator>#include <cerrno>#include <climits>#include <boost/filesystem/operations.hpp>#include <boost/filesystem/fstream.hpp>#include <boost/filesystem/exception.hpp>// #define BOOST_SPIRIT_DEBUG#include <boost/spirit.hpp>#include <boost/function.hpp>#include <boost/bind.hpp>namespace {boolisQuated( const std::string & str ){ return ( str.length() >= 2 && ( ( *str.begin() == '\"' && *str.rbegin() == '\"' ) || ( *str.begin() == '\'' && *str.rbegin() == '\'' ) ) );}std::stringcleanString( std::string str ){ if ( str.empty() ) { return str; } if ( *str.begin() == '\'' ) { if ( *str.rbegin() == '\'' ) { str = str.substr( 1, str.length() - 2 ); } else { return str; } for ( std::string::size_type esc = str.find( "\\'" ); esc != std::string::npos; esc = str.find( "\\'" ) ) { str.replace( esc, 2, "'" ); } } else if ( *str.begin() == '"' ) { if ( *str.rbegin() == '"' ) { str = str.substr( 1, str.length() - 2 ); } else { return str; } for ( std::string::size_type esc = str.find( "\\\"" ); esc != std::string::npos; esc = str.find( "\\\"" ) ) { str.replace( esc, 2, "\"" ); } } return str;}std::stringcleanString( const char * begin, const char * end ){ return cleanString( std::string( begin, end ) );}}namespace rcss {namespace conf {const char * Parser::ErrorStrs[] = { "None", "'=' expected", "'::' expected", "value expected", "string expected" };class ParseErrorHandler {public: static boost::spirit::error_status<> parseError( const Parser * parser, const boost::spirit::rule<>::scanner_t & scanner, const boost::spirit::parser_error< Parser::Errors > & error ) { std::string what; if ( error.where + 10 > scanner.last ) { what = std::string( error.where, scanner.last ); } else { what = std::string( error.where, error.where + 10 ); } std::string::iterator newline = std::find( what.begin(), what.end(), '\n' ); if ( newline != what.end() ) { what = std::string( what.begin(), newline ); } parser->m_builder.parseError( what, Parser::ErrorStrs[ error.descriptor ], parser->m_stack.front().m_name, parser->m_stack.front().m_lineno ); return boost::spirit::error_status<>( boost::spirit::error_status<>::fail ); }};Parser::Parser( Builder & builder ) : m_builder( builder ){ m_builder.addedToParser( *this );}Parser::~Parser(){ m_builder.removedFromParser();}boolParser::parse( int argc, const char * const * argv ){#ifdef HAVE_SSTREAM std::stringstream strm;#else std::strstream strm;#endif if ( argc > 1 ) { std::string arg( argv[1] ); if ( arg.find_first_of( " \t" ) != std::string::npos && ! isQuated( arg ) ) { strm << "\'" << arg << "\'"; } else { strm << arg; } } for ( int i = 2; i < argc; ++i ) { std::string arg( argv[i] ); if ( arg.find_first_of( " \t" ) != std::string::npos && ! isQuated( arg ) ) { strm << ' ' << '\'' << arg << '\''; } else { strm << ' ' << arg; } }#ifndef HAVE_SSTREAM strm << std::ends;#else strm << std::flush;#endif bool res = rcss::Parser::parse( strm, "cmd line args" );#ifndef HAVE_SSTREAM strm.freeze( false );#endif return res;}boolParser::parse( std::istream & strm ){ return rcss::Parser::parse( strm );}boolParser::parse( std::istream & strm, const std::string & name ){ return rcss::Parser::parse( strm, name );}boolParser::parse( const boost::filesystem::path & file ){ return rcss::Parser::parse( file );}boolParser::parseCreateConf( const boost::filesystem::path & conf_name, const std::string & module_name ){ std::string native_path = conf_name.native_file_string(); boost::filesystem::ifstream conf( conf_name ); if ( ! conf.is_open() ) { m_builder.creatingConfFile( native_path ); boost::filesystem::ofstream new_conf( conf_name ); if ( new_conf.is_open() ) { m_builder.createConfFile( new_conf, module_name ); new_conf.close(); m_builder.createdConfFile( native_path ); return true; } else { std::cerr << "is not opened. Parser::parseCreateConf " << native_path << std::endl; m_builder.confCreationFailed( native_path, errno ); return false; } } else { bool rval = parse( conf, native_path ); conf.close(); return rval; }}boolParser::doParse( std::istream & strm ){ m_builder.reset(); m_stack.push_front( StreamState( strm, getStreamName(), 1 ) ); bool rval = boostParse(); m_stack.pop_front(); rval = rval && m_builder.success(); return rval;}voidParser::countNewLines( const char * begin, const char * end ){ int count = 0; for ( const char * i = begin; i != end; ++i ) { if ( '\n' == *i ) { ++count; } } if ( ! m_stack.empty() ) { m_stack.front().m_lineno += count; }}boolParser::include( const char * begin, const char * end ){ std::string incname = cleanString( begin, end ); boost::filesystem::path path; try { path = boost::filesystem::path( incname, &boost::filesystem::native ); } catch(...) { try { path = boost::filesystem::path( incname ); } catch ( const std::exception & e ) { m_builder.includeFailed( incname, e.what(), m_stack.front().m_name, m_stack.front().m_lineno ); return false; } } boost::filesystem::path full_name; if ( path.has_root_directory() ) { full_name = path; } else { const std::string & curr_path = m_stack.front().m_name; if ( curr_path.empty() || curr_path == "cmd line args" || curr_path == "anonymous stream" ) { full_name = complete( path ); } else { boost::filesystem::path branch( curr_path, boost::filesystem::native ); branch = branch.branch_path(); full_name = branch / path; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -