am 6929b5fa: am c71fdabd: Merge "First pass on reentrant C++-ish parser"

* commit '6929b5fab007281d3c35deec905feb8fdc506a31':
  First pass on reentrant C++-ish parser
This commit is contained in:
Casey Dahlin
2015-09-11 01:55:49 +00:00
committed by Android Git Automerger
6 changed files with 180 additions and 83 deletions

View File

@@ -33,6 +33,8 @@
using namespace std; using namespace std;
ParseState *psGlobal;
static void static void
test_document(document_item_type* d) test_document(document_item_type* d)
{ {
@@ -111,7 +113,7 @@ main_import_parsed(buffer_type* statement)
{ {
import_info* import = (import_info*)malloc(sizeof(import_info)); import_info* import = (import_info*)malloc(sizeof(import_info));
memset(import, 0, 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.lineno = statement->lineno;
import->statement.data = strdup(statement->data); import->statement.data = strdup(statement->data);
import->statement.extra = NULL; import->statement.extra = NULL;

View File

@@ -1,20 +1,86 @@
#include "aidl_language.h" #include "aidl_language.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string>
#include <iostream>
#ifdef _WIN32 using std::string;
int isatty(int fd) using std::cerr;
{ using std::endl;
return (fd == 0);
}
#endif
#if 0
ParserCallbacks k_parserCallbacks = {
NULL
};
#endif
ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; 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;
}

View File

@@ -1,6 +1,9 @@
#ifndef AIDL_AIDL_LANGUAGE_H_ #ifndef AIDL_AIDL_LANGUAGE_H_
#define AIDL_AIDL_LANGUAGE_H_ #define AIDL_AIDL_LANGUAGE_H_
#include <string>
#include "macros.h"
typedef enum { typedef enum {
NO_EXTRA_TEXT = 0, NO_EXTRA_TEXT = 0,
@@ -141,12 +144,6 @@ typedef struct ParserCallbacks {
extern ParserCallbacks* g_callbacks; 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 // the package name for our current file
extern char const* g_currentPackage; extern char const* g_currentPackage;
@@ -157,6 +154,33 @@ typedef enum {
void init_buffer_type(buffer_type* buf, int lineno); 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 #if __cplusplus
} }
#endif #endif

View File

@@ -7,6 +7,13 @@
extern YYSTYPE yylval; extern YYSTYPE yylval;
#ifdef _WIN32
static inline int isatty(int fd)
{
return 0;
}
#endif
// comment and whitespace handling // comment and whitespace handling
// these functions save a copy of the buffer // these functions save a copy of the buffer
static void begin_extra_text(unsigned lineno, which_extra_text which); 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) \ #define SET_BUFFER(t) \
do { \ do { \
yylval.buffer.lineno = yylineno; \ yylval->buffer.lineno = yyget_lineno(yyscanner); \
yylval.buffer.token = (t); \ yylval->buffer.token = (t); \
yylval.buffer.data = strdup(yytext); \ yylval->buffer.data = strdup(yytext); \
yylval.buffer.extra = get_extra_text(); \ yylval->buffer.extra = get_extra_text(); \
} while(0) } while(0)
%} %}
%option yylineno %option yylineno
%option noyywrap %option noyywrap
%option reentrant
%option bison-bridge
%x COPYING LONG_COMMENT %x COPYING LONG_COMMENT
@@ -96,9 +105,9 @@ oneway { SET_BUFFER(ONEWAY); return ONEWAY; }
/* syntax error! */ /* syntax error! */
. { printf("UNKNOWN(%s)", yytext); . { printf("UNKNOWN(%s)", yytext);
yylval.buffer.lineno = yylineno; yylval->buffer.lineno = yylineno;
yylval.buffer.token = IDENTIFIER; yylval->buffer.token = IDENTIFIER;
yylval.buffer.data = strdup(yytext); yylval->buffer.data = strdup(yytext);
return IDENTIFIER; return IDENTIFIER;
} }
@@ -177,36 +186,17 @@ void do_package_statement(const char* importText)
// main parse function // main parse function
// ================================================ // ================================================
char const* g_currentFilename = NULL; extern ParseState *psGlobal;
char const* g_currentPackage = NULL; 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) if (!ps.OpenFileFromDisk()) {
{ fprintf(stderr, "aidl: unable to open file for read: %s\n", filename);
yyin = fopen(filename, "r"); return 1;
if (yyin) { }
char const* oldFilename = g_currentFilename;
char const* oldPackage = g_currentPackage;
g_currentFilename = strdup(filename);
g_error = 0; return ps.RunParser();
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;
}
} }

View File

@@ -4,14 +4,24 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
int yyerror(char* errstr); int yyerror(ParseState* ps, char* errstr)
int yylex(void); {
extern int yylineno; ps->ReportError(errstr);
return 1;
}
int yylex(lexer_type *, void *);
static int count_brackets(const char*); static int count_brackets(const char*);
#define YYLEX_PARAM ps->Scanner()
%} %}
%parse-param { ParseState* ps }
%pure-parser
%token IMPORT %token IMPORT
%token PACKAGE %token PACKAGE
%token IDENTIFIER %token IDENTIFIER
@@ -27,8 +37,8 @@ static int count_brackets(const char*);
%% %%
document: document:
document_items { g_callbacks->document($1.document_item); } document_items { ps->ProcessDocument(*$1.document_item); }
| headers document_items { g_callbacks->document($2.document_item); } | headers document_items { ps->ProcessDocument(*$2.document_item); }
; ;
headers: headers:
@@ -42,8 +52,8 @@ package:
; ;
imports: imports:
IMPORT { g_callbacks->import(&($1.buffer)); } IMPORT { ps->ProcessImport($1.buffer); }
| IMPORT imports { g_callbacks->import(&($1.buffer)); } | IMPORT imports { ps->ProcessImport($1.buffer); }
; ;
document_items: document_items:
@@ -66,7 +76,8 @@ document_items:
} }
} }
| document_items error { | 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); $2.buffer.lineno, $2.buffer.data);
$$ = $1; $$ = $1;
} }
@@ -84,19 +95,20 @@ parcelable_decl:
b->document_item.next = NULL; b->document_item.next = NULL;
b->keyword_token = $1.buffer; b->keyword_token = $1.buffer;
b->name = $2.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->semicolon_token = $3.buffer;
b->parcelable = true; b->parcelable = true;
$$.user_data = b; $$.user_data = b;
} }
| PARCELABLE ';' { | PARCELABLE ';' {
fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n", 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; $$.user_data = NULL;
} }
| PARCELABLE error ';' { | PARCELABLE error ';' {
fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n", 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; $$.user_data = NULL;
} }
; ;
@@ -128,7 +140,8 @@ interface_decl:
interface_header IDENTIFIER '{' interface_items '}' { interface_header IDENTIFIER '{' interface_items '}' {
interface_type* c = $1.interface_obj; interface_type* c = $1.interface_obj;
c->name = $2.buffer; 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->open_brace_token = $3.buffer;
c->interface_items = $4.interface_item; c->interface_items = $4.interface_item;
c->close_brace_token = $5.buffer; c->close_brace_token = $5.buffer;
@@ -136,12 +149,12 @@ interface_decl:
} }
| INTERFACE error '{' interface_items '}' { | INTERFACE error '{' interface_items '}' {
fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", 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; $$.document_item = NULL;
} }
| INTERFACE error '}' { | INTERFACE error '}' {
fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", 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; $$.document_item = NULL;
} }
@@ -163,7 +176,7 @@ interface_items:
} }
| interface_items error ';' { | interface_items error ';' {
fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n", fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n",
g_currentFilename, $3.buffer.lineno); ps->FileName().c_str(), $3.buffer.lineno);
$$ = $1; $$ = $1;
} }
; ;
@@ -259,7 +272,8 @@ arg_list:
} }
} }
| error { | 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; $$.arg = NULL;
} }
; ;
@@ -279,7 +293,8 @@ arg:
type: type:
IDENTIFIER { IDENTIFIER {
$$.type.type = $1.buffer; $$.type.type = $1.buffer;
init_buffer_type(&$$.type.array_token, yylineno); init_buffer_type(&$$.type.array_token,
$1.buffer.lineno);
$$.type.dimension = 0; $$.type.dimension = 0;
} }
| IDENTIFIER ARRAY { | IDENTIFIER ARRAY {
@@ -289,13 +304,14 @@ type:
} }
| GENERIC { | GENERIC {
$$.type.type = $1.buffer; $$.type.type = $1.buffer;
init_buffer_type(&$$.type.array_token, yylineno); init_buffer_type(&$$.type.array_token,
$1.buffer.lineno);
$$.type.dimension = 0; $$.type.dimension = 0;
} }
; ;
direction: direction:
{ init_buffer_type(&$$.buffer, yylineno); } { init_buffer_type(&$$.buffer, $$.buffer.lineno); }
| IN { $$.buffer = $1.buffer; } | IN { $$.buffer = $1.buffer; }
| OUT { $$.buffer = $1.buffer; } | OUT { $$.buffer = $1.buffer; }
| INOUT { $$.buffer = $1.buffer; } | INOUT { $$.buffer = $1.buffer; }
@@ -306,15 +322,6 @@ direction:
#include <ctype.h> #include <ctype.h>
#include <stdio.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) void init_buffer_type(buffer_type* buf, int lineno)
{ {
buf->lineno = lineno; buf->lineno = lineno;

8
tools/aidl/macros.h Normal file
View File

@@ -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_