am c48778ee: am 6929b5fa: am c71fdabd: Merge "First pass on reentrant C++-ish parser"
* commit 'c48778ee31878c3239bbf85c485eac64e5a06b59':
First pass on reentrant C++-ish parser
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index 832c51c..616f276 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -33,6 +33,8 @@
using namespace std;
+ParseState *psGlobal;
+
static void
test_document(document_item_type* d)
{
@@ -111,7 +113,7 @@
{
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 5fab6c2..5252920 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);
-}
-#endif
-
-#if 0
-ParserCallbacks k_parserCallbacks = {
- NULL
-};
-#endif
+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_);
+}
+
+ParseState::~ParseState() {
+ yylex_destroy(scanner_);
+}
+
+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 a3b1efc..f3a126e 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 @@
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 @@
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 aa42f2e..953e370 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 @@
#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 @@
/* 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 @@
// 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);
+ if (!ps.OpenFileFromDisk()) {
+ fprintf(stderr, "aidl: unable to open file for read: %s\n", filename);
+ return 1;
+ }
- 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;
- }
+ return ps.RunParser();
}
-
diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y
index 9c5d10e..90fd58c 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 @@
%%
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 @@
;
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 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 @@
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_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 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 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 @@
}
}
| 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 @@
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 @@
}
| 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 @@
#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 0000000..67b8076
--- /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_