Newer
Older

Graziano Scalamera
committed
/*
* formula_grammar.h
*
* $Author: graziano $
*
* $Revision: 1.5 $
*
* $Log: formula_grammar.h,v $
*
*
* copyleft: Sincrotrone Trieste S.C.p.A. di interesse nazionale
* Strada Statale 14 - km 163,5 in AREA Science Park
* 34012 Basovizza, Trieste ITALY
*/
#ifndef FORMULA_GRAMMAR_H_
#define FORMULA_GRAMMAR_H_
#include <boost/version.hpp>

Graziano Scalamera
committed
//#define BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING //test trying to have node also if formula of type (ev/ev/ev/ev) 27/02/2008
#if BOOST_VERSION < 103600
#ifndef BOOST_SPIRIT_THREADSAFE
#define BOOST_SPIRIT_THREADSAFE
#endif
#endif
#if BOOST_VERSION < 103600

Graziano Scalamera
committed
#include <boost/spirit/core.hpp>
#include <boost/spirit/tree/ast.hpp>
//for ast parse trees (in tree_formula)
#include <boost/spirit/symbols/symbols.hpp> //for symbol table

Graziano Scalamera
committed
using namespace boost::spirit;
#else
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_ast.hpp>
//for ast parse trees (in tree_formula)
#include <boost/spirit/include/classic_symbols.hpp> //for symbol table
using namespace boost::spirit::classic;

Graziano Scalamera
committed
#endif

Graziano Scalamera
committed
using namespace std;
/*typedef char const* iterator_t;
typedef node_val_data_factory<unsigned int> factory_t;
typedef tree_match<iterator_t, factory_t> parse_tree_match_t;
typedef tree_parse_info<iterator_t, factory_t> tree_parse_t;
typedef parse_tree_match_t::tree_iterator iter_t;*/
typedef node_val_data<iterator_t, unsigned int> node_t;
typedef tree_node<node_t> tree_node_t;
/*static unsigned int stat_tmp;
static void Save_Stat (unsigned int val)
{
stat_tmp = val;
}
static void Assign_Stat (tree_node_t & node, const iterator_t & begin, const iterator_t & end)
{
node.value.value(stat_tmp);
}*/
static unsigned int stat_tmp;

Graziano Scalamera
committed
struct Save_Stat
{
void operator () (unsigned int val) const
{
stat_tmp = val;
}
};
struct Assign_Stat
{
void operator () (tree_node_t & node, const iterator_t & begin, const iterator_t & end) const
{
node.value.value(stat_tmp);
}
};
//TODO: duplicated from alarm.h
enum _AlarmStateEnum {
_NORM,
_UNACK,
_ACKED,
_RTNUN,
_SHLVD,
_DSUPR,
_OOSRV,

Graziano Scalamera
committed
_ERROR
static vector<string> quality_labels = {"ATTR_VALID","ATTR_INVALID","ATTR_ALARM","ATTR_CHANGING","ATTR_WARNING"};

Graziano Scalamera
committed
struct formula_grammar : public grammar<formula_grammar>
{
/*formula_t &m_formula;
symbols<unsigned int> sym_grp;
formula_grammar(formula_t &f) \
: m_formula(f)
{
}*/

Graziano Scalamera
committed
static const int val_rID = 1;
static const int val_hID = 2;
static const int val_stID = 3;
static const int event_ID = 4;
static const int nameID = 5;
static const int indexID = 6;
static const int funcID = 7;
static const int logical_exprID = 8;
static const int bitwise_exprID = 9;
static const int equality_exprID = 10;
static const int compare_exprID = 11;
static const int add_exprID = 12;
static const int mult_exprID = 13;
static const int expr_atomID = 14;
static const int shift_exprID = 15;
static const int unary_exprID = 16;
static const int val_stringID = 17; //TODO: OK ?
static const int func_dualID = 18;
static const int logical_expr_parenID = 19;
static const int cond_exprID = 20;
static const int exprID = 21;
static const int nonempty_exprID = 22;
static const int val_qualityID = 23;
static const int val_alarm_enum_stID = 24;
static const int propertyID = 25;

Graziano Scalamera
committed
symbols<unsigned int> tango_states;
symbols<unsigned int> attr_quality;

Graziano Scalamera
committed
symbols<unsigned int> alarm_enum_states;

Graziano Scalamera
committed
formula_grammar()
{
tango_states.add("ON", (unsigned int)Tango::ON);
tango_states.add("OFF", (unsigned int)Tango::OFF);
tango_states.add("CLOSE", (unsigned int)Tango::CLOSE);
tango_states.add("OPEN", (unsigned int)Tango::OPEN);
tango_states.add("INSERT", (unsigned int)Tango::INSERT);
tango_states.add("EXTRACT", (unsigned int)Tango::EXTRACT);
tango_states.add("MOVING", (unsigned int)Tango::MOVING);
tango_states.add("STANDBY", (unsigned int)Tango::STANDBY);
tango_states.add("FAULT", (unsigned int)Tango::FAULT);
tango_states.add("INIT", (unsigned int)Tango::INIT);
tango_states.add("RUNNING", (unsigned int)Tango::RUNNING);
tango_states.add("ALARM", (unsigned int)Tango::ALARM);
tango_states.add("DISABLE", (unsigned int)Tango::DISABLE);
tango_states.add("UNKNOWN", (unsigned int)Tango::UNKNOWN);
attr_quality.add("ATTR_VALID", (unsigned int)Tango::ATTR_VALID);
attr_quality.add("ATTR_INVALID", (unsigned int)Tango::ATTR_INVALID);
attr_quality.add("ATTR_ALARM", (unsigned int)Tango::ATTR_ALARM);
attr_quality.add("ATTR_CHANGING", (unsigned int)Tango::ATTR_CHANGING);
attr_quality.add("ATTR_WARNING", (unsigned int)Tango::ATTR_WARNING);
alarm_enum_states.add("NORM", (unsigned int)_NORM);
alarm_enum_states.add("UNACK", (unsigned int)_UNACK);
alarm_enum_states.add("ACKED", (unsigned int)_ACKED);
alarm_enum_states.add("RTNUN", (unsigned int)_RTNUN);
alarm_enum_states.add("SHLVD", (unsigned int)_SHLVD);
alarm_enum_states.add("DSUPR", (unsigned int)_DSUPR);
alarm_enum_states.add("OOSRV", (unsigned int)_OOSRV);

Graziano Scalamera
committed
alarm_enum_states.add("ERROR", (unsigned int)_ERROR);

Graziano Scalamera
committed
}
template <typename ScannerT>
struct definition
{
/* typedef
scanner<
typename ScannerT::iterator_t,
scanner_policies<
typename ScannerT::iteration_policy_t,
ast_match_policy<
typename ScannerT::match_policy_t::iterator_t,
typename ScannerT::match_policy_t::factory_t
>,
typename ScannerT::action_policy_t
>
> ast_scanner;*/
//typedef scanner_list< ScannerT, phrase_scanner_t > scanners; //try using multiple scanners
definition(formula_grammar const& self)
{
symbol
= (alnum_p | '.' | '_' | '-' | '+') //any alpha numeric char plus '.', '_', '-'

Graziano Scalamera
committed
;
= (alnum_p | '_' | '.') //any alpha numeric char plus '_', '.' for attribute names

Graziano Scalamera
committed
//------------------------------ALARM NAME--------------------------------------
name
#if BOOST_VERSION < 103600
= token_node_d[
#else
= reduced_node_d[
#endif
lexeme_d[ //needed to ignore "space_p" (skip white spaces) evaluating name
!("tango://" >> (+symbol) >> ':' >> uint_p >> "/") //eventually match FQDN
>> (+symbol) >> '/' >> (+symbol)
>> '/' >> (+symbol) >> '/' >> (+symbol_attr)

Graziano Scalamera
committed
]
]
// = repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol)
;
index
= inner_node_d[ch_p('[') >> uint_p >> ch_p(']')]
;
property
= str_p(".quality")
| str_p(".alarm")
| str_p(".normal")
;

Graziano Scalamera
committed
//------------------------------FORMULA--------------------------------------
val_r
#if BOOST_VERSION < 103600
= leaf_node_d[real_p]
#else
= reduced_node_d[real_p]
#endif
;
val_h
#if BOOST_VERSION < 103600
= token_node_d[(str_p("0x") >> hex_p)] //token_node_d here to create only one node with all chars
#else
= reduced_node_d[(str_p("0x") >> hex_p)] //token_node_d here to create only one node with all chars
#endif
;
val_st
=
//access_node_d[self.tango_states[&Save_Stat]][&Assign_Stat] //save Tango::state value in node
access_node_d[self.tango_states[Save_Stat()]][Assign_Stat()] //save Tango::state value in node
;
val_quality
=
//access_node_d[self.attr_quality[&Save_Stat]][&Assign_Stat] //save Tango::state value in node
access_node_d[self.attr_quality[Save_Stat()]][Assign_Stat()] //save Tango::state value in node
;
val_alarm_enum_st
=
//access_node_d[self.alarm_enum_states[&Save_Stat]][&Assign_Stat] //save Tango::state value in node
access_node_d[self.alarm_enum_states[Save_Stat()]][Assign_Stat()] //save Tango::state value in node
;
val_string
#if BOOST_VERSION < 103600
= token_node_d[
#else
= reduced_node_d[
#endif
lexeme_d[ //to conserve white spaces
ch_p('\'')
>> (+(anychar_p - '\'')) //one ore more char except '"'
>> '\''
]
]
// = repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol)

Graziano Scalamera
committed
;
event_
= name
| (property)

Graziano Scalamera
committed
;
/*top = ternary_if;
ternary_if
= logical_expr_paren
>> !(root_node_d[str_p("?")] >> logical_expr_paren >> discard_node_d[ch_p(':')] >> logical_expr_paren)
;*/
cond_expr = logical_expr >> *(root_node_d[ch_p('?')] >> cond_expr >> discard_node_d[ch_p(':')] >> cond_expr);
/*top = logical_expr
;*/

Graziano Scalamera
committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
logical_expr
= bitwise_expr
>> *( (root_node_d[str_p("&&")] >> bitwise_expr)
| (root_node_d[str_p("||")] >> bitwise_expr)
)
;
bitwise_expr
= equality_expr
>> *( (root_node_d[ch_p('&')] >> equality_expr)
| (root_node_d[ch_p('|')] >> equality_expr)
| (root_node_d[ch_p('^')] >> equality_expr)
)
;
equality_expr
= compare_expr
>> *( (root_node_d[str_p("==")] >> compare_expr)
| (root_node_d[str_p("!=")] >> compare_expr)
)
;
compare_expr
= shift_expr
>> *( (root_node_d[str_p("<=")] >> add_expr)
| (root_node_d[str_p(">=")] >> add_expr)
| (root_node_d[ch_p('<')] >> add_expr)
| (root_node_d[ch_p('>')] >> add_expr)
)
;
shift_expr
= add_expr
>> *( (root_node_d[str_p("<<")] >> add_expr)
| (root_node_d[str_p(">>")] >> add_expr)
)
;
add_expr
= mult_expr
>> *( (root_node_d[ch_p('+')] >> mult_expr)
| (root_node_d[ch_p('-')] >> mult_expr)
)
;
mult_expr
= unary_expr
>> *( (root_node_d[ch_p('*')] >> unary_expr)
| (root_node_d[ch_p('/')] >> unary_expr)

Graziano Scalamera
committed
)
;

Graziano Scalamera
committed
unary_expr
= ( expr_atom
| function
| function_dual
| (root_node_d[ch_p('+')] >> expr_atom)

Graziano Scalamera
committed
| (root_node_d[ch_p('-')] >> expr_atom)
| (root_node_d[ch_p('!')] >> expr_atom)
// | (root_node_d[ch_p('~')] >> expr_atom) //TODO
)
;
function
= ( root_node_d[str_p("abs")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?
| root_node_d[str_p("cos")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?
| root_node_d[str_p("sin")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?
| root_node_d[str_p("quality")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?
| root_node_d[str_p("AND")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?
| root_node_d[str_p("OR")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(')')]) //TODO: ? not expr_atom ?

Graziano Scalamera
committed
)
;
function_dual
= ( (root_node_d[str_p("max")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')]))
//| (root_node_d[str_p("max")] >> (inner_node_d[ch_p('(') >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> discard_node_d[ch_p(',')] >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> ')']))
| (root_node_d[str_p("min")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')]))
//| (root_node_d[str_p("min")] >> (inner_node_d[ch_p('(') >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> discard_node_d[ch_p(',')] >> discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')] >> ')']))
| (root_node_d[str_p("pow")] >> (discard_node_d[ch_p('(')] >> cond_expr >> discard_node_d[ch_p(',')] >> cond_expr >> discard_node_d[ch_p(')')]))
)
//= *( (root_node_d[str_p("max")] >> (inner_node_d[ch_p('(') >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> ')']))
// | (root_node_d[str_p("min")] >> (inner_node_d[ch_p('(') >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> ')']))
//| (root_node_d[str_p("min")] >> (discard_node_d[ch_p('(')] >> logical_expr_paren >> discard_node_d[ch_p(',')] >> logical_expr_paren >> discard_node_d[ch_p(',')]))
//| (root_node_d[str_p("min")] >> (ch_p('(') >> expr_atom >> ch_p(',') >> expr_atom >> ch_p(',')))
//)
;
non_empty_expression = cond_expr;
top = non_empty_expression | epsilon_p;
// top = non_empty_expression;

Graziano Scalamera
committed
expr_atom
= //val_h | val_r

Graziano Scalamera
committed
event_
| val_h | val_r | val_st | val_quality | val_alarm_enum_st | val_string
//| (inner_node_d[ch_p('(') >> non_empty_expression >> ')'])
| (discard_node_d[ch_p('(')] >> non_empty_expression >> discard_node_d[ch_p(')')])
;
= (discard_node_d[ch_p('(')] >> logical_expr >> discard_node_d[ch_p(')')])
| logical_expr

Graziano Scalamera
committed
}
rule<ScannerT> top;
//rule<ScannerT> symbol;
rule<typename lexeme_scanner<ScannerT>::type> symbol; //needed to use lexeme_d in rule name
rule<typename lexeme_scanner<ScannerT>::type> symbol_attr; //needed to use lexeme_d in rule name

Graziano Scalamera
committed
rule<ScannerT, parser_context<>, parser_tag<val_rID> > val_r;
rule<ScannerT, parser_context<>, parser_tag<val_hID> > val_h;
rule<ScannerT, parser_context<>, parser_tag<val_stID> > val_st;
rule<ScannerT, parser_context<>, parser_tag<event_ID> > event_;
rule<ScannerT, parser_context<>, parser_tag<logical_exprID> > logical_expr;
rule<ScannerT, parser_context<>, parser_tag<bitwise_exprID> > bitwise_expr;
rule<ScannerT, parser_context<>, parser_tag<shift_exprID> > shift_expr;
rule<ScannerT, parser_context<>, parser_tag<equality_exprID> > equality_expr;
rule<ScannerT, parser_context<>, parser_tag<compare_exprID> > compare_expr;
rule<ScannerT, parser_context<>, parser_tag<add_exprID> > add_expr;
rule<ScannerT, parser_context<>, parser_tag<mult_exprID> > mult_expr;
rule<ScannerT, parser_context<>, parser_tag<unary_exprID> > unary_expr;
rule<ScannerT, parser_context<>, parser_tag<expr_atomID> > expr_atom;
rule<ScannerT, parser_context<>, parser_tag<funcID> > function;
rule<ScannerT, parser_context<>, parser_tag<nameID> > name;
rule<ScannerT, parser_context<>, parser_tag<indexID> > index;
rule<ScannerT, parser_context<>, parser_tag<val_stringID> > val_string;
rule<ScannerT, parser_context<>, parser_tag<func_dualID> > function_dual;
rule<ScannerT, parser_context<>, parser_tag<logical_expr_parenID> > logical_expr_paren;
rule<ScannerT, parser_context<>, parser_tag<cond_exprID> > cond_expr;
rule<ScannerT, parser_context<>, parser_tag<nonempty_exprID> > non_empty_expression;
rule<ScannerT, parser_context<>, parser_tag<exprID> > expression;
rule<ScannerT, parser_context<>, parser_tag<val_qualityID> > val_quality;
rule<ScannerT, parser_context<>, parser_tag<val_alarm_enum_stID> > val_alarm_enum_st;
rule<ScannerT, parser_context<>, parser_tag<propertyID> > property;

Graziano Scalamera
committed
rule<ScannerT> const&
start() const { return top; }
};
};
#endif /*FORMULA_GRAMMAR_H_*/