Initial work
This commit is contained in:
commit
3222551702
374 changed files with 40290 additions and 0 deletions
191
external/android-emugl/host/tools/emugen/Parser.cpp
vendored
Normal file
191
external/android-emugl/host/tools/emugen/Parser.cpp
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "Parser.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define WHITESPACE " \t\n"
|
||||
|
||||
// Parse the |input| string as a list of type-specific tokens.
|
||||
// This tokenizes the input, using whitespace as separators and '*' as
|
||||
// a single token too. On success, return true and sets |*out| to the
|
||||
// list of tokens. On failure, return false.
|
||||
//
|
||||
// Example: 'const char**foo' -> ['const', 'char', '*', '*', 'foo']
|
||||
//
|
||||
static bool parseTypeTokens(const std::string& input,
|
||||
std::vector<std::string>* out,
|
||||
std::string* error) {
|
||||
out->clear();
|
||||
size_t pos = 0U;
|
||||
|
||||
// Parse all tokens in the input, treat '*' as a single token.
|
||||
// I.e.
|
||||
for (;;) {
|
||||
// skip leading whitespace.
|
||||
pos = input.find_first_not_of(WHITESPACE, pos);
|
||||
if (pos == std::string::npos) {
|
||||
break; // end of parse.
|
||||
}
|
||||
|
||||
// If this is a star, ensure it follows a type name.
|
||||
// otherwise treat it as part of the final type.
|
||||
if (input[pos] == '*') {
|
||||
out->push_back(std::string("*"));
|
||||
pos += 1U;
|
||||
continue;
|
||||
}
|
||||
|
||||
// find end of type/token.
|
||||
size_t end = input.find_first_of(WHITESPACE "*", pos);
|
||||
if (end == std::string::npos) {
|
||||
end = input.size();
|
||||
}
|
||||
|
||||
std::string str = input.substr(pos, end - pos);
|
||||
if (str.size() == 0) {
|
||||
// Sanity check: should not happen.
|
||||
if (error != NULL) {
|
||||
*error = "Unexpected empty token !?";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
out->push_back(str);
|
||||
pos = end;
|
||||
}
|
||||
|
||||
if (error != NULL) {
|
||||
// Sanity check: require non-empty input
|
||||
if (out->empty()) {
|
||||
*error = "Empty parameter declaration!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check: There must be base type name before any '*'
|
||||
for (size_t n = 0; n < out->size(); ++n) {
|
||||
std::string& token = (*out)[n];
|
||||
if (token == "*") {
|
||||
*error = "Unexpected '*' before type name";
|
||||
return false;
|
||||
} else if (token != "const") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Given |tokens|, an input vector of strings, join the first |count| items
|
||||
// into a normalized type string, and return it.
|
||||
static std::string buildTypeString(const std::vector<std::string>& tokens,
|
||||
size_t count) {
|
||||
std::string result;
|
||||
|
||||
for (size_t n = 0; n < count; ++n) {
|
||||
const std::string& token = tokens[n];
|
||||
if (n > 0 && token != "*") {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string normalizeTypeDeclaration(const std::string& input) {
|
||||
std::vector<std::string> tokens;
|
||||
if (!parseTypeTokens(input, &tokens, NULL)) {
|
||||
return "";
|
||||
}
|
||||
return buildTypeString(tokens, tokens.size());
|
||||
}
|
||||
|
||||
bool parseTypeDeclaration(const std::string& input,
|
||||
std::string* typeName,
|
||||
std::string* error) {
|
||||
// The type name can be made of several tokens, e.g. 'unsigned int'
|
||||
// use an array to store them, and a count variable. Each item can be
|
||||
// one of '*', 'const' or a type name component (e.g. 'struct', 'unsigned')
|
||||
std::vector<std::string> tokens;
|
||||
|
||||
if (!parseTypeTokens(input, &tokens, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check, there must be a least one non-special tokens.
|
||||
size_t nonSpecialCount = 0;
|
||||
for (size_t n = 0; n < tokens.size(); ++n) {
|
||||
if (tokens[n] != "*" && tokens[n] != "const") {
|
||||
nonSpecialCount++;
|
||||
}
|
||||
}
|
||||
if (nonSpecialCount == 0) {
|
||||
*error = "Missing type name";
|
||||
return false;
|
||||
}
|
||||
// Build the type name from all tokens before it.
|
||||
*typeName = buildTypeString(tokens, tokens.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool parseParameterDeclaration(const std::string& param,
|
||||
std::string* typeName,
|
||||
std::string* variableName,
|
||||
std::string* error) {
|
||||
std::vector<std::string> tokens;
|
||||
|
||||
if (!parseTypeTokens(param, &tokens, error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check, there must be a least two non-special tokens.
|
||||
size_t nonSpecialCount = 0;
|
||||
for (size_t n = 0; n < tokens.size(); ++n) {
|
||||
if (tokens[n] != "*" && tokens[n] != "const") {
|
||||
nonSpecialCount++;
|
||||
}
|
||||
}
|
||||
if (nonSpecialCount == 0) {
|
||||
*error = "Missing type name";
|
||||
return false;
|
||||
}
|
||||
if (nonSpecialCount == 1) {
|
||||
*error = "Missing variable name";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check: variable name must not be followed by 'const' or '*'
|
||||
const std::string& lastToken = tokens[tokens.size() - 1U];
|
||||
if (lastToken == "*") {
|
||||
*error = "Extra '*' after variable name";
|
||||
return false;
|
||||
}
|
||||
if (lastToken == "const") {
|
||||
*error = "Extra 'const' after variable name";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract the variable name as the last token.
|
||||
if (variableName) {
|
||||
*variableName = lastToken;
|
||||
}
|
||||
// Build the type name from all tokens before it.
|
||||
*typeName = buildTypeString(tokens, tokens.size() - 1U);
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue