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 
16 #include <algorithm>
17 #include <iostream>
18 #include <iterator>
19 #include <util/string_constant.h>
20 
22 
23 extern char *yystatement_listtext;
24 
30 static irep_idt find_name(const exprt &root)
31 {
32  for(const exprt &op : root.operands())
33  {
34  if(op.get(ID_statement_list_type) == ID_statement_list_identifier)
35  return op.get(ID_value);
36  }
37  UNREACHABLE; // Root expression should always have a name
38 }
39 
41 {
42  const exprt::operandst &ops = tag_list.operands();
43  transform(
44  begin(ops),
45  end(ops),
46  std::back_inserter(parse_tree.tags),
47  static_cast<const symbol_exprt &(*)(const exprt &)>(to_symbol_expr));
48 }
49 
55 static std::string find_version(const exprt &root)
56 {
57  for(const exprt &op : root.operands())
58  {
59  if(op.get(ID_statement_list_type) == ID_statement_list_version)
60  {
61  const string_constantt &constant{to_string_constant(op)};
62  return id2string(constant.get_value());
63  }
64  }
65  UNREACHABLE; // Root expression should always have a version
66 }
67 
73 static typet find_return_value(const exprt &root)
74 {
75  INVARIANT(
76  root.id() == ID_statement_list_function,
77  "Expression ID should be statement_list_function");
78 
79  for(const exprt &op : root.operands())
80  {
81  if(op.get(ID_statement_list_type) == ID_statement_list_return)
82  return op.type();
83  }
84 
85  UNREACHABLE; // Root expression of FC should always have a return value
86 }
87 
93 static exprt find_variable_list(const exprt &root)
94 {
95  for(const exprt &op : root.operands())
96  {
97  if(op.id() == ID_statement_list_var_decls)
98  return op;
99  }
100  UNREACHABLE; // Root expression should always have a variable list
101 }
102 
110  const exprt &var_list)
111 {
112  for(const exprt &entry : var_list.operands())
113  {
114  std::vector<symbol_exprt> symbols;
115  exprt default_value = nil_exprt();
116  for(const exprt &part : entry.operands())
117  {
118  const symbol_exprt *const symbol =
119  expr_try_dynamic_cast<symbol_exprt>(part);
120  if(symbol)
121  symbols.push_back(*symbol);
122  else
123  default_value = part;
124  }
125 
126  for(const symbol_exprt &symbol : symbols)
127  {
129  if(default_value.is_not_nil())
130  declaration.default_value = default_value;
131  parse_tree_list.push_back(declaration);
132  }
133  }
134 }
135 
140 static void fill_temp_vars(
142  const exprt &temp_vars)
143 {
144  for(const exprt &entry : temp_vars.operands())
145  {
146  for(const exprt &part : entry.operands())
147  {
148  const symbol_exprt *const symbol =
149  expr_try_dynamic_cast<symbol_exprt>(part);
150  if(symbol)
151  {
153  parse_tree_list.push_back(declaration);
154  }
155  else
156  UNREACHABLE; // Temp variables should not have an initial value.
157  }
158  }
159 }
160 
164 static void find_variables(
166  const exprt &var_decls)
167 {
168  for(const exprt &decls : var_decls.operands())
169  {
170  if(decls.id() == ID_statement_list_var_input)
171  fill_vars_with_default_values(function.var_input, decls);
172  else if(decls.id() == ID_statement_list_var_inout)
173  fill_vars_with_default_values(function.var_inout, decls);
174  else if(decls.id() == ID_statement_list_var_output)
175  fill_vars_with_default_values(function.var_output, decls);
176  else if(decls.id() == ID_statement_list_var_constant)
177  fill_vars_with_default_values(function.var_constant, decls);
178  else if(decls.id() == ID_statement_list_var_temp)
179  fill_temp_vars(function.var_temp, decls);
180  }
181 }
182 
186 static void find_variables(
188  const exprt &var_decls)
189 {
190  for(const exprt &decls : var_decls.operands())
191  {
192  if(ID_statement_list_var_input == decls.id())
194  else if(ID_statement_list_var_inout == decls.id())
196  else if(ID_statement_list_var_output == decls.id())
198  else if(ID_statement_list_var_static == decls.id())
200  else if(ID_statement_list_var_constant == decls.id())
202  else if(ID_statement_list_var_temp == decls.id())
203  fill_temp_vars(block.var_temp, decls);
204  }
205 }
206 
212 static exprt find_network_list(const exprt &root)
213 {
214  for(const exprt &op : root.operands())
215  {
216  if(op.id() == ID_statement_list_networks)
217  return op;
218  }
219  UNREACHABLE; // Root expression should always have a network list
220 }
221 
226 static std::string find_network_title(const exprt &network)
227 {
228  for(const exprt &network_element : network.operands())
229  {
230  if(network_element.get(ID_statement_list_type) == ID_statement_list_title)
231  return network_element.get(ID_value).c_str();
232  }
233  UNREACHABLE; // Network expression should always have a title
234 }
235 
241 static exprt find_network_instructions(const exprt &network)
242 {
243  for(const exprt &network_element : network.operands())
244  {
245  if(network_element.id() == ID_statement_list_instructions)
246  return network_element;
247  }
248  UNREACHABLE; // Network expression should always have an instruction list
249 }
250 
254 static void find_instructions(
256  const exprt &instructions)
257 {
258  for(const exprt &instruction_expr : instructions.operands())
259  {
261 
262  codet code_token(to_multi_ary_expr(instruction_expr).op0().id());
263  string_constantt label{ID_nil};
264  for(auto op_it = std::next(instruction_expr.operands().begin());
265  op_it != end(instruction_expr.operands());
266  ++op_it)
267  {
268  if(op_it->get(ID_statement_list_type) == ID_label)
269  label = to_string_constant(*op_it);
270  else if(op_it->is_not_nil())
271  code_token.add_to_operands(*op_it);
272  }
273 
274  if(label.get_value() == ID_nil)
275  instruction.add_token(code_token);
276  else
277  instruction.add_token(code_labelt{label.get_value(), code_token});
278 
279  network.add_instruction(instruction);
280  }
281 }
282 
287 static void find_networks(
289  const exprt &network_list)
290 {
291  for(const exprt &expr_network : network_list.operands())
292  {
293  const std::string title(find_network_title(expr_network));
295  const exprt instructions = find_network_instructions(expr_network);
296  find_instructions(network, instructions);
297  module.add_network(network);
298  }
299 }
300 
302 {
303  INVARIANT(
304  block.id() == ID_statement_list_function_block,
305  "Root expression ID should be ID_statement_list_function_block");
306 
307  // Generate new function block.
309  find_version(block)};
310 
311  // Fill the block with networks and variables.
313  find_networks(fb, find_network_list(block));
314 
316 }
317 
319 {
320  INVARIANT(
321  function.id() == ID_statement_list_function,
322  "Expression ID should be statement_list_function");
323 
324  // Generate new function.
326  find_name(function), find_version(function), find_return_value(function)};
327 
328  // Fill the function with networks and variables.
329  find_variables(fn, find_variable_list(function));
330  find_networks(fn, find_network_list(function));
331 
333 }
334 
336 {
337  return yystatement_listparse() != 0;
338 }
339 
340 int yystatement_listerror(const std::string &error)
341 {
343  return 0;
344 }
345 
347 {
348  parsert::clear();
349  parse_tree.clear();
350 }
351 
352 void statement_list_parsert::print_tree(std::ostream &out) const
353 {
355 }
356 
358 {
359  parse_tree.swap(other);
360 }
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
statement_list_parse_treet::var_declarationt::default_value
optionalt< exprt > default_value
Optional default value of the variable.
Definition: statement_list_parse_tree.h:33
statement_list_parser.h
statement_list_parsert::add_function_block
void add_function_block(const exprt &block)
Adds a function block to the parse tree by converting the block expression tree.
Definition: statement_list_parser.cpp:301
statement_list_parsert::print_tree
void print_tree(std::ostream &out) const
Prints the parse tree of this instance to the given output stream.
Definition: statement_list_parser.cpp:352
statement_list_parse_treet::var_declarationst
std::list< var_declarationt > var_declarationst
Definition: statement_list_parse_tree.h:39
statement_list_parser
statement_list_parsert statement_list_parser
Instance of the parser, used by other modules.
Definition: statement_list_parser.cpp:21
typet
The type of an expression, extends irept.
Definition: type.h:28
transform
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
Definition: abstract_value_object.cpp:159
statement_list_parse_treet::tia_modulet::var_temp
var_declarationst var_temp
Temp variable declarations.
Definition: statement_list_parse_tree.h:93
statement_list_parsert::parse
bool parse() override
Starts the parsing process and saves the result inside of this instance's parse tree.
Definition: statement_list_parser.cpp:335
find_version
static std::string find_version(const exprt &root)
Searches for the version of the TIA module inside of its root expression.
Definition: statement_list_parser.cpp:55
find_network_title
static std::string find_network_title(const exprt &network)
Searches for the title of a network inside of its root expression.
Definition: statement_list_parser.cpp:226
to_string_constant
const string_constantt & to_string_constant(const exprt &expr)
Definition: string_constant.h:40
statement_list_parse_treet::var_declarationt
Struct for a single variable declaration in Statement List.
Definition: statement_list_parse_tree.h:28
statement_list_parse_treet::tia_modulet::var_input
var_declarationst var_input
Input variable declarations.
Definition: statement_list_parse_tree.h:87
parsert::clear
virtual void clear()
Definition: parser.h:32
yystatement_listtext
char * yystatement_listtext
string_constant.h
exprt
Base class for all expressions.
Definition: expr.h:55
statement_list_parse_treet::instructiont
Represents a regular Statement List instruction which consists out of one or more codet tokens.
Definition: statement_list_parse_tree.h:43
statement_list_parse_treet::tia_modulet
Base element of all modules in the Totally Integrated Automation (TIA) portal by Siemens.
Definition: statement_list_parse_tree.h:79
fill_vars_with_default_values
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.
Definition: statement_list_parser.cpp:108
find_instructions
static void find_instructions(statement_list_parse_treet::networkt &network, const exprt &instructions)
Adds all valid instructions to the given network.
Definition: statement_list_parser.cpp:254
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
string_constantt
Definition: string_constant.h:14
statement_list_parse_treet::function_blockt
Structure for a simple function block in Statement List.
Definition: statement_list_parse_tree.h:146
output_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.
Definition: statement_list_parse_tree_io.cpp:56
statement_list_parse_treet::tia_modulet::add_network
void add_network(networkt &network)
Adds a network to the function.
Definition: statement_list_parse_tree.cpp:50
statement_list_parsert::add_tag_list
void add_tag_list(const exprt &tag_list)
Adds a tag list to the parse tree by converting the tag_list expression tree.
Definition: statement_list_parser.cpp:40
statement_list_parsert::swap_tree
void swap_tree(statement_list_parse_treet &other)
Swaps the contents of the parse tree of this instance with other.
Definition: statement_list_parser.cpp:357
statement_list_parse_tree_io.h
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
statement_list_parse_treet::tia_modulet::var_constant
var_declarationst var_constant
Constant variable declarations.
Definition: statement_list_parse_tree.h:95
find_network_instructions
static exprt find_network_instructions(const exprt &network)
Searches for the instruction list of a network inside of its root expression.
Definition: statement_list_parser.cpp:241
statement_list_parsert::parse_tree
statement_list_parse_treet parse_tree
Tree that is being filled by the parsing process.
Definition: statement_list_parser.h:71
statement_list_parse_treet::add_function
void add_function(functiont &function)
Adds a function to the parse tree.
Definition: statement_list_parse_tree.cpp:93
statement_list_parse_treet::swap
void swap(statement_list_parse_treet &other)
Swaps the contents of the parse tree with the parameter.
Definition: statement_list_parse_tree.cpp:105
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
code_labelt
codet representation of a label for branch targets.
Definition: std_code.h:958
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
statement_list_parse_tree.h
find_network_list
static exprt find_network_list(const exprt &root)
Searches for the network list of the TIA element inside of its root expression.
Definition: statement_list_parser.cpp:212
fill_temp_vars
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...
Definition: statement_list_parser.cpp:140
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
yystatement_listparse
int yystatement_listparse()
Defined in statement_list_y.tab.cpp.
parsert::parse_error
void parse_error(const std::string &message, const std::string &before)
Definition: parser.cpp:30
statement_list_parse_treet::function_blockt::var_static
var_declarationst var_static
FB-exclusive static variable declarations.
Definition: statement_list_parse_tree.h:149
statement_list_parsert::clear
void clear() override
Removes all functions and function blocks from the parse tree and clears the internal state of the pa...
Definition: statement_list_parser.cpp:346
statement_list_parse_treet
Intermediate representation of a parsed Statement List file before converting it into a goto program.
Definition: statement_list_parse_tree.h:20
statement_list_parse_treet::clear
void clear()
Removes all functions and function blocks from the parse tree.
Definition: statement_list_parse_tree.cpp:98
find_name
static irep_idt find_name(const exprt &root)
Searches for the name of the TIA module inside of its root expression.
Definition: statement_list_parser.cpp:30
statement_list_parse_treet::instructiont::add_token
void add_token(const codet &token)
Adds a codet element to the list of all tokens.
Definition: statement_list_parse_tree.cpp:120
statement_list_parse_treet::tags
std::vector< symbol_exprt > tags
List of tags that were included in the source.
Definition: statement_list_parse_tree.h:177
statement_list_parsert::add_function
void add_function(const exprt &function)
Adds a function to the parse tree by converting the function expression tree.
Definition: statement_list_parser.cpp:318
find_networks
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.
Definition: statement_list_parser.cpp:287
statement_list_parse_treet::networkt::add_instruction
void add_instruction(const instructiont &inst)
Adds an instruction to the network.
Definition: statement_list_parse_tree.cpp:68
exprt::add_to_operands
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:162
find_return_value
static typet find_return_value(const exprt &root)
Searches for the return type of a function inside of its root expression.
Definition: statement_list_parser.cpp:73
exprt::operands
operandst & operands()
Definition: expr.h:94
INVARIANT
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
statement_list_parse_treet::tia_modulet::var_inout
var_declarationst var_inout
Inout variable declarations.
Definition: statement_list_parse_tree.h:89
yystatement_listerror
int yystatement_listerror(const std::string &error)
Forwards any errors that are encountered during the parse process.
Definition: statement_list_parser.cpp:340
statement_list_parse_treet::functiont
Structure for a simple function in Statement List.
Definition: statement_list_parse_tree.h:127
statement_list_parse_treet::tia_modulet::var_output
var_declarationst var_output
Output variable declarations.
Definition: statement_list_parse_tree.h:91
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
find_variable_list
static exprt find_variable_list(const exprt &root)
Searches for the variable list of the TIA module inside of its root expression.
Definition: statement_list_parser.cpp:93
statement_list_parsert
Responsible for starting the parse process and to translate the result into a statement_list_parse_tr...
Definition: statement_list_parser.h:34
statement_list_parse_treet::networkt
Representation of a network in Siemens TIA.
Definition: statement_list_parse_tree.h:58
validation_modet::INVARIANT
@ INVARIANT
statement_list_parse_treet::add_function_block
void add_function_block(function_blockt &block)
Adds a function block to the parse tree.
Definition: statement_list_parse_tree.cpp:88
find_variables
static void find_variables(statement_list_parse_treet::functiont &function, const exprt &var_decls)
Adds all valid variable declarations to the given function.
Definition: statement_list_parser.cpp:164
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28