blob: 897efa0ef24b00d764766d8add6b8fe766459faa [file] [log] [blame]
Jiyong Parke5c45292020-05-26 19:06:24 +09001/*
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#include "parser.h"
Steven Moreland21780812020-09-11 01:29:45 +000018#include "aidl_language_y.h"
Jiyong Park2a7c92b2020-07-22 19:12:36 +090019#include "logging.h"
Jiyong Parke5c45292020-05-26 19:06:24 +090020
21void yylex_init(void**);
22void yylex_destroy(void*);
23void yyset_in(FILE* f, void*);
24int yyparse(Parser*);
25YY_BUFFER_STATE yy_scan_buffer(char*, size_t, void*);
26void yy_delete_buffer(YY_BUFFER_STATE, void*);
27
28std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
29 const android::aidl::IoDelegate& io_delegate,
30 AidlTypenames& typenames) {
31 // Make sure we can read the file first, before trashing previous state.
32 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
33 if (raw_buffer == nullptr) {
34 AIDL_ERROR(filename) << "Error while opening file for parsing";
35 return nullptr;
36 }
37
38 // We're going to scan this buffer in place, and yacc demands we put two
39 // nulls at the end.
40 raw_buffer->append(2u, '\0');
41
42 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
43
Jiyong Park8e79b7f2020-07-20 20:52:38 +090044 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) {
45 return nullptr;
46 }
Jiyong Parke5c45292020-05-26 19:06:24 +090047
48 return parser;
49}
50
Steven Moreland6c07b832020-10-29 23:39:53 +000051void Parser::SetTypeParameters(AidlTypeSpecifier* type,
52 std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args) {
53 if (type->IsArray()) {
54 AIDL_ERROR(type) << "Must specify type parameters (<>) before array ([]).";
55 AddError();
56 }
57 if (!type->SetTypeParameters(type_args)) {
58 AIDL_ERROR(type) << "Can only specify one set of type parameters.";
59 AddError();
60 delete type_args;
61 }
62}
63
Jooyung Han29813842020-12-08 01:28:03 +090064class ConstantReferenceResolver : public AidlConstantValue::Visitor {
65 public:
66 ConstantReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
67 TypeResolver& resolver, bool* success)
68 : scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {}
Jooyung Han9d3cbe22020-12-28 03:02:08 +090069 void Visit(const AidlConstantValue&) override {}
70 void Visit(const AidlUnaryConstExpression&) override {}
71 void Visit(const AidlBinaryConstExpression&) override {}
72 void Visit(const AidlConstantReference& v) override {
Jooyung Han29813842020-12-08 01:28:03 +090073 if (IsCircularReference(&v)) {
74 *success_ = false;
75 return;
76 }
77
Jooyung Han9d3cbe22020-12-28 03:02:08 +090078 if (v.GetRefType() && !v.GetRefType()->IsResolved()) {
Jooyung Han29813842020-12-08 01:28:03 +090079 if (!resolver_(typenames_.GetDocumentFor(scope_), v.GetRefType().get())) {
80 AIDL_ERROR(v.GetRefType()) << "Failed to resolve '" << v.GetRefType()->GetName() << "'";
81 *success_ = false;
82 return;
83 }
84 }
Jooyung Han9d3cbe22020-12-28 03:02:08 +090085 const AidlConstantValue* resolved = v.Resolve(scope_);
Jooyung Han29813842020-12-08 01:28:03 +090086 if (!resolved) {
87 AIDL_ERROR(v.GetRefType()) << "Failed to resolve '" << v.GetRefType()->GetName() << "'";
88 *success_ = false;
89 return;
90 }
91
92 // resolve recursive references
93 Push(&v);
94 const_cast<AidlConstantValue*>(resolved)->Accept(*this);
95 Pop();
96 }
97
98 private:
99 struct StackElem {
100 const AidlDefinedType* scope;
101 const AidlConstantReference* ref;
102 };
103
104 void Push(const AidlConstantReference* ref) {
105 stack_.push_back({scope_, ref});
Jooyung Han9d3cbe22020-12-28 03:02:08 +0900106 if (ref->GetRefType()) {
107 scope_ = ref->GetRefType()->GetDefinedType();
108 }
Jooyung Han29813842020-12-08 01:28:03 +0900109 }
110
111 void Pop() {
112 scope_ = stack_.back().scope;
113 stack_.pop_back();
114 }
115
116 bool IsCircularReference(const AidlConstantReference* ref) {
117 auto it = std::find_if(stack_.begin(), stack_.end(),
118 [&](const auto& elem) { return elem.ref == ref; });
119 if (it == stack_.end()) {
120 return false;
121 }
122 std::vector<std::string> path;
123 while (it != stack_.end()) {
124 path.push_back(it->ref->Literal());
125 ++it;
126 }
127 path.push_back(ref->Literal());
128 AIDL_ERROR(ref) << "Found a circular reference: " << android::base::Join(path, " -> ");
129 return true;
130 }
131
132 const AidlDefinedType* scope_;
133 const AidlTypenames& typenames_;
134 TypeResolver& resolver_;
135 bool* success_;
136 std::vector<StackElem> stack_ = {};
137};
138
139bool Parser::Resolve(TypeResolver& type_resolver) {
Jiyong Parke5c45292020-05-26 19:06:24 +0900140 bool success = true;
141 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
Jooyung Han29813842020-12-08 01:28:03 +0900142 if (!type_resolver(document_, typespec)) {
Jiyong Parke5c45292020-05-26 19:06:24 +0900143 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
144 success = false;
145 // don't stop to show more errors if any
146 }
147 }
Jooyung Han690f5842020-12-04 13:02:04 +0900148
Jooyung Han690f5842020-12-04 13:02:04 +0900149 // resolve "field references" as well.
150 for (const auto& type : document_->DefinedTypes()) {
Jooyung Han29813842020-12-08 01:28:03 +0900151 ConstantReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
Jooyung Han690f5842020-12-04 13:02:04 +0900152 if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
153 for (const auto& enumerator : enum_type->GetEnumerators()) {
154 if (auto value = enumerator->GetValue(); value) {
Jooyung Han29813842020-12-08 01:28:03 +0900155 value->Accept(ref_resolver);
Jooyung Han690f5842020-12-04 13:02:04 +0900156 }
157 }
158 } else {
159 for (const auto& constant : type->GetConstantDeclarations()) {
Jooyung Han29813842020-12-08 01:28:03 +0900160 const_cast<AidlConstantValue&>(constant->GetValue()).Accept(ref_resolver);
Jooyung Han690f5842020-12-04 13:02:04 +0900161 }
162 for (const auto& field : type->GetFields()) {
163 if (field->IsDefaultUserSpecified()) {
Jooyung Han29813842020-12-08 01:28:03 +0900164 const_cast<AidlConstantValue*>(field->GetDefaultValue())->Accept(ref_resolver);
Jooyung Han690f5842020-12-04 13:02:04 +0900165 }
166 }
167 }
168 }
169
Jiyong Parke5c45292020-05-26 19:06:24 +0900170 return success;
171}
172
173Parser::Parser(const std::string& filename, std::string& raw_buffer,
174 android::aidl::AidlTypenames& typenames)
175 : filename_(filename), typenames_(typenames) {
176 yylex_init(&scanner_);
177 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
178}
179
180Parser::~Parser() {
181 yy_delete_buffer(buffer_, scanner_);
182 yylex_destroy(scanner_);
183}