* commit '6929b5fab007281d3c35deec905feb8fdc506a31': First pass on reentrant C++-ish parser
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
8
tools/aidl/macros.h
Normal 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_
|
||||||
Reference in New Issue
Block a user