diff options
author | Casey Dahlin <sadmac@google.com> | 2015-09-09 17:59:06 -0700 |
---|---|---|
committer | Casey Dahlin <sadmac@google.com> | 2015-09-10 16:55:18 -0700 |
commit | 9941dcc7aadcc15f7a52b4a76af4025f33b7f45f (patch) | |
tree | 5168601a1e15decce5627da1c5ba001a922f84bd /tools/aidl | |
parent | 596fd38af207727d508a63fca39506c90ba29c44 (diff) |
First pass on reentrant C++-ish parser
We're flipping Flex/Bison in to reentrant mode, cutting down on global
variables, and exposing a more C++-like interface earlier. This is the first
phase. There's still a couple of weird hacks to deal with the previous code's
reckless disregard for scope sanity, but the outline of things to come is
starting to appear, and this CL really doesn't need to get any bigger.
Change-Id: Ife2d70db026d7ab1319bdf6c586959315666d0bb
Signed-off-by: Casey Dahlin <sadmac@google.com>
Diffstat (limited to 'tools/aidl')
-rw-r--r-- | tools/aidl/aidl.cpp | 4 | ||||
-rw-r--r-- | tools/aidl/aidl_language.cpp | 90 | ||||
-rw-r--r-- | tools/aidl/aidl_language.h | 36 | ||||
-rw-r--r-- | tools/aidl/aidl_language_l.l | 62 | ||||
-rw-r--r-- | tools/aidl/aidl_language_y.y | 63 | ||||
-rw-r--r-- | tools/aidl/macros.h | 8 |
6 files changed, 180 insertions, 83 deletions
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index 46c689970dc4..d5815011ef4c 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -36,6 +36,8 @@ using std::set; using std::string; using std::vector; +ParseState *psGlobal; + static void test_document(document_item_type* d) { @@ -114,7 +116,7 @@ main_import_parsed(buffer_type* statement) { import_info* import = (import_info*)malloc(sizeof(import_info)); memset(import, 0, sizeof(import_info)); - import->from = strdup(g_currentFilename); + import->from = strdup(psGlobal->FileName().c_str()); import->statement.lineno = statement->lineno; import->statement.data = strdup(statement->data); import->statement.extra = NULL; diff --git a/tools/aidl/aidl_language.cpp b/tools/aidl/aidl_language.cpp index 5fab6c26431a..525292055755 100644 --- a/tools/aidl/aidl_language.cpp +++ b/tools/aidl/aidl_language.cpp @@ -1,20 +1,86 @@ #include "aidl_language.h" #include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string> +#include <iostream> -#ifdef _WIN32 -int isatty(int fd) -{ - return (fd == 0); +using std::string; +using std::cerr; +using std::endl; + +ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; + +void yylex_init(void **); +void yylex_destroy(void *); +void yyset_in(FILE *f, void *); +int yyparse(ParseState*); + +ParseState::ParseState() : ParseState("") {} + +ParseState::ParseState(const string& filename) + : filename_(filename) { + yylex_init(&scanner_); } -#endif -#if 0 -ParserCallbacks k_parserCallbacks = { - NULL -}; -#endif +ParseState::~ParseState() { + yylex_destroy(scanner_); +} -ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; +string ParseState::FileName() { + return filename_; +} + +string ParseState::Package() { + return g_currentPackage; +} + +void ParseState::ProcessDocument(const document_item_type& items) { + /* The cast is not my fault. I didn't write the code on the other side. */ + /* TODO(sadmac): b/23977313 */ + g_callbacks->document((document_item_type *)&items); +} + +void ParseState::ProcessImport(const buffer_type& statement) { + /* The cast is not my fault. I didn't write the code on the other side. */ + /* TODO(sadmac): b/23977313 */ + g_callbacks->import((buffer_type *)&statement); +} +void ParseState::ReportError(const string& err) { + /* FIXME: We're printing out the line number as -1. We used to use yylineno + * (which was NEVER correct even before reentrant parsing). Now we'll need + * another way. + */ + cerr << filename_ << ":" << -1 << ": " << err << endl; + error_ = 1; +} + +bool ParseState::FoundNoErrors() { + return error_ == 0; +} + +void *ParseState::Scanner() { + return scanner_; +} + +bool ParseState::OpenFileFromDisk() { + FILE *in = fopen(FileName().c_str(), "r"); + + if (! in) + return false; + + yyset_in(in, Scanner()); + return true; +} + +int ParseState::RunParser() { + int ret = yyparse(this); + + free((void *)g_currentPackage); + g_currentPackage = NULL; + + if (error_) + return 1; + + return ret; +} diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h index a3b1efcbaf40..f3a126e9f57a 100644 --- a/tools/aidl/aidl_language.h +++ b/tools/aidl/aidl_language.h @@ -1,6 +1,9 @@ #ifndef AIDL_AIDL_LANGUAGE_H_ #define AIDL_AIDL_LANGUAGE_H_ +#include <string> + +#include "macros.h" typedef enum { NO_EXTRA_TEXT = 0, @@ -141,12 +144,6 @@ typedef struct ParserCallbacks { extern ParserCallbacks* g_callbacks; -// true if there was an error parsing, false otherwise -extern int g_error; - -// the name of the file we're currently parsing -extern char const* g_currentFilename; - // the package name for our current file extern char const* g_currentPackage; @@ -157,6 +154,33 @@ typedef enum { void init_buffer_type(buffer_type* buf, int lineno); +class ParseState { + public: + ParseState(); + ParseState(const std::string& filename); + ~ParseState(); + + bool OpenFileFromDisk(); + int RunParser(); + void ReportError(const std::string& err); + + bool FoundNoErrors(); + std::string FileName(); + std::string Package(); + void *Scanner(); + + void ProcessDocument(const document_item_type& items); + void ProcessImport(const buffer_type& statement); + + private: + int error_ = 0; + std::string filename_; + std::string package_; + void *scanner_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(ParseState); +}; + #if __cplusplus } #endif diff --git a/tools/aidl/aidl_language_l.l b/tools/aidl/aidl_language_l.l index aa42f2e9a9fd..953e3709eb66 100644 --- a/tools/aidl/aidl_language_l.l +++ b/tools/aidl/aidl_language_l.l @@ -7,6 +7,13 @@ extern YYSTYPE yylval; +#ifdef _WIN32 +static inline int isatty(int fd) +{ + return 0; +} +#endif + // comment and whitespace handling // these functions save a copy of the buffer static void begin_extra_text(unsigned lineno, which_extra_text which); @@ -20,16 +27,18 @@ static void do_package_statement(const char* importText); #define SET_BUFFER(t) \ do { \ - yylval.buffer.lineno = yylineno; \ - yylval.buffer.token = (t); \ - yylval.buffer.data = strdup(yytext); \ - yylval.buffer.extra = get_extra_text(); \ + yylval->buffer.lineno = yyget_lineno(yyscanner); \ + yylval->buffer.token = (t); \ + yylval->buffer.data = strdup(yytext); \ + yylval->buffer.extra = get_extra_text(); \ } while(0) %} %option yylineno %option noyywrap +%option reentrant +%option bison-bridge %x COPYING LONG_COMMENT @@ -96,9 +105,9 @@ oneway { SET_BUFFER(ONEWAY); return ONEWAY; } /* syntax error! */ . { printf("UNKNOWN(%s)", yytext); - yylval.buffer.lineno = yylineno; - yylval.buffer.token = IDENTIFIER; - yylval.buffer.data = strdup(yytext); + yylval->buffer.lineno = yylineno; + yylval->buffer.token = IDENTIFIER; + yylval->buffer.data = strdup(yytext); return IDENTIFIER; } @@ -177,36 +186,17 @@ void do_package_statement(const char* importText) // main parse function // ================================================ -char const* g_currentFilename = NULL; +extern ParseState *psGlobal; char const* g_currentPackage = NULL; -int yyparse(void); +int parse_aidl(char const *filename) { + ParseState ps(filename); + psGlobal = &ps; -int parse_aidl(char const *filename) -{ - yyin = fopen(filename, "r"); - if (yyin) { - char const* oldFilename = g_currentFilename; - char const* oldPackage = g_currentPackage; - g_currentFilename = strdup(filename); - - g_error = 0; - yylineno = 1; - int rv = yyparse(); - if (g_error != 0) { - rv = g_error; - } - - free((void*)g_currentFilename); - g_currentFilename = oldFilename; - - if (g_currentPackage) free((void*)g_currentPackage); - g_currentPackage = oldPackage; - - return rv; - } else { - fprintf(stderr, "aidl: unable to open file for read: %s\n", filename); - return 1; - } -} + if (!ps.OpenFileFromDisk()) { + fprintf(stderr, "aidl: unable to open file for read: %s\n", filename); + return 1; + } + return ps.RunParser(); +} diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y index 9c5d10e6892a..90fd58c5353c 100644 --- a/tools/aidl/aidl_language_y.y +++ b/tools/aidl/aidl_language_y.y @@ -4,14 +4,24 @@ #include <stdlib.h> #include <string.h> -int yyerror(char* errstr); -int yylex(void); -extern int yylineno; +int yyerror(ParseState* ps, char* errstr) +{ + ps->ReportError(errstr); + return 1; +} + +int yylex(lexer_type *, void *); static int count_brackets(const char*); +#define YYLEX_PARAM ps->Scanner() + %} +%parse-param { ParseState* ps } + +%pure-parser + %token IMPORT %token PACKAGE %token IDENTIFIER @@ -27,8 +37,8 @@ static int count_brackets(const char*); %% document: - document_items { g_callbacks->document($1.document_item); } - | headers document_items { g_callbacks->document($2.document_item); } + document_items { ps->ProcessDocument(*$1.document_item); } + | headers document_items { ps->ProcessDocument(*$2.document_item); } ; headers: @@ -42,8 +52,8 @@ package: ; imports: - IMPORT { g_callbacks->import(&($1.buffer)); } - | IMPORT imports { g_callbacks->import(&($1.buffer)); } + IMPORT { ps->ProcessImport($1.buffer); } + | IMPORT imports { ps->ProcessImport($1.buffer); } ; document_items: @@ -66,7 +76,8 @@ document_items: } } | document_items error { - fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", g_currentFilename, + fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$ = $1; } @@ -84,19 +95,20 @@ parcelable_decl: b->document_item.next = NULL; b->keyword_token = $1.buffer; b->name = $2.buffer; - b->package = g_currentPackage ? strdup(g_currentPackage) : NULL; + b->package = + strdup(ps->Package().c_str()); b->semicolon_token = $3.buffer; b->parcelable = true; $$.user_data = b; } | PARCELABLE ';' { fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n", - g_currentFilename, $1.buffer.lineno); + ps->FileName().c_str(), $1.buffer.lineno); $$.user_data = NULL; } | PARCELABLE error ';' { fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.user_data = NULL; } ; @@ -128,7 +140,8 @@ interface_decl: interface_header IDENTIFIER '{' interface_items '}' { interface_type* c = $1.interface_obj; c->name = $2.buffer; - c->package = g_currentPackage ? strdup(g_currentPackage) : NULL; + c->package = + strdup(ps->Package().c_str()); c->open_brace_token = $3.buffer; c->interface_items = $4.interface_item; c->close_brace_token = $5.buffer; @@ -136,12 +149,12 @@ interface_decl: } | INTERFACE error '{' interface_items '}' { fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.document_item = NULL; } | INTERFACE error '}' { fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.document_item = NULL; } @@ -163,7 +176,7 @@ interface_items: } | interface_items error ';' { fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n", - g_currentFilename, $3.buffer.lineno); + ps->FileName().c_str(), $3.buffer.lineno); $$ = $1; } ; @@ -259,7 +272,8 @@ arg_list: } } | error { - fprintf(stderr, "%s:%d: syntax error in parameter list\n", g_currentFilename, $1.buffer.lineno); + fprintf(stderr, "%s:%d: syntax error in parameter list\n", + ps->FileName().c_str(), $1.buffer.lineno); $$.arg = NULL; } ; @@ -279,7 +293,8 @@ arg: type: IDENTIFIER { $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); + init_buffer_type(&$$.type.array_token, + $1.buffer.lineno); $$.type.dimension = 0; } | IDENTIFIER ARRAY { @@ -289,13 +304,14 @@ type: } | GENERIC { $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); + init_buffer_type(&$$.type.array_token, + $1.buffer.lineno); $$.type.dimension = 0; } ; direction: - { init_buffer_type(&$$.buffer, yylineno); } + { init_buffer_type(&$$.buffer, $$.buffer.lineno); } | IN { $$.buffer = $1.buffer; } | OUT { $$.buffer = $1.buffer; } | INOUT { $$.buffer = $1.buffer; } @@ -306,15 +322,6 @@ direction: #include <ctype.h> #include <stdio.h> -int g_error = 0; - -int yyerror(char* errstr) -{ - fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr); - g_error = 1; - return 1; -} - void init_buffer_type(buffer_type* buf, int lineno) { buf->lineno = lineno; diff --git a/tools/aidl/macros.h b/tools/aidl/macros.h new file mode 100644 index 000000000000..67b8076404a4 --- /dev/null +++ b/tools/aidl/macros.h @@ -0,0 +1,8 @@ +#ifndef AIDL_MACROS_H_ +#define AIDL_MACROS_H_ + +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // AIDL_MACROS_H_ |