Created
January 16, 2014 12:32
-
-
Save milesrout/8454266 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
#include <cstdio> | |
#include <cstdint> | |
#include <string> | |
#include <boost/spirit/include/lex_lexertl.hpp> | |
#include <boost/spirit/include/qi.hpp> | |
namespace jupiter { | |
namespace lex = boost::spirit::lex; | |
namespace qi = boost::spirit::qi; | |
template <typename Lexer> | |
struct lexer : lex::lexer<Lexer> { | |
lexer() | |
: comma(",") | |
, colon(":") | |
, lbrack("\\["), rbrack("\\]") | |
, lparen("\\("), rparen("\\)") | |
, plus("\\+") | |
, instruction("set|add|sub|mul|mli|div|dvi|mod|mdi|and|bor|xor|shr|asr|shl|ifb|ifc|ife|ifn|ifl|ifg|ifa|ifu|adx|sbx|sti|std|jsr|int|iag|ias|rfi|iaq|hwn|hwq|hwi") | |
, value("a|b|c|x|y|z|i|j|pc|sp|ia|ex|push|pop|peek|pick") | |
, identifier("[A-Za-z_][A-Za-z0-9_]*") | |
, hex_integer("0x[0-9A-Fa-f]+") | |
, dec_integer("[1-9][0-9]+") | |
, oct_integer("0[0-7]*") | |
, bin_integer("0b[01]+") | |
{ | |
this->self = comma | colon | lbrack | rbrack | lparen | rparen | plus | instruction | value | identifier | hex_integer | dec_integer | oct_integer | bin_integer; | |
} | |
lex::token_def<> comma, colon, lbrack, rbrack, lparen, rparen, plus; | |
lex::token_def<std::string> instruction, value, identifier; | |
lex::token_def<std::uint16_t> hex_integer, dec_integer, oct_integer, bin_integer; | |
}; | |
namespace parser_semantic_actions { | |
void print(std::string attr) | |
{ | |
std::puts(attr.c_str()); | |
} | |
void hello() | |
{ | |
std::puts("Hello!"); | |
} | |
} | |
template <typename Iterator> | |
struct grammar : qi::grammar<Iterator> { | |
template <typename Token> | |
grammar(Token const& token) | |
: grammar::base_type(start) | |
{ | |
namespace psa = parser_semantic_actions; | |
// attribute: std::array<std::string, 3> | |
instruction = | |
token.instruction [&psa::print] | |
>> token.value [&psa::print] | |
>> token.comma | |
>> token.value [&psa::print]; | |
/* | |
token.instruction [ ( [](std::string attr){ std::puts(attr.c_str()); } ) ] | |
>> token.value [ ( [](std::string attr){ std::puts(attr.c_str()); } ) ] | |
>> token.comma | |
>> token.value [ ( [](std::string attr){ std::puts(attr.c_str()); } ) ]; | |
*/ | |
// attribute: std::string | |
label = token.identifier [ ( [](std::string attr){ std::puts(attr.c_str()); } ) ] >> token.colon; | |
// attribute: boost::variant<std::array<std::string, 3>, std::string> | |
statement = instruction | label; | |
// attribute: std::vector<boost::variant<std::array<std::string, 3>, std::string>> | |
start = (*statement) [&psa::hello]; | |
} | |
qi::rule<Iterator> start, statement, label, instruction; | |
}; | |
} | |
int main(int argc, char **argv) | |
{ | |
namespace lex = boost::spirit::lex; | |
namespace qi = boost::spirit::qi; | |
namespace psa = jupiter::parser_semantic_actions; | |
std::string str = "!!foobar: set a, b"; | |
typedef lex::lexertl::token<char const *, boost::mpl::vector<std::string> > token_type; | |
typedef lex::lexertl::lexer<token_type> lexer_type; | |
typedef jupiter::lexer<lexer_type>::iterator_type iterator_type; | |
jupiter::lexer<lexer_type> lexer; | |
jupiter::grammar<iterator_type> grammar(lexer); | |
char const *first = str.c_str(); | |
char const *last = &first[str.size()]; | |
bool r = lex::tokenize_and_parse(first, last, lexer, grammar[&psa::hello]); | |
if (r) { | |
std::puts("Successful."); | |
} else { | |
std::string rest(first, last); | |
std::printf("Unsuccessful. Stopped at: \"%s\"\n.", rest.c_str()); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment