aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-04-19 16:21:36 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-04-20 20:48:43 +0800
commit2720c869e0395b96694a72e71ac4b5eea3b2c64c (patch)
tree04e3f71971a50e527249172ccda0e7992c741435 /utils
parentWalker: first support for function arguments (diff)
downloadlibbash-2720c869e0395b96694a72e71ac4b5eea3b2c64c.tar.gz
libbash-2720c869e0395b96694a72e71ac4b5eea3b2c64c.tar.bz2
libbash-2720c869e0395b96694a72e71ac4b5eea3b2c64c.zip
Build: separate utility programs from tests
Diffstat (limited to 'utils')
-rw-r--r--utils/ast_printer.cpp184
-rw-r--r--utils/variable_printer.cpp54
2 files changed, 238 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+*/
+///
+/// \file ast_printer.cpp
+/// \brief helper program to visualize AST
+///
+
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <boost/program_options.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include "core/parser_builder.h"
+#include "libbashParser.h"
+
+namespace po = boost::program_options;
+namespace qi = boost::spirit::qi;
+
+struct reversed_pair : std::pair<ANTLR3_INT32, std::string>
+{};
+
+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<ANTLR3_INT32, std::string> token_map,
+ ANTLR3_INT32 token)
+{
+ return token_map[token];
+}
+
+static bool build_token_map(std::unordered_map<ANTLR3_INT32, std::string>& 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<iterator, reversed_pair()> line = +~qi::char_('=') >> '=' >> qi::int_parser<ANTLR3_INT32>();
+
+ 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<ANTLR3_INT32, std::string> 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<std::string>& files,
+ bool print_name,
+ std::function<void(std::istream&)> 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<void(std::istream&)> printer)
+{
+ std::istringstream input(expr);
+ printer(input);
+}
+
+static inline void print_cin(std::function<void(std::istream&)> printer)
+{
+ printer(std::cin);
+}
+
+int main(int argc, char** argv)
+{
+ std::vector<std::string> files;
+ std::string expr;
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "produce help message")
+ ("files,f", po::value<std::vector<std::string>>()->multitoken(),
+ "input scripts. If this option and -e are not specified, "
+ "will use standard input")
+ ("expr,e", po::value<std::string>(), "one line of script")
+ ("dot,d", "print graphviz doc file instead of tree string if -s is not specified")
+ ("token,t", po::value<std::string>(), "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<void(std::istream&)> printer;
+ if(vm.count("token"))
+ printer = std::bind(&print_token,
+ std::placeholders::_1,
+ vm["token"].as<std::string>(),
+ 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<std::vector<std::string>>(),
+ vm.count("name"),
+ printer);
+ else if(vm.count("expr"))
+ print_expression(vm["expr"].as<std::string>(), 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 <http://www.gnu.org/licenses/>.
+*/
+///
+/// \file variable_printer.cpp
+/// \author Mu Qiao
+/// \brief a program to write variables in a script into standard output
+///
+
+#include <algorithm>
+#include <iostream>
+#include <map>
+
+#include <gtest/gtest.h>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include "libbash.h"
+
+int main(int argc, char** argv)
+{
+ if(argc != 2)
+ {
+ std::cerr<<"Please provide your script as an argument"<<std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ std::unordered_map<std::string, std::vector<std::string>> variables;
+ libbash::interpret(argv[1], variables);
+
+ std::map<std::string, std::vector<std::string>> 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;
+}