FE 0.5.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 ///@{
48 /// Use like this:
49 /// ```
50 /// auto track = tracker();
51 /// auto foo = parse_foo();
52 /// auto bar = parse_bar();
53 /// auto foobar = new FooBar(track, foo, bar);
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
77 /// Get lookahead.
78 Tok ahead(size_t i = 0) const { return ahead_[i]; }
79
80 /// Invoke Lexer to retrieve next Token.
81 Tok lex() {
82 auto result = ahead();
83 prev_ = result.loc();
84 ahead_.put(self().lexer().lex());
85 return result;
86 }
87
88 /// If Parser::ahead() is a @p tag, consume and return it, otherwise yield `std::nullopt`.
89 Tok accept(Tag tag) {
90 if (tag != ahead().tag()) return {};
91 return lex();
92 }
93
94 /// Parser::lex Parser::ahead() which must be a @p tag.
95 /// Issue error with @p ctxt otherwise.
96 Tok expect(Tag tag, std::string_view ctxt) {
97 if (ahead().tag() == tag) return lex();
98 self().syntax_err(tag, ctxt);
99 return {};
100 }
101
102 /// Consume Parser::ahead which must be a @p tag; asserts otherwise.
103 Tok eat([[maybe_unused]] Tag tag) {
104 assert(tag == ahead().tag() && "internal parser error");
105 return lex();
106 }
107 ///@}
108
111};
112
113} // 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:110
Tok lex()
Invoke Lexer to retrieve next Token.
Definition parser.h:81
Ring< Tok, K > ahead_
Definition parser.h:109
Tok eat(Tag tag)
Consume Parser::ahead which must be a tag; asserts otherwise.
Definition parser.h:103
Tok expect(Tag tag, std::string_view ctxt)
Parser::lex Parser::ahead() which must be a tag.
Definition parser.h:96
Tok accept(Tag tag)
If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.
Definition parser.h:89
Tracker tracker()
Factory method to build a Parser::Tracker.
Definition parser.h:71
Tok ahead(size_t i=0) const
Get lookahead.
Definition parser.h:78
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
const std::filesystem::path * path
Definition loc.h:55
Pos begin
Definition loc.h:56
Position in a source file; pass around as value.
Definition loc.h:10