HAL
parser_types.cpp
Go to the documentation of this file.
3 
4 #include <deque>
5 #include <stack>
6 
7 namespace hal
8 {
9  namespace BooleanFunctionParser
10  {
12  {
13  return Token(TokenType::And, {}, {});
14  }
15 
17  {
18  return Token(TokenType::Not, {}, {});
19  }
20 
22  {
23  return Token(TokenType::NotSuffix, {}, {});
24  }
25 
27  {
28  return Token(TokenType::Or, {}, {});
29  }
30 
32  {
33  return Token(TokenType::Xor, {}, {});
34  }
35 
36  Token Token::Variable(std::string name, u16 size)
37  {
38  return Token(TokenType::Variable, std::make_tuple(name, size), {});
39  }
40 
41  Token Token::Constant(std::vector<BooleanFunction::Value> constant)
42  {
43  return Token(TokenType::Constant, std::make_tuple("", 0), constant);
44  }
45 
47  {
48  return Token(TokenType::BracketOpen, {}, {});
49  }
50 
52  {
53  return Token(TokenType::BracketClose, {}, {});
54  }
55 
56  unsigned Token::precedence(const ParserType& parser) const
57  {
58  static const std::map<ParserType, std::map<TokenType, unsigned>> parser2precedence = {
60  std::map<TokenType, unsigned>({
62  {TokenType::Not, 4},
63  {TokenType::And, 3},
64  {TokenType::Xor, 2},
65  {TokenType::Or, 1},
66  })},
68  std::map<TokenType, unsigned>({
69  {TokenType::Not, 4},
70  {TokenType::And, 3},
71  {TokenType::Xor, 2},
72  {TokenType::Or, 1},
73  })},
74  };
75 
76  const auto& precedence = parser2precedence.at(parser);
77  if (auto iter = precedence.find(this->type); iter != precedence.end())
78  {
79  return iter->second;
80  }
81 
82  return 5;
83  }
84 
85  bool Token::is(TokenType _type) const
86  {
87  return this->type == _type;
88  }
89 
90  std::ostream& operator<<(std::ostream& os, const Token& token)
91  {
92  static const std::map<TokenType, std::string> type2str = {
93  {TokenType::And, "And"},
94  {TokenType::Or, "Or"},
95  {TokenType::Not, "Not"},
96  {TokenType::NotSuffix, "NotSuffix"},
97  {TokenType::Xor, "Xor"},
98 
99  {TokenType::BracketOpen, "BracketOpen"},
100  {TokenType::BracketClose, "BracketClose"},
101 
102  {TokenType::Variable, "Variable"},
103  {TokenType::Constant, "Constant"},
104  };
105 
106  os << "Token { " << type2str.at(token.type);
107 
108  if (token.type == TokenType::Variable)
109  {
110  os << ", " << std::get<0>(token.variable) << " (" << std::get<1>(token.variable) << ")";
111  }
112  if (token.type == TokenType::Constant)
113  {
114  os << ", "
115  << "0b";
116  for (auto i = token.constant.size(); i-- != 0;)
117  {
118  os << token.constant[i];
119  }
120  }
121 
122  os << " }";
123  return os;
124  }
125 
126  std::string Token::to_string() const
127  {
128  std::stringstream ss;
129  ss << *this;
130  return ss.str();
131  }
132 
133  Token::Token(TokenType _type, std::tuple<std::string, u16> _variable, std::vector<BooleanFunction::Value> _constant) : type(_type), variable(_variable), constant(_constant)
134  {
135  }
136 
137  Result<std::vector<Token>> reverse_polish_notation(std::vector<Token>&& tokens, const std::string& expression, const ParserType& parser)
138  {
139  std::stack<Token> operator_stack;
140  std::vector<Token> output;
141 
142  for (auto&& token : tokens)
143  {
144  switch (token.type)
145  {
146  // (1) constants / variables are always pushed into output queue
147  case TokenType::Constant:
148  case TokenType::Variable: {
149  output.emplace_back(token);
150  break;
151  }
152 
153  // (2) operations are pushed into the operator stack with respect
154  // to the operator precedence and bracket level
155  case TokenType::And:
156  case TokenType::Or:
157  case TokenType::Not:
158  case TokenType::Xor: {
159  while (!operator_stack.empty() && !operator_stack.top().is(TokenType::BracketOpen) && operator_stack.top().precedence(parser) > token.precedence(parser))
160  {
161  output.emplace_back(operator_stack.top());
162  operator_stack.pop();
163  }
164  operator_stack.push(token);
165  break;
166  }
167 
168  // (3) the liberty grammar contains suffix not operations that
169  // invert the previous operation, i.e, acts similiar to
170  // a "not" operation in reverse-polish notation. hence,
171  // we simply push a "not" the output as the previous
172  // expression has been already translated to the reverse-
173  // polish notation in the output vector.
174  case TokenType::NotSuffix: {
175  output.emplace_back(Token::Not());
176  break;
177  }
178 
179  // (4) open brackets are always pushed into the operator stack
180  case TokenType::BracketOpen: {
181  operator_stack.push(token);
182  break;
183  }
184 
185  // (5) close brackets push remaining operations into the output
186  // queue until the bracket level is closed
188  while (!operator_stack.empty() && !operator_stack.top().is(TokenType::BracketOpen))
189  {
190  output.emplace_back(operator_stack.top());
191  operator_stack.pop();
192  }
193 
194  operator_stack.pop();
195 
196  break;
197  }
198  }
199  }
200 
201  while (!operator_stack.empty())
202  {
203  if (operator_stack.top().is(TokenType::BracketOpen))
204  {
205  return ERR("could not translate '" + expression + "' to reverse polish notation: bracket level is invalid");
206  }
207 
208  output.emplace_back(operator_stack.top());
209  operator_stack.pop();
210  }
211  return OK(output);
212  }
213 
214  Result<BooleanFunction> translate(std::vector<Token>&& tokens, const std::string& expression)
215  {
216  auto nodes = std::vector<BooleanFunction::Node>();
217  nodes.reserve(tokens.size());
218 
219  for (auto&& token : tokens)
220  {
222  {
223  return ERR("could not translate tokens: tokens are imbalanced, i.e., the operation comes before the operand nodes");
224  }
225 
226  switch (token.type)
227  {
229  nodes.emplace_back(BooleanFunction::Node::Operation(BooleanFunction::NodeType::And, nodes.back().size));
230  break;
232  nodes.emplace_back(BooleanFunction::Node::Operation(BooleanFunction::NodeType::Or, nodes.back().size));
233  break;
235  nodes.emplace_back(BooleanFunction::Node::Operation(BooleanFunction::NodeType::Not, nodes.back().size));
236  break;
238  nodes.emplace_back(BooleanFunction::Node::Operation(BooleanFunction::NodeType::Xor, nodes.back().size));
239  break;
240 
242  nodes.emplace_back(BooleanFunction::Node::Variable(std::get<0>(token.variable), std::get<1>(token.variable)));
243  break;
245  nodes.emplace_back(BooleanFunction::Node::Constant(token.constant));
246  break;
247 
248  default:
249  return ERR("could not translate tokens: unable to handle '" + token.to_string() + "' in '" + expression + "'");
250  }
251  }
252 
253  if (auto res = BooleanFunction::build(std::move(nodes)); res.is_error())
254  {
255  return ERR_APPEND(res.get_error(), "could not translate tokens: unable to build Boolean function from vector of nodes");
256  }
257  else
258  {
259  return res;
260  }
261  }
262  } // namespace BooleanFunctionParser
263 } // namespace hal
static Result< BooleanFunction > build(std::vector< Node > &&nodes)
uint16_t u16
Definition: defines.h:40
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
parser
Definition: control.py:13
ParserType
ParserType refers to the parser identifier.
Definition: parser.h:36
@ Liberty
refers to the 'Liberty' Boolean function parser
@ Standard
refers to the 'Standard' Boolean function parser
std::ostream & operator<<(std::ostream &os, const Token &token)
Result< BooleanFunction > translate(std::vector< Token > &&tokens, const std::string &expression)
TokenType
TokenType refers to a token identifier for a Boolean function string.
Definition: parser.h:45
Result< std::vector< Token > > reverse_polish_notation(std::vector< Token > &&tokens, const std::string &expression, const ParserType &parser)
PinType type
std::string name
static Node Constant(const std::vector< BooleanFunction::Value > value)
static Node Operation(u16 type, u16 size)
static Node Variable(const std::string variable, u16 size)
Token refers to a token identifier and accompanied data.
Definition: parser.h:62
std::tuple< std::string, u16 > variable
optional value and bit-size in case token is a variable
Definition: parser.h:70
TokenType type
refers to the underlying token type identifier
Definition: parser.h:68
static Token Constant(std::vector< BooleanFunction::Value > value)
Token(TokenType _type, std::tuple< std::string, u16 > variable, std::vector< BooleanFunction::Value > constant)
Construct a new initialized Token.
bool is(TokenType type) const
static Token Variable(std::string name, u16 size)
std::vector< BooleanFunction::Value > constant
optional value in case token is a constant
Definition: parser.h:72
unsigned precedence(const ParserType &type) const