Lumiera  0.pre.03
»edit your freedom«
common/advice/binding.cpp
Go to the documentation of this file.
1 /*
2  Binding - pattern defining a specific attachment to the Advice system
3 
4  Copyright (C)
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
25 #include "lib/symbol.hpp"
26 #include "lib/util.hpp"
27 
28 #include <boost/functional/hash.hpp>
29 #include <boost/lexical_cast.hpp>
30 #include <regex>
31 
32 
33 using lib::Literal;
34 using util::isnil;
35 
36 using std::regex;
37 using std::smatch;
38 using std::sregex_iterator;
39 using std::regex_constants::match_continuous;
40 using boost::hash_combine;
41 using boost::lexical_cast;
42 
43 
44 namespace lumiera{
45 namespace advice {
46 
47  LUMIERA_ERROR_DEFINE (BINDING_PATTERN_SYNTAX, "Unable to parse the given binding pattern definition");
48 
49 
50 
51 
52 
54  namespace{ // Implementation details
55 
56  const string matchSym = "(\\w+(?:[\\.\\-]\\w+)*)";
57  const string matchArg = "\\(\\s*"+matchSym+"?\\s*\\)";
58  regex findPredicate ("\\s*"+matchSym+"("+matchArg+")?\\s*,?");
59 
64  inline uint
65  detectArity (smatch const& match)
66  {
67  if (!match[2].matched) return 0; // no parenthesis at all
68  if (!match[3].matched) return 0; // empty parenthesis
69 
70  // later we could analyse the argument in detail here...
71  return 1; // but now we just accept a single constant symbol
72  }
73  }
74 
75 
76  void
78  {
79  string def(lit);
80  string::const_iterator end_of_last_match = def.begin();
81 
82  sregex_iterator end;
83  sregex_iterator pos (def.begin(),def.end(), findPredicate,
84  match_continuous); // continuous: don't allow garbage *not* matched by the RegExp
85  while (pos != end)
86  {
87  smatch match = *pos;
88  atoms_.insert (Atom (match[1], detectArity(match), match[3]));
89  end_of_last_match = match[0].second;
90  ++pos;
91  }
92 
93  if ( end_of_last_match !=def.end()
94  && *end_of_last_match !='.'
95  ) // if the match did *not stop at the end of the pattern definition list
96  throw lumiera::error::Invalid ("Trailing garbage in binding pattern definition"
97  , LUMIERA_ERROR_BINDING_PATTERN_SYNTAX);
98  }
99 
100 
102  : atoms_()
103  { }
104 
106  {
107  if (!isnil(spec))
108  parse_and_append (spec);
109  }
110 
111 
112  void
114  {
115  REQUIRE (spec);
116  parse_and_append (spec);
117  }
118 
119 
120 
121  Binding::operator string() const
122  {
123  string repr("Binding[");
124  typedef NormalisedAtoms::const_iterator AIter;
125  AIter end = atoms_.end();
126  AIter pos = atoms_.begin();
127  for ( ; pos!=end ; ++pos)
128  repr += string(*pos)+", ";
129 
130  if (0 < atoms_.size())
131  repr.resize(repr.size()-2);
132 
133  repr += "]";
134  return repr;
135  }
136 
137 
138  Binding::Atom::operator string() const
139  {
140  return sym_+"/"+lexical_cast<string> (ari_)
141  +"("+arg_+")";
142  }
143 
144 
145  HashVal
146  Binding::calculateHash() const
147  {
148  HashVal hash=0;
149 
150  typedef NormalisedAtoms::const_iterator AIter;
151  AIter pos = atoms_.begin();
152  AIter end = atoms_.end();
153  for ( ; pos!=end ; ++pos)
154  {
155  hash_combine (hash, pos->sym());
156  hash_combine (hash, pos->arity());
157  hash_combine (hash, pos->arg());
158  }
159 
160  return hash;
161  }
162 
163 
172  bool
173  operator== (Binding const& b1, Binding const& b2)
174  {
175  if (b1.atoms_.size() != b2.atoms_.size())
176  return false;
177 
178  ASSERT (b1.atoms_.size() == b2.atoms_.size());
179 
180  typedef Binding::NormalisedAtoms::const_iterator Iter;
181  Iter end = b1.atoms_.end();
182  Iter p1 = b1.atoms_.begin();
183  Iter p2 = b2.atoms_.begin();
184 
185  for ( ; p1!=end; ++p1, ++p2 )
186  if (! p1->identical(*p2))
187  return false;
188 
189  return true;
190  }
191 
192 
193 
194 }} // namespace lumiera::advice
regex findPredicate("\*"+matchSym+"("+matchArg+")?\*,?")
sym(arg), groups: [symbol, parenthesis, argument symbol]
Conjunction of predicates to be matched against a collaboration partner for establishing an Advice co...
friend bool operator==(Binding const &, Binding const &)
bindings are considered equivalent if, after normalisation, their respective definitions are identica...
void parse_and_append(Literal def)
internal: parse into atoms, and insert them
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
single predicate as part of an advice binding pattern
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
A pattern to define and identify a specific attachment to the Advice system.
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
void addPredicate(Literal spec)
extend the definition of this binding by adding a predicate according to the given textual definition...
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
Lumiera public interface.
Definition: advice.cpp:104
uint detectArity(smatch const &match)
detect the arity of an predicate, as matched by findPredicate.
Binding()
create the empty binding, equivalent to true
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:71