1// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22#pragma once
23
24#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
25#pragma GCC system_header
26#endif
27
28#include <capnp/compiler/lexer.capnp.h>
29#include <kj/parse/common.h>
30#include <kj/arena.h>
31#include "error-reporter.h"
32
33namespace capnp {
34namespace compiler {
35
36bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result,
37 ErrorReporter& errorReporter);
38bool lex(kj::ArrayPtr<const char> input, LexedTokens::Builder result, ErrorReporter& errorReporter);
39// Lex the given source code, placing the results in `result`. Returns true if there
40// were no errors, false if there were. Even when errors are present, the file may have partial
41// content which can be fed into later stages of parsing in order to find more errors.
42//
43// There are two versions, one that parses a list of statements, and one which just parses tokens
44// that might form a part of one statement. In other words, in the later case, the input should
45// not contain semicolons or curly braces, unless they are in string literals of course.
46
47class Lexer {
48 // Advanced lexer interface. This interface exposes the inner parsers so that you can embed them
49 // into your own parsers.
50
51public:
52 Lexer(Orphanage orphanage, ErrorReporter& errorReporter);
53 // `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is
54 // a pointer to the beginning of the input, used to compute byte offsets.
55
56 ~Lexer() noexcept(false);
57
58 class ParserInput: public kj::parse::IteratorInput<char, const char*> {
59 // Like IteratorInput<char, const char*> except that positions are measured as byte offsets
60 // rather than pointers.
61
62 public:
63 ParserInput(const char* begin, const char* end)
64 : IteratorInput<char, const char*>(begin, end), begin(begin) {}
65 explicit ParserInput(ParserInput& parent)
66 : IteratorInput<char, const char*>(parent), begin(parent.begin) {}
67
68 inline uint32_t getBest() {
69 return IteratorInput<char, const char*>::getBest() - begin;
70 }
71 inline uint32_t getPosition() {
72 return IteratorInput<char, const char*>::getPosition() - begin;
73 }
74
75 private:
76 const char* begin;
77 };
78
79 template <typename Output>
80 using Parser = kj::parse::ParserRef<ParserInput, Output>;
81
82 struct Parsers {
83 Parser<kj::Tuple<>> emptySpace;
84 Parser<Orphan<Token>> token;
85 Parser<kj::Array<Orphan<Token>>> tokenSequence;
86 Parser<Orphan<Statement>> statement;
87 Parser<kj::Array<Orphan<Statement>>> statementSequence;
88 };
89
90 const Parsers& getParsers() { return parsers; }
91
92private:
93 Orphanage orphanage;
94 kj::Arena arena;
95 Parsers parsers;
96};
97
98} // namespace compiler
99} // namespace capnp
100