Skip to content

Instantly share code, notes, and snippets.

@milesrout
Created January 16, 2014 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milesrout/8454266 to your computer and use it in GitHub Desktop.
Save milesrout/8454266 to your computer and use it in GitHub Desktop.
#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