/******************************************************************************* * 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 }