HAL
parser_standard.cpp
Go to the documentation of this file.
3 
4 #include <boost/fusion/include/at_c.hpp>
5 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
6 #include <boost/spirit/home/x3.hpp>
7 #include <sstream>
8 
9 namespace hal
10 {
11  namespace BooleanFunctionParser
12  {
14  {
15  // stores the list of tokens that are generated and filled during the
16  // parsing process adn the different semantic actions
17  std::vector<Token> tokens;
18 
20  // (1) Semantic actions to generate tokens
22 
23  const auto AndAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::And()); };
24  const auto NotAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Not()); };
25  const auto OrAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Or()); };
26  const auto XorAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Xor()); };
27 
28  const auto BracketOpenAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::BracketOpen()); };
29  const auto BracketCloseAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::BracketClose()); };
30 
31  const auto VariableAction = [&tokens](auto& ctx) {
32  // # Developer Note
33  // We combine the first matched character with the remaining
34  // string and do not remove any preceding '/' character.
35  std::stringstream name;
36  name << std::string(1, boost::fusion::at_c<0>(_attr(ctx)));
37  name << boost::fusion::at_c<1>(_attr(ctx));
38 
39  tokens.emplace_back(BooleanFunctionParser::Token::Variable(name.str(), 1));
40  };
41  const auto VariableIndexAction = [&tokens](auto& ctx) {
42  // # Developer Note
43  // Since the first character is an optional '\' character and
44  // generally escaped a.k.a. removed within HAL, we also do not
45  // touch the part and only assemble the remaining string.
46  std::stringstream name;
47  name << std::string(1, boost::fusion::at_c<1>(_attr(ctx)));
48  name << boost::fusion::at_c<2>(_attr(ctx));
49  name << boost::fusion::at_c<3>(_attr(ctx));
50  name << boost::fusion::at_c<4>(_attr(ctx));
51  name << boost::fusion::at_c<5>(_attr(ctx));
52  tokens.emplace_back(BooleanFunctionParser::Token::Variable(name.str(), 1));
53  };
54  const auto ConstantAction = [&tokens](auto& ctx) {
55  const auto value = (_attr(ctx) == '0') ? BooleanFunction::Value::ZERO : BooleanFunction::Value::ONE;
56  tokens.emplace_back(BooleanFunctionParser::Token::Constant({value}));
57  };
58 
60  // (2) Rules
62 
63  namespace x3 = boost::spirit::x3;
64 
65  const auto AndRule = x3::lit("&")[AndAction];
66  const auto NotRule = x3::char_("!~")[NotAction];
67  const auto OrRule = x3::lit("|")[OrAction];
68  const auto XorRule = x3::lit("^")[XorAction];
69 
70  const auto BracketOpenRule = x3::lit("(")[BracketOpenAction];
71  const auto BracketCloseRule = x3::lit(")")[BracketCloseAction];
72 
73  const auto VariableRule = x3::lexeme[(x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_"))][VariableAction];
74  const auto VariableIndexRoundBracketRule =
75  x3::lexeme[(-(x3::char_("\\")) >> x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_") >> x3::char_("(") >> x3::int_ >> x3::char_(")"))][VariableIndexAction];
76  const auto VariableIndexSquareBracketRule =
77  x3::lexeme[(-(x3::char_("\\")) >> x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_") >> x3::char_("[") >> x3::int_ >> x3::char_("]"))][VariableIndexAction];
78  const auto VariableIndexRule = VariableIndexRoundBracketRule | VariableIndexSquareBracketRule;
79 
80  const auto ConstantRule = x3::lexeme[x3::char_("0-1")][ConstantAction];
81  const auto ConstantPrefixRule = x3::lit("0b") >> x3::lexeme[x3::char_("0-1")][ConstantAction];
82  const auto ConstantSuffixRule = x3::lexeme[x3::char_("0-1") >> x3::lit("'b1")][ConstantAction];
83 
84  auto iter = expression.begin();
85  const auto ok = x3::phrase_parse(
86  iter,
87  expression.end(),
89  // (3) Parsing Expression Grammar
91  +(AndRule | NotRule | OrRule | XorRule | VariableIndexRule | VariableRule | ConstantSuffixRule | ConstantPrefixRule | ConstantRule | BracketOpenRule | BracketCloseRule),
92  x3::space // skips any whitespace in between boolean function
93  );
94 
95  if (!ok || (iter != expression.end()))
96  {
97  return ERR("could not parse Boolean function '" + expression + "': " + std::string(iter, expression.end()));
98  }
99 
100  return OK(tokens);
101  }
102  } // namespace BooleanFunctionParser
103 } // namespace hal
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
Result< std::vector< Token > > parse_with_standard_grammar(const std::string &expression)
std::string name
static Token Constant(std::vector< BooleanFunction::Value > value)
static Token Variable(std::string name, u16 size)