/* Copyright 2015, 2016, Michele Santullo * This file is part of "dindexer". * * "dindexer" is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * "dindexer" is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with "dindexer". If not, see . */ #include "glob_ast.hpp" #include "glob2regex/exceptions.hpp" #include //#include //#include //#include //#include //#include //#include //#include //#include #include #include #include #include #include #include //#define AST_DEBUG_OUTPUT #if defined(AST_DEBUG_OUTPUT) # include #endif namespace qi = boost::spirit::qi; namespace g2r { namespace { template struct GlobGrammar : qi::grammar { GlobGrammar ( void ); ~GlobGrammar ( void ) = default; qi::rule start; qi::rule alternation_list; qi::rule alternation; qi::rule group; qi::rule literal; qi::rule single_char_comma_list; qi::rule escaped_glob; qi::rule jolly; }; template GlobGrammar::GlobGrammar() : GlobGrammar::base_type(start) { using boost::spirit::qi::lit; using boost::spirit::qi::char_; using boost::spirit::qi::matches; using boost::spirit::qi::eps; using boost::spirit::qi::string; using boost::spirit::qi::as_string; using boost::spirit::qi::attr; using boost::spirit::qi::repeat; using boost::spirit::qi::inf; static const char* const special_char_list = "{}[]*\\+? "; const uint16_t uint16_zero = 0; const uint16_t uint16_one = 1; start = *(group | alternation | literal | jolly); alternation_list = *(group | alternation | as_string[+(~char_("{}[]*\\+? ,") | escaped_glob)] | jolly); single_char_comma_list = ~char_(special_char_list) % ","; alternation = eps >> lit("{") >> (alternation_list % ",") >> "}"; group = (lit("[") >> matches[lit("!")] >> as_string[-string("]") >> *(~char_(']') | escaped_glob)] >> "]") | (attr(false) >> lit("{") >> single_char_comma_list >> lit("}")); literal = +(~char_(special_char_list) | escaped_glob); escaped_glob = lit("\\") >> char_(special_char_list); jolly = (attr(uint16_zero) >> attr(uint16_zero) >> attr(true) >> "**") | (attr(uint16_zero) >> attr(uint16_zero) >> attr(false) >> "*") | (attr(uint16_one) >> attr(uint16_one) >> attr(false) >> "?") ; } } //unnamed namespace GlobExpression make_ast (const std::string& parGlob) { GlobGrammar gramm; auto glob_beg = parGlob.cbegin(); GlobExpression glob_ast; const bool parse_ret = boost::spirit::qi::parse( glob_beg, parGlob.end(), gramm, glob_ast ); #if defined(AST_DEBUG_OUTPUT) std::cout << "make_ast(\"" << parGlob << "\") - parse_ret = "; if (parse_ret) std::cout << "true"; else std::cout << "false"; std::cout << ", glob_ast.size() = " << glob_ast.size() << std::endl; #endif if (not parse_ret or parGlob.end() != glob_beg) throw ParsingError(parGlob, parGlob.end() - glob_beg); return glob_ast; } } //namespace g2r