From 2720c869e0395b96694a72e71ac4b5eea3b2c64c Mon Sep 17 00:00:00 2001 From: Mu Qiao Date: Tue, 19 Apr 2011 16:21:36 +0800 Subject: Build: separate utility programs from tests --- utils/ast_printer.cpp | 184 +++++++++++++++++++++++++++++++++++++++++++++ utils/variable_printer.cpp | 54 +++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 utils/ast_printer.cpp create mode 100644 utils/variable_printer.cpp (limited to 'utils') diff --git a/utils/ast_printer.cpp b/utils/ast_printer.cpp new file mode 100644 index 0000000..66d8c8a --- /dev/null +++ b/utils/ast_printer.cpp @@ -0,0 +1,184 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash 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 2 of the License, or + (at your option) any later version. + + libbash 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 libbash. If not, see . +*/ +/// +/// \file ast_printer.cpp +/// \brief helper program to visualize AST +/// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "core/parser_builder.h" +#include "libbashParser.h" + +namespace po = boost::program_options; +namespace qi = boost::spirit::qi; + +struct reversed_pair : std::pair +{}; + +BOOST_FUSION_ADAPT_STRUCT( + reversed_pair + , (std::string, second) + (ANTLR3_INT32, first) +) + +static void print_ast(std::istream& input, bool silent, bool dot) +{ + parser_builder parser(input); + + if(silent) + return; + + if(dot) + std::cout << parser.get_dot_graph() << std::endl; + else + std::cout << parser.get_string_tree() << std::endl; +} + +static inline std::string token_mapper(std::unordered_map token_map, + ANTLR3_INT32 token) +{ + return token_map[token]; +} + +static bool build_token_map(std::unordered_map& token_map, + const std::string& path) +{ + std::ifstream token_file(path); + token_file.unsetf(std::ios::skipws); + + typedef boost::spirit::istream_iterator iterator; + + iterator first(token_file); + iterator last; + + qi::rule line = +~qi::char_('=') >> '=' >> qi::int_parser(); + + return qi::parse(first, last, line % qi::eol >> qi::eol, token_map) && first == last; +} + +static inline void print_token(std::istream& input, + const std::string& token_path, + bool silent) +{ + if(silent) + return; + + parser_builder parser(input); + std::unordered_map token_map; + + if(build_token_map(token_map, token_path)) + { + std::cout << parser.get_tokens(std::bind(&token_mapper, + token_map, + std::placeholders::_1)) + << std::endl; + } + else + { + std::cerr << "Building token map failed" << std::endl; + } +} + +static void print_files(const std::vector& files, + bool print_name, + std::function printer) +{ + for(auto iter = files.begin(); iter != files.end(); ++iter) + { + if(print_name) + std::cout << "Interpreting " << *iter << std::endl; + + std::ifstream input(iter->c_str()); + printer(input); + } +} + +static inline void print_expression(const std::string& expr, + std::function printer) +{ + std::istringstream input(expr); + printer(input); +} + +static inline void print_cin(std::function printer) +{ + printer(std::cin); +} + +int main(int argc, char** argv) +{ + std::vector files; + std::string expr; + + po::options_description desc("Allowed options"); + desc.add_options() + ("help,h", "produce help message") + ("files,f", po::value>()->multitoken(), + "input scripts. If this option and -e are not specified, " + "will use standard input") + ("expr,e", po::value(), "one line of script") + ("dot,d", "print graphviz doc file instead of tree string if -s is not specified") + ("token,t", po::value(), "Print all tokens instead of AST. " + "The argument is the path to libbash.tokens") + ("name,n", "When using files as input scripts, print out file names") + ("silent,s", "do not print any AST") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if(vm.count("help")) + { + std::cout << desc << std::endl; + return 1; + } + + std::function printer; + if(vm.count("token")) + printer = std::bind(&print_token, + std::placeholders::_1, + vm["token"].as(), + vm.count("silent")); + else + printer = std::bind(&print_ast, + std::placeholders::_1, + vm.count("silent"), + vm.count("dot")); + + if(vm.count("files")) + print_files(vm["files"].as>(), + vm.count("name"), + printer); + else if(vm.count("expr")) + print_expression(vm["expr"].as(), printer); + else + print_cin(printer); +} diff --git a/utils/variable_printer.cpp b/utils/variable_printer.cpp new file mode 100644 index 0000000..ed4aa69 --- /dev/null +++ b/utils/variable_printer.cpp @@ -0,0 +1,54 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash 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 2 of the License, or + (at your option) any later version. + + libbash 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 libbash. If not, see . +*/ +/// +/// \file variable_printer.cpp +/// \author Mu Qiao +/// \brief a program to write variables in a script into standard output +/// + +#include +#include +#include + +#include +#include +#include + +#include "libbash.h" + +int main(int argc, char** argv) +{ + if(argc != 2) + { + std::cerr<<"Please provide your script as an argument"<> variables; + libbash::interpret(argv[1], variables); + + std::map> sorted(variables.begin(), variables.end()); + // Currently we don't need internal variables + sorted.erase("IFS"); + + using namespace boost::spirit::karma; + std::cout << format((string << '=' << -(string % ' ')) % eol, sorted) << std::endl; + + return 0; +} -- cgit v1.2.3-65-gdbad