1 /*
2  * Copyright (C) 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "aidl_language.h"
20 #include "aidl_typenames.h"
21 #include "comments.h"
22 #include "io_delegate.h"
23 #include "logging.h"
24 #include "options.h"
25 
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 struct yy_buffer_state;
31 typedef yy_buffer_state* YY_BUFFER_STATE;
32 
33 class AidlToken {
34  public:
AidlToken(const std::string & text,android::aidl::Comments comments)35   AidlToken(const std::string& text, android::aidl::Comments comments)
36       : text_(text), comments_(std::move(comments)) {}
37   ~AidlToken() = default;
38 
39   AidlToken(const AidlToken&) = delete;
40   AidlToken(AidlToken&&) = delete;
41   AidlToken& operator=(const AidlToken&) = delete;
42   AidlToken& operator=(AidlToken&&) = delete;
43 
GetText()44   const std::string& GetText() const { return text_; }
GetComments()45   const android::aidl::Comments& GetComments() const { return comments_; }
46 
47   template <typename T>
Append(T && text)48   void Append(T&& text) {
49     text_ += std::forward<T>(text);
50   }
51 
52  private:
53   std::string text_;
54   android::aidl::Comments comments_;
55 };
56 
57 using TypeResolver = std::function<bool(const AidlDocument*, AidlTypeSpecifier*)>;
58 
59 class Parser {
60  public:
61   // non-copyable, non-assignable
62   Parser(const Parser&) = delete;
63   Parser& operator=(const Parser&) = delete;
64 
65   ~Parser();
66 
67   // Parse contents of file |filename|. Should only be called once.
68   static std::unique_ptr<Parser> Parse(const std::string& filename,
69                                        const android::aidl::IoDelegate& io_delegate,
70                                        AidlTypenames& typenames);
71 
AddError()72   void AddError() { error_++; }
HasError()73   bool HasError() const { return error_ != 0; }
74 
FileName()75   const std::string& FileName() const { return filename_; }
Scanner()76   void* Scanner() const { return scanner_; }
77 
78   // This restricts the grammar to something more reasonable. One alternative
79   // would be to support multiple sets of type specifiers in our AST, but then a
80   // lot of later code would have to deal with this more complicated type. So,
81   // in order to keep the AST simpler, restricting the grammar here.
82   //
83   // Takes ownership of type_args, modifies type.
84   void SetTypeParameters(AidlTypeSpecifier* type,
85                          std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args);
86 
SetPackage(const std::string & package)87   void SetPackage(const std::string& package) { package_ = package; }
Package()88   const std::string& Package() const { return package_; }
89 
DeferResolution(AidlTypeSpecifier * typespec)90   void DeferResolution(AidlTypeSpecifier* typespec) {
91     unresolved_typespecs_.emplace_back(typespec);
92   }
93 
GetUnresolvedTypespecs()94   const vector<AidlTypeSpecifier*>& GetUnresolvedTypespecs() const { return unresolved_typespecs_; }
95 
96   bool Resolve(TypeResolver& type_resolver);
SetDocument(std::unique_ptr<AidlDocument> && document)97   void SetDocument(std::unique_ptr<AidlDocument>&& document) {
98     // The parsed document is owned by typenames_. This parser object only has
99     // a reference to it.
100     document_ = document.get();
101     if (!typenames_.AddDocument(std::move(document))) {
102       document_ = nullptr;
103       AddError();
104     }
105   }
106 
ParsedDocument()107   const AidlDocument& ParsedDocument() const {
108     AIDL_FATAL_IF(HasError(), FileName());
109     return *document_;
110   }
111 
112  private:
113   explicit Parser(const std::string& filename, std::string& raw_buffer,
114                   android::aidl::AidlTypenames& typenames);
115 
116   std::string filename_;
117   std::string package_;
118   AidlTypenames& typenames_;
119 
120   void* scanner_ = nullptr;
121   YY_BUFFER_STATE buffer_;
122   int error_ = 0;
123 
124   vector<AidlTypeSpecifier*> unresolved_typespecs_;
125   const AidlDocument* document_;
126 };
127