FE 0.6.0
A header-only C++ library for writing frontends
Loading...
Searching...
No Matches
parser.h
Go to the documentation of this file.
1#pragma once
2
3#include "fe/loc.h"
4#include "fe/ring.h"
5
6namespace fe {
7
8/// The blueprint for a [recursive descent](https://en.wikipedia.org/wiki/Recursive_descent_parser)/
9/// [ascent parser](https://en.wikipedia.org/wiki/Recursive_ascent_parser) using a @p K lookahead of `Tok`ens.
10/// Parser::accept and Parser::expect indicate failure by constructing a @p Tok%en with its default constructor.
11/// Provide a conversion operator to `bool` to check for an error:
12/// ```
13/// class Tok {
14/// public:
15/// enum class Tag {
16/// Nil,
17/// // ...
18/// };
19/// // ...
20/// explicit bool operator() const { return tag_ != Tag::Nil; }
21/// // ...
22/// };
23///
24/// // Your Parser:
25/// if (auto tok = accept(Tok::Tag:My_Tag)) {
26/// do_sth(tok);
27/// }
28/// ```
29template<class Tok, class Tag, size_t K, class S>
30requires(std::is_convertible_v<Tok, bool> || std::is_constructible_v<bool, Tok>) || std::is_default_constructible_v<Tok>
31class Parser {
32private:
33 S& self() { return *static_cast<S*>(this); }
34 const S& self() const { return *static_cast<const S*>(this); }
35
36protected:
37 /// @name Construction
38 ///@{
39 void init(const std::filesystem::path* path) {
40 ahead_.reset();
41 for (size_t i = 0; i != K; ++i) ahead_[i] = self().lexer().lex();
42 prev_ = Loc(path, {1, 1});
43 }
44 ///@}
45
46 /// @name Track Loc%ation in Source File
47 /// Use like this:
48 /// ```
49 /// auto track = tracker();
50 /// auto foo = parse_foo();
51 /// auto bar = parse_bar();
52 /// auto foobar = new FooBar(track, foo, bar);
53 /// ```
54 ///@{
55 class Tracker {
56 public:
57 Tracker(Loc& prev, Pos pos)
58 : prev_(prev)
59 , pos_(pos) {}
60
61 Loc loc() const { return {prev_.path, pos_, prev_.finis}; }
62 Loc operator()() const { return loc(); }
63 operator Loc() const { return loc(); }
64
65 private:
66 const Loc& prev_;
67 Pos pos_;
68 };
69
70 /// Factory method to build a Parser::Tracker.
71 Tracker tracker() { return {prev_, ahead().loc().begin}; }
72 ///@}
73
74 /// @name Shift Token
75 ///@{
76 /// Get lookahead.
77 Tok ahead(size_t i = 0) const { return ahead_[i]; }
78
79 /// Invoke Lexer to retrieve next Token.
80 Tok lex() {
81 auto result = ahead();
82 prev_ = result.loc();
83 ahead_.put(self().lexer().lex());
84 return result;
85 }
86
87 /// If Parser::ahead() is a @p tag, consume and return it, otherwise yield `std::nullopt`.
88 Tok accept(Tag tag) {
89 if (tag != ahead().tag()) return {};
90 return lex();
91 }
92
93 /// Parser::lex Parser::ahead() which must be a @p tag.
94 /// Issue error with @p ctxt otherwise.
95 Tok expect(Tag tag, std::string_view ctxt) {
96 if (ahead().tag() == tag) return lex();
97 self().syntax_err(tag, ctxt);
98 return {};
99 }
100
101 /// Consume Parser::ahead which must be a @p tag; asserts otherwise.
102 Tok eat([[maybe_unused]] Tag tag) {
103 assert(tag == ahead().tag() && "internal parser error");
104 return lex();
105 }
106 ///@}
107
110};
111
112} // namespace fe
Loc operator()() const
Definition parser.h:62
Loc loc() const
Definition parser.h:61
Tracker(Loc &prev, Pos pos)
Definition parser.h:57
The blueprint for a recursive descent/ ascent parser using a K lookahead of Tokens.
Definition parser.h:31
Loc prev_
Definition parser.h:109
Tok lex()
Invoke Lexer to retrieve next Token.
Definition parser.h:80
Ring< Tok, K > ahead_
Definition parser.h:108
Tok eat(Tag tag)
Consume Parser::ahead which must be a tag; asserts otherwise.
Definition parser.h:102
Tok expect(Tag tag, std::string_view ctxt)
Parser::lex Parser::ahead() which must be a tag.
Definition parser.h:95
Tok accept(Tag tag)
If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.
Definition parser.h:88
Tracker tracker()
Factory method to build a Parser::Tracker.
Definition parser.h:71
Tok ahead(size_t i=0) const
Definition parser.h:77
void init(const std::filesystem::path *path)
Definition parser.h:39
A ring buffer with N elements.
Definition ring.h:14
Definition arena.h:9
Location in a File.
Definition loc.h:33
Position in a source file; pass around as value.
Definition loc.h:10