x3: Parsing with lexer tokens
Mikael Asplund <[email protected]>
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
Hi!
I'm trying to use spirit x3 to parse output from my lexer (needed), which is a vector of tokens. I'm running into all sorts of compiler errors, though, and there are no examples out there that I could find, so I wrote a minimal example and put it online to request comments from you on how to proceed.
Please have a look here: http://coliru.stacked-crooked.com/a/8975361b37f0c640
This little example is supposed to be run like this: ./a.out 1 + 3
Any help?
/Mikael
PS. I'll include the code here too, but it's probably more readable in the link above. Here we go:
#include <string>
#include <vector>
#include <cctype>
#include <iostream>
#include <boost/spirit/home/x3.hpp>
using std::string;
using std::vector;
namespace x3 = boost::spirit::x3;
int parse_input(vector<string> v);
int main(int argc, const char* argv[]) {
if (argc > 1) {
return parse_input(vector<string>(&argv[1], &argv[argc + !argc]));
}
return -1;
}
namespace lexer {
struct SourcePosition {
string file;
int line = -1;
};
enum class TokenType { OPERATOR, NUMBER, IDENTIFIER };
struct Token : public SourcePosition {
Token(TokenType t, const string& s, const SourcePosition& pos = SourcePosition())
: SourcePosition(pos), type(t), str(s) {}
TokenType type;
string str;
bool operator == (const Token& o) { // Token with empty string will match any token of that type
return type == o.type && (str == o.str || str.empty() || o.str.empty());
}
};
std::ostream& operator<<(std::ostream& o, const TokenType& t) {
return o << (t == TokenType::OPERATOR ? "OPERATOR" :
t == TokenType::NUMBER ? "NUMBER" : "IDENTIFIER");
}
std::ostream& operator<<(std::ostream& o, const Token& t) {
return o << t.type << "(\"" << t.str << "\")";
}
vector<Token> lex(vector<string> v) {
vector<Token> out;
auto conforms_to = [](string s, auto pred) {
return s.end() != std::find_if(s.begin(), s.end(), pred);
};
for (auto& s : v) {
if (conforms_to(s, [](char c){ return std::isdigit(c); })) {
out.push_back(Token(TokenType::NUMBER, s));
} else if (conforms_to(s, [](char c){ return std::isalnum(c); })) {
out.push_back(Token(TokenType::IDENTIFIER, s));
} else {
out.push_back(Token(TokenType::OPERATOR, s));
}
}
return out;
}
}
namespace parser {
using lexer::Token;
using lexer::TokenType;
struct TokenLiteralParser : x3::parser<TokenLiteralParser> {
TokenLiteralParser(const Token& iTok) : tok(iTok) {}
template <typename It, typename Ctx, typename A>
bool parse(It& first, const It& last, const Ctx& ctx, x3::unused_type, A& attr) const {
if (first != last && *first == tok) {
++first;
return true;
}
return false;
}
Token tok;
};
Token TokenAnyNumber(TokenType::NUMBER, "");
Token TokenAnyIdentifier(TokenType::IDENTIFIER, "");
Token TokenPlus(TokenType::OPERATOR, "+");
Token TokenMinus(TokenType::OPERATOR, "-");
}
struct Outputter {
template <typename T>
Outputter& operator=(const T& t) {
std::cout << "output => " << typeid(t).name() << ": " << t << std::endl;
return *this;
}
} outputter;
int parse_input(vector<string> v) {
using namespace parser;
using TL = TokenLiteralParser;
auto lexed = lexer::lex(v);
std::copy(lexed.begin(), lexed.end(), std::ostream_iterator<Token>(std::cout << "\n------ TOKENS ------\n", "\n"));
std::cout << "--------------------\n";
auto first = lexed.begin();
auto last = lexed.end();
Outputter out;
bool r = phrase_parse(first, last,
// Begin grammar
(
(TL(TokenAnyNumber) % (TL(TokenPlus) | TL(TokenMinus)))
),
// End grammar
x3::unused, out);
return !r;
}
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general