blob: 9b40d28ad5988a79278f38272ef8a7e3186cfcf5 [file] [log] [blame]
%{
#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 IDVALUE
%token GENERIC
%token ARRAY
%token PARCELABLE
%token INTERFACE
%token FLATTENABLE
%token RPC
%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.user_data; }
| interface_decl { $$.document_item = (document_item_type*)$1.interface_item; }
;
parcelable_decl:
PARCELABLE IDENTIFIER ';' {
user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
b->document_item.item_type = USER_DATA_TYPE;
b->document_item.next = NULL;
b->keyword_token = $1.buffer;
b->name = $2.buffer;
b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
b->semicolon_token = $3.buffer;
b->flattening_methods = PARCELABLE_DATA;
$$.user_data = b;
}
| PARCELABLE ';' {
fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
g_currentFilename, $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);
$$.user_data = NULL;
}
| FLATTENABLE IDENTIFIER ';' {
user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
b->document_item.item_type = USER_DATA_TYPE;
b->document_item.next = NULL;
b->keyword_token = $1.buffer;
b->name = $2.buffer;
b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
b->semicolon_token = $3.buffer;
b->flattening_methods = PARCELABLE_DATA | RPC_DATA;
$$.user_data = b;
}
| FLATTENABLE ';' {
fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name.\n",
g_currentFilename, $1.buffer.lineno);
$$.user_data = NULL;
}
| FLATTENABLE error ';' {
fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name, saw \"%s\".\n",
g_currentFilename, $2.buffer.lineno, $2.buffer.data);
$$.user_data = NULL;
}
;
interface_header:
INTERFACE {
interface_type* c = (interface_type*)malloc(sizeof(interface_type));
c->document_item.item_type = INTERFACE_TYPE_BINDER;
c->document_item.next = NULL;
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->document_item.item_type = INTERFACE_TYPE_BINDER;
c->document_item.next = NULL;
c->interface_token = $2.buffer;
c->oneway = true;
c->oneway_token = $1.buffer;
c->comments_token = &c->oneway_token;
$$.interface_obj = c;
}
| RPC {
interface_type* c = (interface_type*)malloc(sizeof(interface_type));
c->document_item.item_type = INTERFACE_TYPE_RPC;
c->document_item.next = NULL;
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;
}
;
interface_keywords:
INTERFACE
| RPC
;
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->open_brace_token = $3.buffer;
c->interface_items = $4.interface_item;
c->close_brace_token = $5.buffer;
$$.interface_obj = c;
}
| interface_keywords 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_keywords 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->oneway = false;
method->type = $1.type;
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->hasId = false;
memset(&method->equals_token, 0, sizeof(buffer_type));
memset(&method->id, 0, sizeof(buffer_type));
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->hasId = false;
memset(&method->equals_token, 0, sizeof(buffer_type));
memset(&method->id, 0, sizeof(buffer_type));
method->semicolon_token = $7.buffer;
method->comments_token = &method->oneway_token;
$$.method = method;
}
| type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
method_type *method = (method_type*)malloc(sizeof(method_type));
method->interface_item.item_type = METHOD_TYPE;
method->interface_item.next = NULL;
method->oneway = false;
memset(&method->oneway_token, 0, sizeof(buffer_type));
method->type = $1.type;
method->name = $2.buffer;
method->open_paren_token = $3.buffer;
method->args = $4.arg;
method->close_paren_token = $5.buffer;
method->hasId = true;
method->equals_token = $6.buffer;
method->id = $7.buffer;
method->semicolon_token = $8.buffer;
method->comments_token = &method->type.type;
$$.method = method;
}
| ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
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->hasId = true;
method->equals_token = $7.buffer;
method->id = $8.buffer;
method->semicolon_token = $9.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;
}