Spicy
parser-builder.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <functional>
6 #include <map>
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include <hilti/compiler/context.h>
13 
14 #include <spicy/ast/aliases.h>
15 #include <spicy/ast/types/unit.h>
16 #include <spicy/compiler/detail/codegen/production.h>
17 
18 namespace hilti::type {
19 class Struct;
20 } // namespace hilti::type
21 namespace hilti::builder {
22 class Builder;
23 } // namespace hilti::builder
24 
25 namespace spicy::detail {
26 
27 class CodeGen;
28 
29 namespace codegen {
30 
31 struct ProductionVisitor;
32 
38 enum class LiteralMode {
40  Default,
41 
46  Try,
47 };
48 
49 namespace detail {
50 constexpr hilti::util::enum_::Value<LiteralMode> literal_modes[] = {{LiteralMode::Default, "default"},
51  {LiteralMode::Try, "try"}};
52 } // namespace detail
53 
54 constexpr auto to_string(LiteralMode cc) { return hilti::util::enum_::to_string(cc, detail::literal_modes); }
55 
56 namespace look_ahead {
57 
59 extern const hilti::Type Type;
60 
66 extern const hilti::Expression None;
67 
72 extern const hilti::Expression Eod;
73 
74 } // namespace look_ahead
75 
85 struct ParserState {
86  ParserState(const type::Unit& unit, const Grammar& grammar, Expression data, Expression cur);
87  ParserState(const ParserState& other) = default;
88  ParserState(ParserState&& other) = default;
89  ParserState& operator=(const ParserState& other) = default;
90  ParserState& operator=(ParserState&& other) = default;
91  ~ParserState() = default;
92 
99  void printDebug(const std::shared_ptr<hilti::builder::Builder>& b) const;
100 
102  std::reference_wrapper<const type::Unit> unit;
103 
106 
109 
111  Expression self;
112 
114  Expression data;
115 
117  Expression cur;
118 
120  std::optional<Expression> ncur;
121 
126  Expression trim;
127 
132  Expression lahead = look_ahead::None;
133 
138  Expression lahead_end;
139 
141  LiteralMode literal_mode = LiteralMode::Default;
142 
147  std::optional<Expression> captures;
148 };
149 
152 public:
153  ParserBuilder(CodeGen* cg) : _cg(cg) {}
154 
159  void pushState(ParserState p) { _states.push_back(std::move(p)); }
160 
165  void popState() { _states.pop_back(); }
166 
168  ParserState state() const { return _states.back(); }
169 
176  Expression parseMethodExternalOverload1(const type::Unit& t);
177 
184  Expression parseMethodExternalOverload2(const type::Unit& t);
185 
193  Expression parseMethodExternalOverload3(const type::Unit& t);
194 
200  Expression contextNewFunction(const type::Unit& t);
201 
206  hilti::type::Struct addParserMethods(hilti::type::Struct s, const type::Unit& t, bool declare_only);
207 
209  auto builder() { return _builders.back(); }
210 
212  auto pushBuilder(std::shared_ptr<hilti::builder::Builder> b) {
213  _builders.emplace_back(b);
214  return b;
215  }
216 
218  std::shared_ptr<hilti::builder::Builder> pushBuilder();
219 
221  auto popBuilder() {
222  auto x = _builders.back();
223  _builders.pop_back();
224  return x;
225  }
226 
228  struct ScopeGuard {
229  ScopeGuard(ParserBuilder* self) { this->self = self; }
230  ScopeGuard(ScopeGuard&&) = default;
231  ~ScopeGuard() { self->popBuilder(); }
232 
233  ScopeGuard() = delete;
234  ScopeGuard(const ScopeGuard&) = delete;
235  ScopeGuard& operator=(const ScopeGuard&) = delete;
236  ScopeGuard& operator=(ScopeGuard&&) noexcept = delete;
237 
238  ParserBuilder* self;
239  };
240 
243 
245  auto pushBuilder(std::shared_ptr<hilti::builder::Builder> b, const std::function<void()>& func) {
246  pushBuilder(b);
247  func();
248  popBuilder();
249  return b;
250  }
251 
253  Expression parseType(const Type& t, const production::Meta& meta, const std::optional<Expression>& dst);
254 
256  Expression parseTypeTry(const Type& t, const production::Meta& meta, const std::optional<Expression>& dst);
257 
259  hilti::type::Function parseMethodFunctionType(std::optional<type::function::Parameter> addl_param = {},
260  const Meta& m = {});
261 
271  Expression parseLiteral(const Production& p, const std::optional<Expression>& dst);
272 
284  void waitForInput(const Expression& min, const std::string& error_msg, const Meta& location);
285 
297  Expression waitForInputOrEod(const Expression& min);
298 
306  void waitForInput(const std::string& error_msg, const Meta& location);
307 
316  Expression waitForInputOrEod();
317 
322  void waitForEod();
323 
325  Expression atEod();
326 
334  void advanceInput(const Expression& i);
335 
341  void setInput(const Expression& i);
342 
348  void saveParsePosition();
349 
351  void beforeHook();
352 
354  void afterHook();
355 
363  void consumeLookAhead(std::optional<Expression> dst = {});
364 
366  void parseError(const std::string& error_msg, const Meta& location);
367 
369  void parseError(const Expression& error_msg, const Meta& location);
370 
372  void parseError(const std::string& fmt, std::vector<Expression> args, const Meta& location);
373 
375  void newValueForField(const production::Meta& meta, const Expression& value, const Expression& dd);
376 
381  void enableDefaultNewValueForField(bool enable) { _report_new_value_for_field = enable; };
382 
387  bool isEnabledDefaultNewValueForField() { return _report_new_value_for_field; }
388 
393  Expression newContainerItem(const type::unit::item::Field& field, const Expression& self, const Expression& item,
394  bool need_value);
395 
403  Expression applyConvertExpression(const type::unit::item::Field& field, const Expression& value,
404  std::optional<Expression> dst = {});
405 
413  void trimInput(bool force = false);
414 
421  void initializeUnit(const Location& l);
422 
430  void finalizeUnit(bool success, const Location& l);
431 
433  void initBacktracking();
434 
436  void finishBacktracking();
437 
444  Expression initLoopBody();
445 
454  void finishLoopBody(const Expression& cookie, const Location& l);
455 
456  CodeGen* cg() const { return _cg; }
457  const std::shared_ptr<hilti::Context>& context() const;
458  const hilti::Options& options() const;
459 
460 private:
462  CodeGen* _cg;
463 
464  Expression _parseType(const Type& t, const production::Meta& meta, const std::optional<Expression>& dst,
465  bool is_try);
466 
467  std::vector<ParserState> _states;
468  std::vector<std::shared_ptr<hilti::builder::Builder>> _builders;
469  std::map<ID, Expression> _functions;
470  bool _report_new_value_for_field = true;
471 };
472 
473 } // namespace codegen
474 } // namespace spicy::detail
Definition: function.h:69
void enableDefaultNewValueForField(bool enable)
Definition: parser-builder.h:381
Definition: util.h:637
Definition: context.h:32
auto builder()
Definition: parser-builder.h:209
bool isEnabledDefaultNewValueForField()
Definition: parser-builder.h:387
Expression trim
Definition: parser-builder.h:126
std::optional< Expression > captures
Definition: parser-builder.h:147
Expression data
Definition: parser-builder.h:114
Definition: unit.h:51
Definition: production.h:120
Definition: parser-builder.h:85
ParserState state() const
Definition: parser-builder.h:168
Definition: parser-builder.h:151
Definition: struct.h:118
Definition: field.h:19
void pushState(ParserState p)
Definition: parser-builder.h:159
Definition: meta.h:18
void popState()
Definition: parser-builder.h:165
auto popBuilder()
Definition: parser-builder.h:221
Expression lahead_end
Definition: parser-builder.h:138
auto pushBuilder(std::shared_ptr< hilti::builder::Builder > b)
Definition: parser-builder.h:212
Definition: engine.h:16
bool needs_look_ahead
Definition: parser-builder.h:108
Definition: production.h:40
ID unit_id
Definition: parser-builder.h:105
Definition: builder.h:20
Expression cur
Definition: parser-builder.h:117
Definition: codegen.h:30
auto pushBuilder(std::shared_ptr< hilti::builder::Builder > b, const std::function< void()> &func)
Definition: parser-builder.h:245
Definition: location.h:17
Definition: parser-builder.cc:65
Definition: grammar.h:21
Definition: location.h:86
std::reference_wrapper< const type::Unit > unit
Definition: parser-builder.h:102
Definition: type.h:19
Definition: id.h:18
ScopeGuard makeScopeGuard()
Definition: parser-builder.h:242