289 lines
15 KiB
Plaintext
289 lines
15 KiB
Plaintext
%{
|
|
#include "aidl_language.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
int yyerror(char* errstr);
|
|
int yylex(void);
|
|
extern int yylineno;
|
|
|
|
static int count_brackets(const char*);
|
|
|
|
%}
|
|
|
|
%token IMPORT
|
|
%token PACKAGE
|
|
%token IDENTIFIER
|
|
%token GENERIC
|
|
%token ARRAY
|
|
%token PARCELABLE
|
|
%token INTERFACE
|
|
%token IN
|
|
%token OUT
|
|
%token INOUT
|
|
%token ONEWAY
|
|
|
|
%%
|
|
document:
|
|
document_items { g_callbacks->document($1.document_item); }
|
|
| headers document_items { g_callbacks->document($2.document_item); }
|
|
;
|
|
|
|
headers:
|
|
package { }
|
|
| imports { }
|
|
| package imports { }
|
|
;
|
|
|
|
package:
|
|
PACKAGE { }
|
|
;
|
|
|
|
imports:
|
|
IMPORT { g_callbacks->import(&($1.buffer)); }
|
|
| IMPORT imports { g_callbacks->import(&($1.buffer)); }
|
|
;
|
|
|
|
document_items:
|
|
{ $$.document_item = NULL; }
|
|
| document_items declaration {
|
|
if ($2.document_item == NULL) {
|
|
// error cases only
|
|
$$ = $1;
|
|
} else {
|
|
document_item_type* p = $1.document_item;
|
|
while (p && p->next) {
|
|
p=p->next;
|
|
}
|
|
if (p) {
|
|
p->next = (document_item_type*)$2.document_item;
|
|
$$ = $1;
|
|
} else {
|
|
$$.document_item = (document_item_type*)$2.document_item;
|
|
}
|
|
}
|
|
}
|
|
| document_items error {
|
|
fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", g_currentFilename,
|
|
$2.buffer.lineno, $2.buffer.data);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
declaration:
|
|
parcelable_decl { $$.document_item = (document_item_type*)$1.parcelable; }
|
|
| interface_decl { $$.document_item = (document_item_type*)$1.interface_item; }
|
|
;
|
|
|
|
parcelable_decl:
|
|
PARCELABLE IDENTIFIER ';' {
|
|
parcelable_type* b = (parcelable_type*)malloc(sizeof(parcelable_type));
|
|
b->document_item.item_type = PARCELABLE_TYPE;
|
|
b->document_item.next = NULL;
|
|
b->parcelable_token = $1.buffer;
|
|
b->name = $2.buffer;
|
|
b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
|
|
b->semicolon_token = $3.buffer;
|
|
$$.parcelable = b;
|
|
}
|
|
| PARCELABLE ';' {
|
|
fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
|
|
g_currentFilename, $1.buffer.lineno);
|
|
$$.parcelable = 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);
|
|
$$.parcelable = NULL;
|
|
}
|
|
;
|
|
|
|
interface_header:
|
|
INTERFACE {
|
|
interface_type* c = (interface_type*)malloc(sizeof(interface_type));
|
|
c->interface_token = $1.buffer;
|
|
c->oneway = false;
|
|
memset(&c->oneway_token, 0, sizeof(buffer_type));
|
|
c->comments_token = &c->interface_token;
|
|
$$.interface_obj = c;
|
|
}
|
|
| ONEWAY INTERFACE {
|
|
interface_type* c = (interface_type*)malloc(sizeof(interface_type));
|
|
c->interface_token = $2.buffer;
|
|
c->oneway = true;
|
|
c->oneway_token = $1.buffer;
|
|
c->comments_token = &c->oneway_token;
|
|
$$.interface_obj = c;
|
|
}
|
|
;
|
|
|
|
interface_decl:
|
|
interface_header IDENTIFIER '{' interface_items '}' {
|
|
interface_type* c = $1.interface_obj;
|
|
c->document_item.item_type = INTERFACE_TYPE;
|
|
c->document_item.next = NULL;
|
|
c->name = $2.buffer;
|
|
c->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
|
|
c->open_brace_token = $3.buffer;
|
|
c->interface_items = $4.interface_item;
|
|
c->close_brace_token = $5.buffer;
|
|
$$.interface_obj = c;
|
|
}
|
|
| 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);
|
|
$$.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);
|
|
$$.document_item = NULL;
|
|
}
|
|
|
|
;
|
|
|
|
interface_items:
|
|
{ $$.interface_item = NULL; }
|
|
| interface_items method_decl {
|
|
interface_item_type* p=$1.interface_item;
|
|
while (p && p->next) {
|
|
p=p->next;
|
|
}
|
|
if (p) {
|
|
p->next = (interface_item_type*)$2.method;
|
|
$$ = $1;
|
|
} else {
|
|
$$.interface_item = (interface_item_type*)$2.method;
|
|
}
|
|
}
|
|
| interface_items error ';' {
|
|
fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n",
|
|
g_currentFilename, $3.buffer.lineno);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
method_decl:
|
|
type IDENTIFIER '(' arg_list ')' ';' {
|
|
method_type *method = (method_type*)malloc(sizeof(method_type));
|
|
method->interface_item.item_type = METHOD_TYPE;
|
|
method->interface_item.next = NULL;
|
|
method->type = $1.type;
|
|
method->oneway = false;
|
|
memset(&method->oneway_token, 0, sizeof(buffer_type));
|
|
method->name = $2.buffer;
|
|
method->open_paren_token = $3.buffer;
|
|
method->args = $4.arg;
|
|
method->close_paren_token = $5.buffer;
|
|
method->semicolon_token = $6.buffer;
|
|
method->comments_token = &method->type.type;
|
|
$$.method = method;
|
|
}
|
|
| ONEWAY type IDENTIFIER '(' arg_list ')' ';' {
|
|
method_type *method = (method_type*)malloc(sizeof(method_type));
|
|
method->interface_item.item_type = METHOD_TYPE;
|
|
method->interface_item.next = NULL;
|
|
method->oneway = true;
|
|
method->oneway_token = $1.buffer;
|
|
method->type = $2.type;
|
|
method->name = $3.buffer;
|
|
method->open_paren_token = $4.buffer;
|
|
method->args = $5.arg;
|
|
method->close_paren_token = $6.buffer;
|
|
method->semicolon_token = $7.buffer;
|
|
method->comments_token = &method->oneway_token;
|
|
$$.method = method;
|
|
}
|
|
;
|
|
|
|
arg_list:
|
|
{ $$.arg = NULL; }
|
|
| arg { $$ = $1; }
|
|
| arg_list ',' arg {
|
|
if ($$.arg != NULL) {
|
|
// only NULL on error
|
|
$$ = $1;
|
|
arg_type *p = $1.arg;
|
|
while (p && p->next) {
|
|
p=p->next;
|
|
}
|
|
$3.arg->comma_token = $2.buffer;
|
|
p->next = $3.arg;
|
|
}
|
|
}
|
|
| error {
|
|
fprintf(stderr, "%s:%d: syntax error in parameter list\n", g_currentFilename, $1.buffer.lineno);
|
|
$$.arg = NULL;
|
|
}
|
|
;
|
|
|
|
arg:
|
|
direction type IDENTIFIER {
|
|
arg_type* arg = (arg_type*)malloc(sizeof(arg_type));
|
|
memset(&arg->comma_token, 0, sizeof(buffer_type));
|
|
arg->direction = $1.buffer;
|
|
arg->type = $2.type;
|
|
arg->name = $3.buffer;
|
|
arg->next = NULL;
|
|
$$.arg = arg;
|
|
}
|
|
;
|
|
|
|
type:
|
|
IDENTIFIER {
|
|
$$.type.type = $1.buffer;
|
|
init_buffer_type(&$$.type.array_token, yylineno);
|
|
$$.type.dimension = 0;
|
|
}
|
|
| IDENTIFIER ARRAY {
|
|
$$.type.type = $1.buffer;
|
|
$$.type.array_token = $2.buffer;
|
|
$$.type.dimension = count_brackets($2.buffer.data);
|
|
}
|
|
| GENERIC {
|
|
$$.type.type = $1.buffer;
|
|
init_buffer_type(&$$.type.array_token, yylineno);
|
|
$$.type.dimension = 0;
|
|
}
|
|
;
|
|
|
|
direction:
|
|
{ init_buffer_type(&$$.buffer, yylineno); }
|
|
| IN { $$.buffer = $1.buffer; }
|
|
| OUT { $$.buffer = $1.buffer; }
|
|
| INOUT { $$.buffer = $1.buffer; }
|
|
;
|
|
|
|
%%
|
|
|
|
#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;
|
|
buf->token = 0;
|
|
buf->data = NULL;
|
|
buf->extra = NULL;
|
|
}
|
|
|
|
static int count_brackets(const char* s)
|
|
{
|
|
int n=0;
|
|
while (*s) {
|
|
if (*s == '[') n++;
|
|
s++;
|
|
}
|
|
return n;
|
|
}
|