Vcsn  2.5.dev
Be Rational
driver.cc
Go to the documentation of this file.
1 #include <sstream>
2 
3 #include <boost/algorithm/string/predicate.hpp> // boost::algorithm::contains
4 
5 #include <lib/vcsn/rat/caret.hh>
6 #include <lib/vcsn/rat/driver.hh>
7 #include <lib/vcsn/rat/parse.hh>
8 #include <lib/vcsn/rat/scan.hh>
9 #include <vcsn/dyn/algos.hh> // make_context
10 #include <vcsn/dyn/value.hh>
11 #include <vcsn/misc/stream.hh> // fail_reading
12 
13 namespace vcsn
14 {
15  namespace rat
16  {
17 
19  : scanner_(new yyFlexLexer)
20  , ids_(ids)
21  {
22  context(ctx);
23  }
24 
26  {}
27 
29  {
30  return tape_ctx_[tapes_.back()];
31  }
32 
34  {
35  ctx_ = ctx;
36  tape_ctx_.clear();
37  auto n = dyn::num_tapes(ctx_);
38  if (n)
39  for (size_t t = 0; t < n; ++t)
40  tape_ctx_.emplace_back(dyn::project(ctx_, t));
41  else
42  tape_ctx_.emplace_back(ctx_);
43  }
44 
45  void driver::context(const std::string& ctx)
46  {
48  }
49 
51  {
52  return ids_;
53  }
54 
56  {
57  tapes_.push_back(tapes_.back());
58  }
59 
61  {
62  tapes_.pop_back();
63  }
64 
65  void driver::tape_inc(const location& l)
66  {
67  if (tapes_.back() + 1 < tape_ctx_.size())
68  ++tapes_.back();
69  else
70  throw parser::syntax_error(l, "too many tapes");
71  }
72 
73  void driver::error(const location& l, const std::string& m)
74  {
75  std::ostringstream er;
76  er << l << ": " << m;
77  detail::print_caret(scanner_->yyinput_stream(), er, l);
78  if (!!getenv("YYDEBUG"))
79  std::cerr << "ERROR: " << er.str() << std::endl;
80  errors += (errors.empty() ? "" : "\n") + er.str();
81  }
82 
83  void driver::invalid(const location& l, const std::string& s)
84  {
85  throw parser::syntax_error(l, "invalid input: " + s);
86  }
87 
90  static int
92  {
93  int res = 0;
94  if (const char* cp = getenv("YYDEBUG"))
95  {
96  res = 1;
97  std::istringstream s{cp};
98  s >> res;
99  }
100  return res;
101  }
102 
103  auto
104  driver::parse(std::istream& is, const location& l)
105  -> dyn::expression
106  {
107  scanner_->scan_open_(is);
108  location_ = l;
109  // Parser.
110  parser p(*this);
111  // If the number of nested parser invocations is less than
112  // $YYDEBUG, be verbose. Recursive parsings are used for
113  // weights; for instance "<<a>b>c" uses three (nested) parsers.
114  static int debug_level = debug_level_();
115  static int nesting = 0;
116  p.set_debug_level(debug_level && nesting < debug_level);
117  ++nesting;
118  if (p.parse())
119  result_ = nullptr;
120  scanner_->scan_close_();
121  --nesting;
122  if (!errors.empty())
123  raise(errors);
124  return std::move(result_);
125  }
126 
127  dyn::label
128  driver::make_label(const location& loc, const std::string& s,
129  const dyn::context& ctx)
130  {
131  try
132  {
133  std::istringstream is{s};
134  auto res = dyn::read_label(ctx, is, "text");
135  require(is.peek() == -1,
136  "unexpected trailing characters in: ", s, ": ", is);
137  return res;
138  }
139  catch (const std::exception& e)
140  {
141  throw parser::syntax_error(loc, e.what());
142  }
143  }
144 
146  driver::make_atom(const location& loc, const std::string& s)
147  {
148  // If there are commas in the label, then have it read as a full
149  // label, not a one-tape label.
150  //
151  // FIXME: Remove once the tuple approach works perfectly. And
152  // simplify make_label accordingly (no dyn::context argument
153  // needed).
154  if (boost::algorithm::contains(s, ","))
155  return dyn::to_expression(ctx_, ids_,
156  make_label(loc, s, ctx_));
157  else
158  return dyn::to_expression(context(), ids_,
159  make_label(loc, s, context()));
160  }
161 
164  const class_t& c, bool accept = true)
165  {
166  try
167  {
168  // If there are commas in the labels, then have it read as a full
169  // label, not a one-tape label.
170  //
171  // FIXME: Remove once the tuple approach works perfectly.
172  if (!c.empty()
173  && boost::algorithm::contains(detail::front(c).first, ","))
174  return dyn::to_expression(ctx_, ids_, c, accept);
175  else
176  return dyn::to_expression(context(), ids_, c, accept);
177  }
178  catch (const std::exception& e)
179  {
180  throw parser::syntax_error(loc, e.what());
181  }
182  }
183 
185  driver::make_weight(const location& loc, const std::string& s)
186  {
187  try
188  {
189  std::istringstream is{s};
190  auto res = dyn::read_weight(ctx_, is);
191  require(is.peek() == -1,
192  "unexpected trailing characters in: ", s, ": ", is);
193  return res;
194  }
195  catch (const std::exception& e)
196  {
197  throw parser::syntax_error(loc, e.what());
198  }
199  }
200  }
201 }
Abstract a location.
Definition: location.hh:47
dyn::weight make_weight(const location &loc, const std::string &s)
From a string, generate a weight.
Definition: driver.cc:185
rat::identities ids_
The identities to apply.
Definition: driver.hh:81
std::size_t num_tapes(const context &ctx)
The number of input tapes.
Definition: num-tapes.hh:35
void tape_inc(const location &l)
Increment the top most tape.
Definition: driver.cc:65
rat::identities identities() const
Get the identities.
Definition: driver.cc:50
dyn::expression make_expression(const location &loc, const class_t &c, bool accept)
From a label class, generate an expression.
Definition: driver.cc:163
static int debug_level_()
The nesting limit for parser traces, as specified per $YYDEBUG.
Definition: driver.cc:91
A dyn Value/ValueSet.
Definition: fwd.hh:29
static int debug_level()
Debug level set in the user&#39;s environment.
Definition: debug-level.hh:11
value_impl< detail::expression_tag > expression
Definition: fwd.hh:31
std::vector< unsigned > tapes_
The stack of tape numbers.
Definition: driver.hh:90
std::unique_ptr< yyFlexLexer > scanner_
The scanner.
Definition: driver.hh:57
void set_debug_level(debug_level_type l)
Set the current debugging level.
Definition: parse.cc:567
dyn::context ctx_
The context used to read the expression.
Definition: driver.hh:79
virtual int parse()
Parse.
Definition: parse.cc:596
void error(const location &l, const std::string &m)
Report an error m at l.
Definition: driver.cc:73
void tape_pop()
Pop the tape stack.
Definition: driver.cc:60
expression to_expression(const automaton &aut, identities ids={}, const std::string &algo="auto")
An expression denoting the language of aut.
Define the vcsn::rat::parser class.
void print_caret(std::istream &is, std::ostream &os, const rat::location &loc)
Repeat a line with an error, underlining the error with carets.
Definition: caret.cc:40
return res
Definition: multiply.hh:399
std::vector< dyn::context > tape_ctx_
The context for each tape. If single-tape, [0] is ctx_.
Definition: driver.hh:92
A Bison parser.
Definition: parse.hh:299
dyn::expression parse(std::istream &is, const location &l=location{})
Parse this stream.
Definition: driver.cc:104
std::set< std::pair< std::string, std::string > > class_t
A set of label ranges.
Definition: fwd.hh:12
dyn::label make_label(const location &loc, const std::string &s, const dyn::context &ctx)
From a string, generate a label.
Definition: driver.cc:128
dyn::context context() const
Get the current context.
Definition: driver.cc:28
label read_label(const context &ctx, std::istream &is, const std::string &format="default")
Read a label from a stream.
Definition: read.cc:122
automaton project(const automaton &aut, unsigned tape)
Keep a single tape from a multiple-tape automaton.
Definition: others.cc:112
Template-less root for contexts.
Definition: context.hh:16
std::string errors
The error messages.
Definition: driver.hh:55
Container::value_type front(const Container &container)
The first member of this Container.
Definition: algorithm.hh:72
location location_
The inital location.
Definition: driver.hh:77
context make_context(const std::string &name)
Build a context from its name.
Definition: others.cc:96
void require(Bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
void tape_push()
Push a new tape number on the stack.
Definition: driver.cc:55
Definition: a-star.hh:8
static identities ids(const driver &d)
Get the identities of the driver.
Definition: parse.cc:89
Syntax errors thrown from user actions.
Definition: parse.hh:341
An expressionset can implement several different sets of identities on expressions.
Definition: identities.hh:20
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:82
dyn::expression result_
The parsed expression.
Definition: driver.hh:83
weight read_weight(const context &ctx, std::istream &is)
Read a weight from a stream.
Definition: read.hh:89
dyn::expression make_atom(const location &loc, const std::string &s)
From a string, generate an expression.
Definition: driver.cc:146
ATTRIBUTE_NORETURN void invalid(const location &l, const std::string &s)
The string s is invalid at l.
Definition: driver.cc:83
driver(const dyn::context &ctx, rat::identities ids)
Definition: driver.cc:18