Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9941dcc7 authored by Casey Dahlin's avatar Casey Dahlin
Browse files

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: default avatarCasey Dahlin <sadmac@google.com>
parent 596fd38a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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;
+78 −12
Original line number Diff line number Diff line
#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;
}
+30 −6
Original line number Diff line number Diff line
#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
+26 −36
Original line number Diff line number Diff line
@@ -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)
{
    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;
int parse_aidl(char const *filename) {
  ParseState ps(filename);
  psGlobal = &ps;

        return rv;
    } else {
  if (!ps.OpenFileFromDisk()) {
    fprintf(stderr, "aidl: unable to open file for read: %s\n", filename);
    return 1;
  }
}

  return ps.RunParser();
}
+35 −28
Original line number Diff line number Diff line
@@ -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;
Loading