Created
September 17, 2018 22:34
-
-
Save mhhollomon/5e4706bc064cd983d5db7d3e13bda20f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************************************** | |
* Copyright 2018 Mark Hollomon | |
* | |
************************************************/ | |
#include <iostream> | |
#include <string> | |
#include <cctype> | |
#include <boost/spirit/home/x3.hpp> | |
namespace x3 = boost::spirit::x3; | |
//**************************** | |
// Custom parser | |
//**************************** | |
struct keyword: x3::parser<keyword> { | |
using attribute_type = std::string; | |
keyword(std::string s) : m_kw(s) {}; | |
template<typename Iterator, typename Context, typename RContext, typename Attribute> | |
bool parse(Iterator &first, Iterator const& last, Context const& context, | |
RContext const& rcontext, Attribute& attr) const | |
{ | |
Iterator save = first; | |
auto kbeg = m_kw.begin(); | |
auto const kend = m_kw.end(); | |
while ((first != last) & (kbeg != kend)) { | |
if (*first != *kbeg) break; | |
++first; ++ kbeg; | |
} | |
bool okay = true; | |
if (kbeg == kend) { | |
// Matched our target, but now must make sure | |
// nothing interesting comes afterward. | |
if (first != last) { | |
if (isalnum(*first)) okay = false; | |
else if (*first == '_') okay = false; | |
else okay = true; | |
} | |
} else { | |
okay = false; | |
} | |
if (okay) { | |
attr = m_kw; | |
} else { | |
first = save; | |
} | |
return okay; | |
}; | |
std::string m_kw; | |
}; | |
template<> | |
struct x3::get_info<keyword> | |
{ | |
typedef std::string result_type; | |
std::string operator()( keyword const& kw) const | |
{ | |
return "keyword " + kw.m_kw; | |
} | |
}; | |
//**************************** | |
// The gramar | |
//**************************** | |
using x3::lexeme; | |
using x3::alnum; | |
using x3::alpha; | |
using x3::ascii::char_; | |
x3::symbols<int> symtab; | |
auto const ualnum = alnum | char_('_'); | |
auto mkkw = [](std::string kw) { | |
symtab.add(kw); | |
return keyword(kw); | |
}; | |
auto const kw_var = mkkw("var"); | |
auto const kw_func = mkkw("func"); | |
auto const reserved = lexeme[symtab >> !ualnum]; | |
auto const ident = lexeme[ *char_('_') >> alpha >> *ualnum ] - reserved; | |
auto const stmt = kw_var >> ident; | |
auto const program = +stmt; | |
//**************************** | |
// Main | |
//**************************** | |
int main(int argc, char**argv) | |
{ | |
if (argc < 2) { | |
std::cout << "Need something to parse\n"; | |
exit(1); | |
} | |
std::string input(argv[1]); | |
auto iter = input.cbegin(); | |
auto end_iter = input.cend(); | |
std::cout << "parsing : " << input << "\n"; | |
bool r = x3::phrase_parse(iter, end_iter, program, x3::ascii::space); | |
if (iter != end_iter) { | |
auto distance = end_iter - iter; | |
std::cout << "Failed: didn't parse everything\n"; | |
std::cout << "stopped " << distance << " characters from the end " | |
<< "( '" << *iter << "' )\n"; | |
return 1; | |
} else if (r) { | |
std::cout << "Good input\n"; | |
return 0; | |
} else { | |
std::cout << "Parse failed\n"; | |
return 1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment