CBMC
statement_list_parser.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Statement List Language Parser
4 
5 Author: Matthias Weiss, matthias.weiss@diffblue.com
6 
7 \*******************************************************************/
8 
11 
12 #include "statement_list_parser.h"
13 
14 #include <util/std_code.h>
15 #include <util/string_constant.h>
16 
19 
20 #include <algorithm>
21 #include <iostream>
22 #include <iterator>
23 
25 
31 static irep_idt find_name(const exprt &root)
32 {
33  for(const exprt &op : root.operands())
34  {
35  if(op.get(ID_statement_list_type) == ID_statement_list_identifier)
36  return op.get(ID_value);
37  }
38  UNREACHABLE; // Root expression should always have a name
39 }
40 
42 {
43  const exprt::operandst &ops = tag_list.operands();
44  transform(
45  begin(ops),
46  end(ops),
47  std::back_inserter(parse_tree.tags),
48  static_cast<const symbol_exprt &(*)(const exprt &)>(to_symbol_expr));
49 }
50 
56 static std::string find_version(const exprt &root)
57 {
58  for(const exprt &op : root.operands())
59  {
60  if(op.get(ID_statement_list_type) == ID_statement_list_version)
61  {
62  const string_constantt &constant{to_string_constant(op)};
63  return id2string(constant.value());
64  }
65  }
66  UNREACHABLE; // Root expression should always have a version
67 }
68 
74 static typet find_return_value(const exprt &root)
75 {
76  INVARIANT(
77  root.id() == ID_statement_list_function,
78  "Expression ID should be statement_list_function");
79 
80  for(const exprt &op : root.operands())
81  {
82  if(op.get(ID_statement_list_type) == ID_statement_list_return)
83  return op.type();
84  }
85 
86  UNREACHABLE; // Root expression of FC should always have a return value
87 }
88 
94 static exprt find_variable_list(const exprt &root)
95 {
96  for(const exprt &op : root.operands())
97  {
98  if(op.id() == ID_statement_list_var_decls)
99  return op;
100  }
101  UNREACHABLE; // Root expression should always have a variable list
102 }
103 
111  const exprt &var_list)
112 {
113  for(const exprt &entry : var_list.operands())
114  {
115  std::vector<symbol_exprt> symbols;
116  exprt default_value = nil_exprt();
117  for(const exprt &part : entry.operands())
118  {
119  const symbol_exprt *const symbol =
120  expr_try_dynamic_cast<symbol_exprt>(part);
121  if(symbol)
122  symbols.push_back(*symbol);
123  else
124  default_value = part;
125  }
126 
127  for(const symbol_exprt &symbol : symbols)
128  {
130  if(default_value.is_not_nil())
131  declaration.default_value = default_value;
132  parse_tree_list.push_back(declaration);
133  }
134  }
135 }
136 
141 static void fill_temp_vars(
143  const exprt &temp_vars)
144 {
145  for(const exprt &entry : temp_vars.operands())
146  {
147  for(const exprt &part : entry.operands())
148  {
149  const symbol_exprt *const symbol =
150  expr_try_dynamic_cast<symbol_exprt>(part);
151  if(symbol)
152  {
154  parse_tree_list.push_back(declaration);
155  }
156  else
157  UNREACHABLE; // Temp variables should not have an initial value.
158  }
159  }
160 }
161 
165 static void find_variables(
167  const exprt &var_decls)
168 {
169  for(const exprt &decls : var_decls.operands())
170  {
171  if(decls.id() == ID_statement_list_var_input)
172  fill_vars_with_default_values(function.var_input, decls);
173  else if(decls.id() == ID_statement_list_var_inout)
174  fill_vars_with_default_values(function.var_inout, decls);
175  else if(decls.id() == ID_statement_list_var_output)
176  fill_vars_with_default_values(function.var_output, decls);
177  else if(decls.id() == ID_statement_list_var_constant)
178  fill_vars_with_default_values(function.var_constant, decls);
179  else if(decls.id() == ID_statement_list_var_temp)
180  fill_temp_vars(function.var_temp, decls);
181  }
182 }
183 
187 static void find_variables(
189  const exprt &var_decls)
190 {
191  for(const exprt &decls : var_decls.operands())
192  {
193  if(ID_statement_list_var_input == decls.id())
195  else if(ID_statement_list_var_inout == decls.id())
197  else if(ID_statement_list_var_output == decls.id())
199  else if(ID_statement_list_var_static == decls.id())
201  else if(ID_statement_list_var_constant == decls.id())
203  else if(ID_statement_list_var_temp == decls.id())
204  fill_temp_vars(block.var_temp, decls);
205  }
206 }
207 
213 static exprt find_network_list(const exprt &root)
214 {
215  for(const exprt &op : root.operands())
216  {
217  if(op.id() == ID_statement_list_networks)
218  return op;
219  }
220  UNREACHABLE; // Root expression should always have a network list
221 }
222 
227 static std::string find_network_title(const exprt &network)
228 {
229  for(const exprt &network_element : network.operands())
230  {
231  if(network_element.get(ID_statement_list_type) == ID_statement_list_title)
232  return network_element.get(ID_value).c_str();
233  }
234  UNREACHABLE; // Network expression should always have a title
235 }
236 
242 static exprt find_network_instructions(const exprt &network)
243 {
244  for(const exprt &network_element : network.operands())
245  {
246  if(network_element.id() == ID_statement_list_instructions)
247  return network_element;
248  }
249  UNREACHABLE; // Network expression should always have an instruction list
250 }
251 
255 static void find_instructions(
257  const exprt &instructions)
258 {
259  for(const exprt &instruction_expr : instructions.operands())
260  {
262 
263  codet code_token(to_multi_ary_expr(instruction_expr).op0().id());
264  string_constantt label{ID_nil};
265  for(auto op_it = std::next(instruction_expr.operands().begin());
266  op_it != end(instruction_expr.operands());
267  ++op_it)
268  {
269  if(op_it->get(ID_statement_list_type) == ID_label)
270  label = to_string_constant(*op_it);
271  else if(op_it->is_not_nil())
272  code_token.add_to_operands(*op_it);
273  }
274 
275  if(label.value() == ID_nil)
276  instruction.add_token(code_token);
277  else
278  instruction.add_token(code_labelt{label.value(), code_token});
279 
280  network.add_instruction(instruction);
281  }
282 }
283 
288 static void find_networks(
290  const exprt &network_list)
291 {
292  for(const exprt &expr_network : network_list.operands())
293  {
294  const std::string title(find_network_title(expr_network));
296  const exprt instructions = find_network_instructions(expr_network);
297  find_instructions(network, instructions);
298  module.add_network(network);
299  }
300 }
301 
303 {
304  INVARIANT(
305  block.id() == ID_statement_list_function_block,
306  "Root expression ID should be ID_statement_list_function_block");
307 
308  // Generate new function block.
310  find_version(block)};
311 
312  // Fill the block with networks and variables.
314  find_networks(fb, find_network_list(block));
315 
317 }
318 
320 {
321  INVARIANT(
322  function.id() == ID_statement_list_function,
323  "Expression ID should be statement_list_function");
324 
325  // Generate new function.
327  find_name(function), find_version(function), find_return_value(function)};
328 
329  // Fill the function with networks and variables.
330  find_variables(fn, find_variable_list(function));
331  find_networks(fn, find_network_list(function));
332 
334 }
335 
341 void yystatement_listset_debug(int, void *);
342 
344 {
345  void *scanner;
346  yystatement_listlex_init_extra(this, &scanner);
347 #ifdef STATEMENT_LIST_DEBUG
348  yystatement_listset_debug(1, scanner);
349 #endif
350  bool parse_fail = yystatement_listparse(*this, scanner) != 0;
352  return parse_fail;
353 }
354 
355 void statement_list_parsert::print_tree(std::ostream &out) const
356 {
358 }
359 
361 {
362  parse_tree.swap(other);
363 }
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
codet representation of a label for branch targets.
Definition: std_code.h:959
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
std::vector< exprt > operandst
Definition: expr.h:58
operandst & operands()
Definition: expr.h:94
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
The NIL expression.
Definition: std_expr.h:3073
Intermediate representation of a parsed Statement List file before converting it into a goto program.
std::list< var_declarationt > var_declarationst
void add_function_block(function_blockt &block)
Adds a function block to the parse tree.
std::vector< symbol_exprt > tags
List of tags that were included in the source.
void add_function(functiont &function)
Adds a function to the parse tree.
void swap(statement_list_parse_treet &other)
Swaps the contents of the parse tree with the parameter.
Responsible for starting the parse process and to translate the result into a statement_list_parse_tr...
statement_list_parse_treet parse_tree
Tree that is being filled by the parsing process.
void add_tag_list(const exprt &tag_list)
Adds a tag list to the parse tree by converting the tag_list expression tree.
void add_function_block(const exprt &block)
Adds a function block to the parse tree by converting the block expression tree.
void print_tree(std::ostream &out) const
Prints the parse tree of this instance to the given output stream.
void add_function(const exprt &function)
Adds a function to the parse tree by converting the function expression tree.
void swap_tree(statement_list_parse_treet &other)
Swaps the contents of the parse tree of this instance with other.
bool parse() override
Starts the parsing process and saves the result inside of this instance's parse tree.
Expression to hold a symbol (variable)
Definition: std_expr.h:131
The type of an expression, extends irept.
Definition: type.h:29
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
Statement List Language Parse Tree.
void output_parse_tree(std::ostream &out, const statement_list_parse_treet &parse_tree)
Prints the given Statement List parse tree in a human-readable form to the given output stream.
Statement List Language Parse Tree Output.
static void find_variables(statement_list_parse_treet::functiont &function, const exprt &var_decls)
Adds all valid variable declarations to the given function.
static std::string find_version(const exprt &root)
Searches for the version of the TIA module inside of its root expression.
void yystatement_listset_debug(int, void *)
static exprt find_network_instructions(const exprt &network)
Searches for the instruction list of a network inside of its root expression.
static void find_instructions(statement_list_parse_treet::networkt &network, const exprt &instructions)
Adds all valid instructions to the given network.
static void find_networks(statement_list_parse_treet::tia_modulet &module, const exprt &network_list)
Adds all valid networks and their instructions to the given function element.
static exprt find_network_list(const exprt &root)
Searches for the network list of the TIA element inside of its root expression.
static std::string find_network_title(const exprt &network)
Searches for the title of a network inside of its root expression.
int yystatement_listlex_init_extra(statement_list_parsert *, void **)
static exprt find_variable_list(const exprt &root)
Searches for the variable list of the TIA module inside of its root expression.
int yystatement_listparse(statement_list_parsert &, void *)
Defined in statement_list_y.tab.cpp.
static irep_idt find_name(const exprt &root)
Searches for the name of the TIA module inside of its root expression.
static void fill_temp_vars(statement_list_parse_treet::var_declarationst &parse_tree_list, const exprt &temp_vars)
Adds all temp variable declarations (variable declarations which can't have a default value) to the g...
static typet find_return_value(const exprt &root)
Searches for the return type of a function inside of its root expression.
static void fill_vars_with_default_values(statement_list_parse_treet::var_declarationst &parse_tree_list, const exprt &var_list)
Adds all variable declarations (which can have a default value) to the given list.
int yystatement_listlex_destroy(void *)
Statement List Language Parser.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:987
const string_constantt & to_string_constant(const exprt &expr)
Structure for a simple function block in Statement List.
var_declarationst var_static
FB-exclusive static variable declarations.
Structure for a simple function in Statement List.
Represents a regular Statement List instruction which consists out of one or more codet tokens.
void add_token(const codet &token)
Adds a codet element to the list of all tokens.
Representation of a network in Siemens TIA.
void add_instruction(const instructiont &inst)
Adds an instruction to the network.
Base element of all modules in the Totally Integrated Automation (TIA) portal by Siemens.
var_declarationst var_constant
Constant variable declarations.
var_declarationst var_input
Input variable declarations.
var_declarationst var_inout
Inout variable declarations.
void add_network(networkt &network)
Adds a network to the function.
var_declarationst var_temp
Temp variable declarations.
var_declarationst var_output
Output variable declarations.
Struct for a single variable declaration in Statement List.
std::optional< exprt > default_value
Optional default value of the variable.