/*******************************************************************************
* Gram.y BEAM IDL Lexical analyser
* T.Barnaby, BEAM Ltd, 2/5/02
*******************************************************************************
*/
%{
#include <stdio.h>
#include <stdlib.h>
#include <bidl.h>
#include <Node.h>
#include <BString.h>
#define DOECHO 0
#define DEBUG 0
int yylex();
void yyerror(char *s);
int fflag;
BString tfunc;
int tflag;
BStringList typeNames;
%}
%token MODULE INTERFACE
%token IDENTIFIER
%token CONSTANT
%token STRING_LITERAL
%token TYPEDEF
%token ERROR BOOL INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 STRING DOUBLE
%token TYPE_NAME
%token LIST ARRAY IN INREF OUT
%token STRUCT ENUM
%token CLASS ID DATE DATETIME
%token TYPEDOMAIN APIVERSION
%token COMMENT
%start start
%%
identifier
: IDENTIFIER
{
dprintf("identifier: %s\n", $1->name().retStr());
$$ = new Node(Node::TIDENT, $1->name());
}
;
type
: ERROR
{ $$ = new Node(Node::TTYPE, $1->name()); }
| BOOL
{ $$ = new Node(Node::TTYPE, $1->name()); }
| INT8
{ $$ = new Node(Node::TTYPE, $1->name()); }
| UINT8
{ $$ = new Node(Node::TTYPE, $1->name()); }
| INT16
{ $$ = new Node(Node::TTYPE, $1->name()); }
| UINT16
{ $$ = new Node(Node::TTYPE, $1->name()); }
| INT32
{ $$ = new Node(Node::TTYPE, $1->name()); }
| UINT32
{ $$ = new Node(Node::TTYPE, $1->name()); }
| INT64
{ $$ = new Node(Node::TTYPE, $1->name()); }
| UINT64
{ $$ = new Node(Node::TTYPE, $1->name()); }
| DOUBLE
{ $$ = new Node(Node::TTYPE, $1->name()); }
| STRING
{ $$ = new Node(Node::TTYPE, $1->name()); }
| ID
{ $$ = new Node(Node::TTYPE, $1->name()); }
| DATE
{ $$ = new Node(Node::TTYPE, $1->name()); }
| DATETIME
{ $$ = new Node(Node::TTYPE, $1->name()); }
| STRUCT identifier
{ $$ = new Node(Node::TTYPE, $2->name()); }
| CLASS identifier
{ $$ = new Node(Node::TTYPE, $2->name()); }
| LIST '<' type '>'
{ $$ = new NodeOp1(Node::TTYPELIST, $1->name(), $3); }
| ARRAY '<' type '>'
{ $$ = new NodeOp1(Node::TTYPEARRAY, $1->name(), $3); }
| TYPE_NAME
{ $$ = new Node(Node::TTYPE, $1->name()); }
;
structItem
: type identifier ';'
{ $$ = new NodeOp2(Node::TSTRUCTITEM, "structItem", $1, $2); }
| type identifier ';' COMMENT
{ $$ = new NodeOp2(Node::TSTRUCTITEM, "structItem", $1, $2); $$->append($4) }
;
structItemList
: structItem
{ $$ = new NodeOp1(Node::TLIST, "structItemList", $1); }
| structItemList structItem
{ $$ = $1->append($2); }
|
{ $$ = new Node(Node::TLIST, "structItemList"); }
;
enumerator
: identifier
;
enumeratorList
: enumerator
{ $$ = new NodeOp1(Node::TLIST, "enumeratorList", $1); }
| enumeratorList ',' enumerator
{ $$ = $1->append($3); }
;
parameter
: IN type identifier
{ $$ = new NodeOp3(Node::TFUNCPARAM, "param", new Node(Node::TDIR, "in"), $2, $3); }
| INREF type identifier
{ $$ = new NodeOp3(Node::TFUNCPARAM, "param", new Node(Node::TDIR, "inref"), $2, $3); }
| OUT type identifier
{ $$ = new NodeOp3(Node::TFUNCPARAM, "param", new Node(Node::TDIR, "out"), $2, $3); }
;
parameterList
: parameter
{ $$ = new NodeOp1(Node::TLIST, "parameterList", $1); }
| parameterList ',' parameter
{ $$ = $1->append($3); }
;
derived
: ':' TYPE_NAME
{
$$ = $2;
}
;
declareType
: STRUCT identifier '{' structItemList '}'
{
// printf("AddType: %s\n", $2->name().retStr());
gtypelist.append(Type($2->name(), $4));
$$ = new NodeOp2(Node::TSTRUCT, $2->name(), $4, 0);
}
| STRUCT identifier derived '{' structItemList '}'
{
// printf("AddType: %s\n", $2->name().retStr());
gtypelist.append(Type($2->name(), $5,gtypelist.search($3->name())));
$$ = new NodeOp2(Node::TSTRUCT, $2->name(), $5, $3);
}
| CLASS identifier '{' structItemList '}'
{
// printf("AddType: %s\n", $2->name().retStr());
gtypelist.append(Type($2->name(), $4));
$$ = new NodeOp2(Node::TSTRUCT, $2->name(), $4, 0);
}
| CLASS identifier derived '{' structItemList '}'
{
// printf("AddType: %s\n", $2->name().retStr());
gtypelist.append(Type($2->name(), $5, gtypelist.search($3->name())));
$$ = new NodeOp2(Node::TSTRUCT, $2->name(), $5, $3);
}
| type identifier '(' parameterList ')'
{ $$ = new NodeOp2(Node::TFUNC, $2->name(), $1, $4); }
| type identifier '(' ')'
{ $$ = new NodeOp2(Node::TFUNC, $2->name(), $1, new Node(Node::TLIST, "parameterList")); }
| ENUM '{' enumeratorList '}'
{ $$ = new NodeOp2(Node::TENUM, "enum", 0, $3); }
| ENUM identifier '{' enumeratorList '}'
{ $$ = new NodeOp2(Node::TENUM, "enum", $2, $4); }
;
/*******************************************************************************
* Declarations
*******************************************************************************
*/
declaration
: declareType ';'
| declareType ';' COMMENT
{
$$ = $1->append($3);
}
| COMMENT
| INTERFACE identifier '{' declarationList '}' ';'
{
$$ = new NodeOp1(Node::TINTERFACE, $2->name(), $4);
}
| TYPEDOMAIN '=' CONSTANT ';'
{
$$ = new Node(Node::TTYPEDOMAIN, $3->name());
}
| APIVERSION '=' CONSTANT ';'
{
$$ = new Node(Node::TAPIVERSION, $3->name());
}
;
declarationList
: declaration
{ $$ = new NodeOp1(Node::TLIST, "declarationList", $1); }
| declarationList declaration
{ $$ = $1->append($2); }
;
module
: MODULE identifier '{' declarationList '}' ';'
{
$$ = new NodeOp1(Node::TMODULE, $2->name(), $4);
}
| COMMENT
;
file
: module
{ $$ = new NodeOp1(Node::TLIST, "fileList", $1); }
| file module
{ $$ = $1->append($2); }
;
start
: file
{ result = $1; }
;
%%
extern char yytext[];
extern int column, line;
void yyerror(char *s){
fflush(stdout);
#if DOECHO
printf("\nLine: %d\n\r%*s\n%*s\n", line, column, "^", column, s);
#else
printf("Syntax Error: File(%s) Line(%d) Col(%d)\n", fileName.retStr(), line, column);
#endif
}