HAL  v4.5.0-257-ge24279b4e
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
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  {
13  Result<std::vector<Token>> parse_with_standard_grammar(const std::string& expression, const std::map<std::string, u16>& var_sizes)
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 
19  // Looks up a variable's bit-width from the caller-supplied map; defaults to 1 when absent.
20  const auto var_size = [&var_sizes](const std::string& name) -> u16 {
21  if (auto it = var_sizes.find(name); it != var_sizes.end())
22  {
23  return it->second;
24  }
25  return 1;
26  };
27 
29  // (1) Semantic actions to generate tokens
31 
32  const auto AndAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::And()); };
33  const auto NotAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Not()); };
34  const auto OrAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Or()); };
35  const auto XorAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Xor()); };
36  const auto EqAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Eq()); };
37  const auto QuestionAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Question()); };
38  const auto ColonAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Colon()); };
39  const auto AddAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Add()); };
40  const auto SubAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Sub()); };
41  const auto MulAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::Mul()); };
42 
43  const auto BracketOpenAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::BracketOpen()); };
44  const auto BracketCloseAction = [&tokens](auto& /* ctx */) { tokens.emplace_back(BooleanFunctionParser::Token::BracketClose()); };
45 
46  const auto MultiBitBinAction = [&tokens](auto& ctx) {
47  // _attr(ctx) is a vector<char>/std::string of binary digits (MSB first).
48  const auto& bits = _attr(ctx);
49  std::vector<BooleanFunction::Value> values;
50  values.reserve(bits.size());
51  // BooleanFunction stores constants LSB first, so iterate in reverse.
52  for (auto it = bits.rbegin(); it != bits.rend(); ++it)
53  {
54  values.push_back((*it == '0') ? BooleanFunction::Value::ZERO : BooleanFunction::Value::ONE);
55  }
56  tokens.emplace_back(BooleanFunctionParser::Token::Constant(values));
57  };
58 
59  const auto MultiBitHexAction = [&tokens](auto& ctx) {
60  // Each hex digit contributes 4 bits; LSB first.
61  const auto& digits = _attr(ctx);
62  std::vector<BooleanFunction::Value> values;
63  values.reserve(digits.size() * 4);
64  for (auto it = digits.rbegin(); it != digits.rend(); ++it)
65  {
66  const char c = *it;
67  u8 nibble = 0;
68  if (c >= '0' && c <= '9')
69  nibble = c - '0';
70  else if (c >= 'a' && c <= 'f')
71  nibble = c - 'a' + 10;
72  else
73  nibble = c - 'A' + 10;
74  for (int i = 0; i < 4; ++i)
75  {
76  values.push_back((nibble & (1 << i)) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
77  }
78  }
79  tokens.emplace_back(BooleanFunctionParser::Token::Constant(values));
80  };
81 
82  const auto MultiBitOctAction = [&tokens](auto& ctx) {
83  // Each octal digit contributes 3 bits; LSB first.
84  const auto& digits = _attr(ctx);
85  std::vector<BooleanFunction::Value> values;
86  values.reserve(digits.size() * 3);
87  for (auto it = digits.rbegin(); it != digits.rend(); ++it)
88  {
89  const u8 oct = *it - '0';
90  for (int i = 0; i < 3; ++i)
91  {
92  values.push_back((oct & (1 << i)) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
93  }
94  }
95  tokens.emplace_back(BooleanFunctionParser::Token::Constant(values));
96  };
97 
98  const auto VariableAction = [&tokens, &var_size](auto& ctx) {
99  // # Developer Note
100  // We combine the first matched character with the remaining
101  // string and do not remove any preceding '/' character.
102  std::stringstream name;
103  name << std::string(1, boost::fusion::at_c<0>(_attr(ctx)));
104  name << boost::fusion::at_c<1>(_attr(ctx));
105 
106  tokens.emplace_back(BooleanFunctionParser::Token::Variable(name.str(), var_size(name.str())));
107  };
108  const auto VariableIndexAction = [&tokens, &var_size](auto& ctx) {
109  // # Developer Note
110  // Since the first character is an optional '\' character and
111  // generally escaped a.k.a. removed within HAL, we also do not
112  // touch the part and only assemble the remaining string.
113  std::stringstream name;
114  name << std::string(1, boost::fusion::at_c<1>(_attr(ctx)));
115  name << boost::fusion::at_c<2>(_attr(ctx));
116  name << boost::fusion::at_c<3>(_attr(ctx));
117  name << boost::fusion::at_c<4>(_attr(ctx));
118  name << boost::fusion::at_c<5>(_attr(ctx));
119  tokens.emplace_back(BooleanFunctionParser::Token::Variable(name.str(), var_size(name.str())));
120  };
121  const auto ConstantAction = [&tokens](auto& ctx) {
122  const auto value = (_attr(ctx) == '0') ? BooleanFunction::Value::ZERO : BooleanFunction::Value::ONE;
123  tokens.emplace_back(BooleanFunctionParser::Token::Constant({value}));
124  };
125 
127  // (2) Rules
129 
130  namespace x3 = boost::spirit::x3;
131 
132  const auto AndRule = x3::lit("&")[AndAction];
133  const auto NotRule = x3::char_("!~")[NotAction];
134  const auto OrRule = x3::lit("|")[OrAction];
135  const auto XorRule = x3::lit("^")[XorAction];
136  const auto EqRule = x3::lit("==")[EqAction];
137  const auto QuestionRule = x3::lit("?")[QuestionAction];
138  const auto ColonRule = x3::lit(":")[ColonAction];
139  const auto AddRule = x3::lit("+")[AddAction];
140  const auto SubRule = x3::lit("-")[SubAction];
141  const auto MulRule = x3::lit("*")[MulAction];
142 
143  const auto BracketOpenRule = x3::lit("(")[BracketOpenAction];
144  const auto BracketCloseRule = x3::lit(")")[BracketCloseAction];
145 
146  const auto VariableRule = x3::lexeme[(x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_"))][VariableAction];
147  const auto VariableIndexRoundBracketRule =
148  x3::lexeme[(-(x3::char_("\\")) >> x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_") >> x3::char_("(") >> x3::int_ >> x3::char_(")"))][VariableIndexAction];
149  const auto VariableIndexSquareBracketRule =
150  x3::lexeme[(-(x3::char_("\\")) >> x3::char_("a-zA-Z") >> *x3::char_("a-zA-Z0-9_") >> x3::char_("[") >> x3::int_ >> x3::char_("]"))][VariableIndexAction];
151  const auto VariableIndexRule = VariableIndexRoundBracketRule | VariableIndexSquareBracketRule;
152 
153  const auto ConstantRule = x3::lexeme[x3::char_("0-1")][ConstantAction];
154  const auto ConstantBinRule = x3::lit("0b") >> x3::lexeme[+x3::char_("0-1")][MultiBitBinAction];
155  const auto ConstantHexRule = x3::lit("0x") >> x3::lexeme[+x3::char_("0-9a-fA-F")][MultiBitHexAction];
156  const auto ConstantOctRule = x3::lit("0o") >> x3::lexeme[+x3::char_("0-7")][MultiBitOctAction];
157  const auto ConstantSuffixRule = x3::lexeme[x3::char_("0-1") >> x3::lit("'b1")][ConstantAction];
158 
159  auto iter = expression.begin();
160  const auto ok = x3::phrase_parse(
161  iter,
162  expression.end(),
164  // (3) Parsing Expression Grammar
166  +(AndRule | NotRule | OrRule | XorRule | EqRule | QuestionRule | ColonRule | AddRule | SubRule | MulRule | VariableIndexRule | VariableRule | ConstantSuffixRule | ConstantHexRule
167  | ConstantOctRule | ConstantBinRule | ConstantRule | BracketOpenRule | BracketCloseRule),
168  x3::space // skips any whitespace in between boolean function
169  );
170 
171  if (!ok || (iter != expression.end()))
172  {
173  return ERR("could not parse Boolean function '" + expression + "': " + std::string(iter, expression.end()));
174  }
175 
176  return OK(tokens);
177  }
178  } // namespace BooleanFunctionParser
179 } // namespace hal
uint16_t u16
Definition: defines.h:40
uint8_t u8
Definition: defines.h:39
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
Result< std::vector< Token > > parse_with_standard_grammar(const std::string &expression, const std::map< std::string, u16 > &var_sizes={})
Definition: defines.h:45
std::string name
static Token Constant(std::vector< BooleanFunction::Value > value)
static Token Variable(std::string name, u16 size)