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 }
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:504
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:37
statement_list_parse_treet::var_declarationt::default_value
optionalt< exprt > default_value
Optional default value of the variable.
Definition: statement_list_parse_tree.h:34
statement_list_parser.h
Statement List Language Parser.
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:292
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:343
statement_list_parse_treet::var_declarationst
std::list< var_declarationt > var_declarationst
Definition: statement_list_parse_tree.h:40
statement_list_parser
statement_list_parsert statement_list_parser
Instance of the parser, used by other modules.
Definition: statement_list_parser.cpp:23
typet
The type of an expression, extends irept.
Definition: type.h:29
statement_list_parse_treet::tia_modulet::var_temp
var_declarationst var_temp
Temp variable declarations.
Definition: statement_list_parse_tree.h:94
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:326
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:57
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:228
to_string_constant
const string_constantt & to_string_constant(const exprt &expr)
Definition: string_constant.h:31
statement_list_parse_treet::var_declarationt
Struct for a single variable declaration in Statement List.
Definition: statement_list_parse_tree.h:30
statement_list_parse_treet::tia_modulet::var_input
var_declarationst var_input
Input variable declarations.
Definition: statement_list_parse_tree.h:88
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:53
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:45
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:81
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:110
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:256
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:82
string_constantt
Definition: string_constant.h:16
statement_list_parse_treet::function_blockt
Structure for a simple function block in Statement List.
Definition: statement_list_parse_tree.h:148
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:54
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:42
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:348
statement_list_parse_tree_io.h
Statement List Language Parse Tree Output.
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:402
statement_list_parse_treet::tia_modulet::var_constant
var_declarationst var_constant
Constant variable declarations.
Definition: statement_list_parse_tree.h:96
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:243
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:44
nil_exprt
The NIL expression.
Definition: std_expr.h:3973
statement_list_parse_tree.h
Statement List Language Parse Tree.
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:214
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:142
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:177
irept::id
const irep_idt & id() const
Definition: irep.h:418
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:55
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:150
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:337
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:22
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:32
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:178
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:309
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:278
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:157
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:75
exprt::operands
operandst & operands()
Definition: expr.h:95
INVARIANT
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:424
statement_list_parse_treet::tia_modulet::var_inout
var_declarationst var_inout
Inout variable declarations.
Definition: statement_list_parse_tree.h:90
yystatement_listerror
int yystatement_listerror(const std::string &error)
Forwards any errors that are encountered during the parse process.
Definition: statement_list_parser.cpp:331
statement_list_parse_treet::functiont
Structure for a simple function in Statement List.
Definition: statement_list_parse_tree.h:129
statement_list_parse_treet::tia_modulet::var_output
var_declarationst var_output
Output variable declarations.
Definition: statement_list_parse_tree.h:92
codet::get_statement
const irep_idt & get_statement() const
Definition: std_code.h:71
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:866
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:95
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:35
statement_list_parse_treet::networkt
Representation of a network in Siemens TIA.
Definition: statement_list_parse_tree.h:60
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:166
statement_list_types.h
Statement List Type Helper.
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code.h:35