RSS Git Download  Clone
Raw Blame History
/*******************************************************************************
 *	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
}