cprover
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 
17 #include <algorithm>
18 #include <cmath>
19 #include <iostream>
20 #include <iterator>
21 #include <util/string_constant.h>
22 
24 
25 extern char *yystatement_listtext;
26 
32 static irep_idt find_name(const exprt &root)
33 {
34  for(const exprt &op : root.operands())
35  {
36  if(op.get(ID_statement_list_type) == ID_statement_list_identifier)
37  return op.get(ID_value);
38  }
39  UNREACHABLE; // Root expression should always have a name
40 }
41 
43 {
44  const exprt::operandst &ops = tag_list.operands();
45  transform(
46  begin(ops),
47  end(ops),
48  std::back_inserter(parse_tree.tags),
49  static_cast<const symbol_exprt &(*)(const exprt &)>(to_symbol_expr));
50 }
51 
57 static std::string find_version(const exprt &root)
58 {
59  for(const exprt &op : root.operands())
60  {
61  if(op.get(ID_statement_list_type) == ID_statement_list_version)
62  {
63  const string_constantt &constant{to_string_constant(op)};
64  return id2string(constant.get_value());
65  }
66  }
67  UNREACHABLE; // Root expression should always have a version
68 }
69 
75 static typet find_return_value(const exprt &root)
76 {
77  INVARIANT(
78  root.id() == ID_statement_list_function,
79  "Expression ID should be statement_list_function");
80 
81  for(const exprt &op : root.operands())
82  {
83  if(op.get(ID_statement_list_type) == ID_statement_list_return)
84  return op.type();
85  }
86 
87  UNREACHABLE; // Root expression of FC should always have a return value
88 }
89 
95 static exprt find_variable_list(const exprt &root)
96 {
97  for(const exprt &op : root.operands())
98  {
99  if(op.id() == ID_statement_list_var_decls)
100  return op;
101  }
102  UNREACHABLE; // Root expression should always have a variable list
103 }
104 
112  const exprt &var_list)
113 {
114  for(const exprt &entry : var_list.operands())
115  {
116  std::vector<symbol_exprt> symbols;
117  exprt default_value = nil_exprt();
118  for(const exprt &part : entry.operands())
119  {
120  const symbol_exprt *const symbol =
121  expr_try_dynamic_cast<symbol_exprt>(part);
122  if(symbol)
123  symbols.push_back(*symbol);
124  else
125  default_value = part;
126  }
127 
128  for(const symbol_exprt &symbol : symbols)
129  {
131  if(default_value.is_not_nil())
132  declaration.default_value = default_value;
133  parse_tree_list.push_back(declaration);
134  }
135  }
136 }
137 
142 static void fill_temp_vars(
144  const exprt &temp_vars)
145 {
146  for(const exprt &entry : temp_vars.operands())
147  {
148  for(const exprt &part : entry.operands())
149  {
150  const symbol_exprt *const symbol =
151  expr_try_dynamic_cast<symbol_exprt>(part);
152  if(symbol)
153  {
155  parse_tree_list.push_back(declaration);
156  }
157  else
158  UNREACHABLE; // Temp variables should not have an initial value.
159  }
160  }
161 }
162 
166 static void find_variables(
168  const exprt &var_decls)
169 {
170  for(const exprt &decls : var_decls.operands())
171  {
172  if(decls.id() == ID_statement_list_var_input)
173  fill_vars_with_default_values(function.var_input, decls);
174  else if(decls.id() == ID_statement_list_var_inout)
175  fill_vars_with_default_values(function.var_inout, decls);
176  else if(decls.id() == ID_statement_list_var_output)
177  fill_vars_with_default_values(function.var_output, decls);
178  else if(decls.id() == ID_statement_list_var_constant)
179  fill_vars_with_default_values(function.var_constant, decls);
180  else if(decls.id() == ID_statement_list_var_temp)
181  fill_temp_vars(function.var_temp, decls);
182  }
183 }
184 
188 static void find_variables(
190  const exprt &var_decls)
191 {
192  for(const exprt &decls : var_decls.operands())
193  {
194  if(ID_statement_list_var_input == decls.id())
196  else if(ID_statement_list_var_inout == decls.id())
198  else if(ID_statement_list_var_output == decls.id())
200  else if(ID_statement_list_var_static == decls.id())
202  else if(ID_statement_list_var_constant == decls.id())
204  else if(ID_statement_list_var_temp == decls.id())
205  fill_temp_vars(block.var_temp, decls);
206  }
207 }
208 
214 static exprt find_network_list(const exprt &root)
215 {
216  for(const exprt &op : root.operands())
217  {
218  if(op.id() == ID_statement_list_networks)
219  return op;
220  }
221  UNREACHABLE; // Root expression should always have a network list
222 }
223 
228 static std::string find_network_title(const exprt &network)
229 {
230  for(const exprt &network_element : network.operands())
231  {
232  if(network_element.get(ID_statement_list_type) == ID_statement_list_title)
233  return network_element.get(ID_value).c_str();
234  }
235  UNREACHABLE; // Network expression should always have a title
236 }
237 
243 static exprt find_network_instructions(const exprt &network)
244 {
245  for(const exprt &network_element : network.operands())
246  {
247  if(network_element.id() == ID_statement_list_instructions)
248  return network_element;
249  }
250  UNREACHABLE; // Network expression should always have an instruction list
251 }
252 
256 static void find_instructions(
258  const exprt &instructions)
259 {
260  for(const exprt &instruction_expr : instructions.operands())
261  {
263  codet code_token(to_multi_ary_expr(instruction_expr).op0().id());
264  for(const exprt &operand : instruction_expr.operands())
265  {
266  if(operand.is_not_nil() && operand.id() != code_token.get_statement())
267  code_token.add_to_operands(operand);
268  }
269  instruction.add_token(code_token);
270  network.add_instruction(instruction);
271  }
272 }
273 
278 static void find_networks(
280  const exprt &network_list)
281 {
282  for(const exprt &expr_network : network_list.operands())
283  {
284  const std::string title(find_network_title(expr_network));
286  const exprt instructions = find_network_instructions(expr_network);
287  find_instructions(network, instructions);
288  module.add_network(network);
289  }
290 }
291 
293 {
294  INVARIANT(
295  block.id() == ID_statement_list_function_block,
296  "Root expression ID should be ID_statement_list_function_block");
297 
298  // Generate new function block.
300  find_version(block)};
301 
302  // Fill the block with networks and variables.
304  find_networks(fb, find_network_list(block));
305 
307 }
308 
310 {
311  INVARIANT(
312  function.id() == ID_statement_list_function,
313  "Expression ID should be statement_list_function");
314 
315  // Generate new function.
317  find_name(function), find_version(function), find_return_value(function)};
318 
319  // Fill the function with networks and variables.
320  find_variables(fn, find_variable_list(function));
321  find_networks(fn, find_network_list(function));
322 
324 }
325 
327 {
328  return yystatement_listparse() != 0;
329 }
330 
331 int yystatement_listerror(const std::string &error)
332 {
334  return 0;
335 }
336 
338 {
339  parsert::clear();
340  parse_tree.clear();
341 }
342 
343 void statement_list_parsert::print_tree(std::ostream &out) const
344 {
346 }
347 
349 {
350  parse_tree.swap(other);
351 }
Data structure for representing an arbitrary statement in a program.
Definition: std_code.h:35
const irep_idt & get_statement() const
Definition: std_code.h:71
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:37
Base class for all expressions.
Definition: expr.h:54
std::vector< exprt > operandst
Definition: expr.h:56
operandst & operands()
Definition: expr.h:96
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:140
bool is_not_nil() const
Definition: irep.h:391
const irep_idt & id() const
Definition: irep.h:407
The NIL expression.
Definition: std_expr.h:2735
void parse_error(const std::string &message, const std::string &before)
Definition: parser.cpp:30
virtual void clear()
Definition: parser.h:32
Intermediate representation of a parsed Statement List file before converting it into a goto program.
std::list< var_declarationt > var_declarationst
void clear()
Removes all functions and function blocks from the parse tree.
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 clear() override
Removes all functions and function blocks from the parse tree and clears the internal state of the pa...
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:81
The type of an expression, extends irept.
Definition: type.h:28
const std::string & id2string(const irep_idt &d)
Definition: irep.h:49
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:504
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:424
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.
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.
statement_list_parsert statement_list_parser
Instance of the parser, used by other modules.
static std::string find_network_title(const exprt &network)
Searches for the title of a network inside of its root expression.
int yystatement_listerror(const std::string &error)
Forwards any errors that are encountered during the parse process.
static exprt find_variable_list(const exprt &root)
Searches for the variable list of the TIA module inside of its root expression.
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.
char * yystatement_listtext
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.
Statement List Language Parser.
int yystatement_listparse()
Defined in statement_list_y.tab.cpp.
Statement List Type Helper.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:190
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:816
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.
optionalt< exprt > default_value
Optional default value of the variable.