/*--- C grammar with extensions for oxcc multipass compiler ---*/
/* 
	Norman D. Culver 
	Oxbow Software
	1323 S.E. 17th Street #662
	Ft. Lauderdale, FL 33316
	(305) 527-1663 Voice
	(305) 760-7584 Fax
	(305) 760-4679 Data
	ndc@fhd486.harvard.edu
	norman.culver@channel1.com
	70672,1257 Compuserve

	Copyright 1994 by Norman D. Culver, All Rights Reserved.
*/
/* 
	NOTE -- THE DEADWOOD IN THIS GRAMMAR IS THERE BECAUSE OF THE NEED TO
	RUNTIME INTERPRET AND/OR REGENERATE SOURCE FROM THE AST TREE

	NOTE -- PRODUCTIONS TERMINATED WITH $$; DO NOT MAKE AST NODES

	NOTE -- THE COMPILER COMPILER DERIVES ANY UNFORCED TERMINALS
*/

/* Force a couple of terminal symbol values */
#1	{meta-name}
#2	{typedef-name}

/*--- Operator Precedence. ---*/

  !(  '?'                      )
  !(  '||'                     )
  !(  '&&'                     )
  !(  '|'                      )
  !(  '^'                      )
  !(  '&'                      )
  !(  '=='  '!='               )
  !(  '<'   '>'   '<='   '>='  )
  !(  '<<'  '>>'               )
  !(  '+'   '-'                )
  !(  '*'   '/'   '%'          )
 
/*--- Phrase Structure Grammar ---*/

File
	-> [Input]... <eof>		;

Input
	-> OuterDecl	$$;
	-> FuncDef		$$;
	-> Directive	$$;
	-> OuterAnf		$$;
	-> SegStuff		$$;

SegStuff
	->	__segdef__ DeclID [SegList] ';'	;
	->	__seguse__ DeclID ';'			;

SegList
	->	ConstExp \','...	$$;

FuncDef
	-> [FrontSpec]		
		FuncDeclarator				
		[Attr]
		[InnerDecl]...
		FuncBody			;

NestedFuncDef
	-> FrontSpec		
		FuncDeclarator
		FuncBody			;

FuncDeclarator
	-> Declarator ;

FuncBody
	-> LB
		[DeclOrFunc]...
		[StmtC]...
	   BodyExit			 	;

BodyExit
	->	RB	;

OuterDecl
	-> [FrontSpec] [InitDeclarator \','...] ';' 
		=> classify (typedef 'InitDeclarator' 'TypeAgain' 'ParenDeclarator' 
			'DeclID' <identifier> {meta-name} {typedef-name})  ;

InnerDecl
	-> FrontSpec [InitDeclarator \','...] ';'
		=> classify (typedef 'InitDeclarator' 'TypeAgain' 'ParenDeclarator' 
			'DeclID' <identifier> {meta-name} {typedef-name}) ;

FrontSpec
	-> TypeDefs				$$;
	-> DeclarationSpec...	$$;

TypeDefs
	-> TypeDef TdElem...				$$;
	-> TypeDef Esu...					$$;
	-> TypeDef TypedefName				$$;
	-> TypeDef TypeAgain \','...		$$;

TypeDef
	-> typedef 		;

TdElem
	->	Type		$$;
	->	Qualifier	$$;

TypeAgain
	-> TypedefName InitRHS	;	/* reuse of computed typedef */
	-> Identifier InitRHS	;

DeclarationSpec
	-> TypeSpec				$$;
	-> StorageClassSpec		$$;
	-> Qualifier			$$;
	-> FuncTypeModifier		$$;

InitDeclarator
	-> Declarator [Attr]			;
	-> Declarator [Attr] InitRHS	;

Declarator
	-> [Pointer] DirectDeclarator 		$$;

Pointer
	-> '*' [Qualifier]...				;
	-> '*' [Qualifier]... Pointer		;

DirectDeclarator
	-> DeclID							$$;
	-> ParenDeclarator 					$$;
	-> DirectDeclarator ArrayDecl		$$;
	-> DirectDeclarator FuncParams		$$;

DeclID
	-> <identifier>	;
	-> {meta-name}	;

ParenDeclarator
	-> '(' Declarator ')' ;

ArrayDecl
	-> '[' [BinopC] ']' ;

FuncParams
	-> '(' [ParamList] ')' ;

ParamList
	-> Param \','...			;
	-> Param \','... ',' '...'	;
	-> '...' ;

Param
	-> SpecQual... InitDeclarator		;
	-> SpecQual... [NoNameDeclarator]	;
	-> Identifier ;

NoNameDeclarator
	-> Pointer							;
	-> [Pointer] DirectNoNameDeclarator	;

DirectNoNameDeclarator
	-> ParenNoNameDeclarator						$$;
	-> [DirectNoNameDeclarator] ArrayDecl			$$;
	-> [DirectNoNameDeclarator] FuncParams			$$;

ParenNoNameDeclarator
	-> '(' NoNameDeclarator ')' ;

InitRHS
	-> '=' Init	;

TypeSpec
	-> Specs		$$;
	-> DynType		$$;

DynType
	-> TypedefName	$$;
	-> TypeOf		$$;

Specs
	-> Type			$$;
	-> Esu			$$;

Esu
	-> EnumSpec		$$;
	-> StructSpec	$$;
	-> UnionSpec	$$;

Type
	-> void		;
	-> char		;
	-> short	;
	-> int		;
	-> long		;
	-> float	;
	-> double	;
	-> signed	;
	-> unsigned	;
	-> _segment	;
	-> __segment ;
	
FuncTypeModifier
	-> inline		;
	-> __inline__	;
	-> _cdecl		;
	-> __cdecl		;
	-> _pascal		;
	-> __pascal		;
	-> _fortran		;
	-> __fortran	;
	-> _interrupt	;
	-> __interrupt	;
	-> _ifunc		;
	-> _loadds		;
	-> __loadds		;
	-> _export		;
	-> __export		;
	-> _fastcall	;
	-> _saveregs	;
	-> __saveregs	;
	-> _syscall		;
	-> __syscall	;
	-> _stdcall		;
	-> __stdcall	;

Qualifier
	-> Based		;
	-> const		;
	-> volatile		;
	-> __volatile__	;
	-> _far			;
	-> __far		;
	-> _near		;
	-> __near		;
	-> _huge		;
	-> __huge		;
	-> _seg16		;
	-> __seg16		;
	-> _far16		;
	-> __far16		;
	-> register		;

Based
	-> _based '(' BaseExp ')'	$$;
	-> __based '(' BaseExp ')'	$$;
	
BaseExp
	->  CastExp	;
	-> _self	;
	-> __self	;

SpecQual
	-> TypeSpec		$$;
	-> Qualifier	$$;

TypedefName
	-> {meta-name} => require ({meta-name} {typedef-name}) ;

TypeOf
	-> typeof '(' CastExp ')'	;

StorageClassSpec
	-> extern		;
	-> static		;
	-> _ival		;
	-> auto			$$;

StructSpec	
	-> struct Tag									;
	-> struct '{' StructMembers... '}'				;
	-> struct Tag '{' StructMembers... '}'			;
	-> _Packed struct '{' StructMembers... '}'		;
	-> _Packed struct Tag '{' StructMembers... '}'	;

UnionSpec
	-> union Tag	;
	-> union '{' StructMembers... '}'		;
	-> union Tag '{' StructMembers... '}' 	;

StructMembers
	-> MemberSpec Members ';'	;

MemberSpec
	-> [Qualifier]... Type... 	$$;	/* restrictions should be removed */
	-> [Qualifier]... Esu		$$;
	-> [Qualifier]... DynType	$$;

Members
	-> SMember \','... $$;

SMember
	-> Member	$$;
	-> Bitfield	$$;

Member
	-> MemberDeclarator [Attr] ;

Bitfield
	-> FieldSize [Attr] ;
	-> MemberDeclarator FieldSize [Attr] ;

FieldSize
	-> ':' BinopC ;

MemberDeclarator
	-> [Pointer] DirectDeclarator	$$;

EnumSpec
	-> enum Tag										;
	-> enum '{' Enumerator \','... [','] '}'		;
	-> enum Tag '{' Enumerator \','... [','] '}'	;

Tag
	-> <identifier> ;
	-> {meta-name}	;

Enumerator
	-> EnumID			;
	-> EnumID EnumInit	;

EnumID
	-> <identifier> ;

EnumInit
	-> '=' BinopC ;

Init
	-> InitBlock	$$;
	-> InitExp		$$;

InitBlock
	-> '{' InitInner \','... [','] '}'	;

InitExp
	-> AssignExp		;

InitInner
	-> InitId InitBlock	$$;
	-> InitId InitExp	$$;
	-> InitBlock		$$;
	-> InitExp			$$;

InitId
	->	AryElem...	'='		;
	->	'.' InitLabel '='	;
	->  InitLabel ':' 		;

AryElem
	-> '[' InitElem ']'	$$;

InitElem
	->	Constant	;

InitLabel
	-> <identifier> ;
	-> {meta-name}	;

Attr
	-> Attr1 '(' Constant ')' ')' ')'	;
	-> Attr1 ')' ')'					;
	-> Attr1 '(' Identifier ')' ')' ')'	;
	-> Attr1 '(' Identifier ',' Constant ',' Constant ')' ')' ')'	;

Attr1
	-> __attribute__ '(' '(' AttrId	$$;

AttrId
	-> <identifier> ;
	-> {meta-name}	;

/* Statements */

StmtC
	-> ';'										;			/*0*/
	-> Exp ';'									;			/*1*/
	-> goto Identifier ';'						;			/*2*/
	-> continue ';'								;			/*3*/
	-> break ';'								;			/*4*/
	-> return [RetExp] ';'						;			/*5*/
	-> if '(' IfExp ')' IfStmtC					;			/*6*/
	-> if '(' IfExp ')' IfStmtC else ElseStmtC	;			/*7*/
	-> switch '(' SwExp ')' SwStmtC				;			/*8*/
	-> while '(' WhileExp ')' WhileStmtC		;			/*9*/
	-> do DoStmtC while '(' DoExp ')' ';'		;			/*10*/
	-> for '(' [ForInit] FS1 [ForCond] FS2 [ForPost] ')' ForStmtC	;	/*11*/
	-> BlockC									;			/*12*/
	-> Label ':' [StmtC]						;			/*13*/
	-> AsmStmt									;			/*14*/
	-> AnfBlock									;			/*15*/

FS1
	-> ';' ;
FS2
	-> ';' ;

RetExp
	-> Exp	;

IfExp
	-> Exp	;

SwExp
	-> Exp	;
	
WhileExp
	-> Exp	;

DoExp
	-> Exp	;

IfStmtC
	-> StmtC	;

ElseStmtC
	-> StmtC	;
	
DoStmtC
	-> StmtC	;

WhileStmtC
	-> StmtC	;
	
ForStmtC
	-> StmtC	;

SwStmtC
	-> StmtC	;

ForInit
	-> Exp	;

ForCond
	-> Exp	;

ForPost
	-> Exp	;

BlockC
	-> BlockEntry
		[Local]...
		[DeclOrFunc]...
		[StmtC]...
	   BlockExit			 	;

BlockEntry
	->	LB	;

BlockExit
	-> RB ;

DeclOrFunc
	-> InnerDecl		$$;
	-> NestedFuncDef	$$;

Local
	-> __label__ LocalID ':' $$;

LocalID
	-> <identifier>	;
	-> {meta-name}	;

Label
	->	<identifier> 					;
	->	{meta-name}						;
	->	default 						;
	->	case ConstExp 					;
	->	case ConstExp '...' ConstExp	;

OuterAnf
	->	AnfBlock [';']	;

AsmStmt
	-> GccAsmStmt		$$;
	-> MscAsmStmt		$$;

GccAsmStmt
	-> asm '(' [AsmString]... [GccIOspec] ')' ';' ;

AsmString
	-> String		;

GccIOspec
	-> CO [GccOutputList] CO [GccInputList] [ClobbersList]	$$;

GccOutputList
	-> GccOutput \','...	$$;

GccInputList
	-> GccInput \','...		$$;

ClobbersList
	-> CO Clobbers \','...	$$;

GccOutput
	-> String GccfixExp ;

GccInput
	-> String GccfixExp ;
	
Clobbers
	-> String			;

GccfixExp
	-> PostfixExp ;

MscAsmStmt
	-> _asm [AsmElem]...			;
	-> _asm '{' [AsmAll]... '}'		;
	-> _asm '(' AsmEmit... ')'		;
	
AsmAll
	-> AsmElem		$$;
	-> AsmUnixOp	$$;

AsmElem
	-> AsmOp		$$;
	-> AsmId		$$;
	-> Constant		$$;
	-> Type			$$;
	-> AsmEmit		$$;

AsmOp
	->	'+'		;
	->	'-'		;
	->	'*'		;
	->	'/'		;
	->	'.'		;
	->	'['		;
	->	']'		;
	->	','		;
	->	':'		;

AsmUnixOp
	->	'%'		;
	->	'$'		;
	->	'('		;
	->	')'		;

AsmId
	-> <identifier>		;
	-> {meta-name}		;

AsmEmit
	->	_emit Constant					;
	-> _emit '(' Constant \','... ')'	;

CO
	-> ':'	;

AnfBlock
	-> __anf__ '{' [AnfStmt]... '}'	;

AnfStmt
	->	AnfOp [AnfTarget] ';'	;
	->	Label ':' [AnfStmt]		;

AnfTarget
	->	AssignExp \','...		$$;

AnfOp
	->	DeclID		;

/* Expressions */

Exp
	-> AssignExp		;
	-> Exp ',' CommaExp	;

CommaExp
	-> AssignExp	;	/* needed for regen source */

ConstExp
	->BinopC		;

AssignExp
	-> BinopC					$$;
	-> AssignLHS '+='  AssignExp ;		/* 1 */
	-> AssignLHS '-='  AssignExp ;		/* 2 */
	-> AssignLHS '*='  AssignExp ;		/* 3 */
	-> AssignLHS '/='  AssignExp ;		/* 4 */
	-> AssignLHS '<<=' AssignExp ;		/* 5 */
	-> AssignLHS '>>=' AssignExp ;		/* 6 */
	-> AssignLHS '%='  AssignExp ;		/* 7 */
	-> AssignLHS '|='  AssignExp ;		/* 8 */
	-> AssignLHS '^='  AssignExp ;		/* 9 */
	-> AssignLHS '&='  AssignExp ;		/* 10 */
	-> AssignLHS '='   AssignExp ;		/* 11 */

AssignLHS
	-> CastExp ;

BinopC
	-> BaseOrCast			$$;
	-> BinopC '+'  BinopC	;	/* 1 */
	-> BinopC '-'  BinopC	;	/* 2 */
	-> BinopC '*'  BinopC	;	/* 3 */
	-> BinopC '/'  BinopC	;	/* 4 */
	-> BinopC '<<' BinopC	;	/* 5 */
	-> BinopC '>>' BinopC	;	/* 6 */
	-> BinopC '%'  BinopC	;	/* 7 */
	-> BinopC '|'  BinopC	;	/* 8 */
	-> BinopC '^'  BinopC	;	/* 9 */
	-> BinopC '&'  BinopC	;	/* 10 */
	-> BinopC '==' BinopC	;	/* 11 */
	-> BinopC '!=' BinopC	;	/* 12 */
	-> BinopC '<'  BinopC	;	/* 13 */
	-> BinopC '>'  BinopC	;	/* 14 */
	-> BinopC '<=' BinopC	;	/* 15 */
	-> BinopC '>=' BinopC	;	/* 16 */
	-> BinopC '||' BinopC	;	/* 17 */
	-> BinopC '&&' BinopC	;	/* 18 */
	-> BinopC '?'  BinopC ':' BinopC ;	/* 19 */
	-> BinopC '?'  ':' BinopC ;	/* 20 */

BaseOrCast
	->	BasedPtr	$$;
	->	CastExp		$$;

BasedPtr
	-> PostfixExp ':>' PostfixExp	;

CastExp
	-> UnaryExp				;
	-> '(' Cast ')' CastExp	;

Cast
	-> SpecQual... [NoNameDeclarator]	;

UnaryExp
	-> PostfixExp		$$;
	-> PreIncrement		$$;
	-> UnOpC  CastExp	$$;
	-> SizeOf			$$;
	-> AlignOf			$$;
	-> SegName			$$;

UnOpC
	-> '&'	;
	-> '*'	;
	-> '-'	;
	-> '~'	;
	-> '!'	;

PreIncrement
	-> '++' UnaryExp	;
	-> '--' UnaryExp	;

PostIncrement
	-> PostfixExp '++' ;
	-> PostfixExp '--' ;

SizeOf
	-> sizeof UnaryExp		;
	-> sizeof '(' Cast ')'	;

AlignOf
	-> __alignof__ UnaryExp		;
	-> __alignof__ '(' Cast ')'	;

SegName
	-> _segname '(' String ')'	;
	-> __segname '(' String ')'	;

PostfixExp
	-> PrimaryExp			$$;
	-> ArrayElement			$$;
	-> StructureElement		$$;
	-> PointerElement		$$;
	-> FunctionCall			$$;
	-> PostIncrement		$$;
   
ArrayElement
	-> ElemNameExp '[' ElemExp ']' ;

ElemNameExp
	-> Identifier		;
	-> ArrayElement 	;
	-> '(' Exp ')'		;
	-> PointerElement 	;
	-> StructureElement ;
	-> FunctionCall 	;
	-> String			;

ElemExp
	->	Exp ;

StructureElement
	-> PostfixExp '.' ElementName ;

PointerElement
	-> PostfixExp '->' ElementName ;	 

ElementName
	-> <identifier>	;
	-> {meta-name}	;

FunctionCall
	-> PostfixExp ArgList ;
	
ArgList
	-> '(' [Args] ')' ;

Args
	-> Arg \','... $$;

Arg
	-> AssignExp		;
	-> ArgId AssignExp	;

ArgId
	-> ArgLabel ':'		$$;

ArgLabel
	-> <identifier>		;
	-> {meta-name}		;	

PrimaryExp
	-> Constant					$$;
	-> Identifier				$$;
	-> '(' Exp ')'				$$;
	-> CompoundExp				$$;
	-> String...				$$;

CompoundExp
	-> '(' BlockC CompoundExit	;

CompoundExit
	->	')' ;

Identifier
	-> <identifier>  ;

Constant
	-> <int> ;			/*0*/
	-> <long> ;			/*1*/
	-> <ll>	;			/*2*/
	-> <uint> ;			/*3*/
	-> <ulong> ;		/*4*/
	-> <ull> ;			/*5*/

	-> <hex> ;			/*6*/
	-> <lhex> ;			/*7*/
	-> <llhex> ;		/*8*/
	-> <uhex> ;			/*9*/
	-> <ulhex> ;		/*10*/
	-> <ullhex> ;		/*11*/

	-> <octal> ;		/*12*/
	-> <loctal> ;		/*13*/
	-> <lloctal> ;		/*14*/
	-> <uoctal> ;		/*15*/
	-> <uloctal> ;		/*16*/
	-> <ulloctal> ;		/*17*/

	-> <float> ;		/*18*/
	-> <double> ;		/*19*/
	-> <ldouble> ;		/*20*/

	-> <literal> ;		/*21*/
	-> <wliteral> ;		/*22*/

String
	-> <string> ;
	-> <wstring> ;

LB	-> '{' $$;
RB	-> '}' $$;

Directive
	-> <notline> ;
	-> <linenum> ; /* this will never happen, linenum is expunged by doline */

/* Lexical grammar for c and c++ */

IGNORE 			:= spaces ;
				:= comment ;
				:= comment2 ;

"eof"			:= (0 | 26 | 255) ;


"linenum"		:= line restofline => doline ;
line			:= '#line' ;

"notline"		:= notline restofline ;
notline			:= '#' ;

"identifier"	:= ident => dyntoken ;
ident			:= letter ;
				:= ident letter ;
				:= ident digit ;

"int"			:= digits ;

"long"			:= digits 'l' ;
				:= digits 'L' ;

"uint"			:= digits 'U' ;
				:= digits 'u' ;

"ulong"			:= digits 'LU' ;
				:= digits 'UL' ;
				:= digits 'ul' ;
				:= digits 'lu' ;
				:= digits 'lU' ;
				:= digits 'Lu' ;
				:= digits 'uL' ;
				:= digits 'Ul' ;

"ll"			:= digits 'LL' ;
				:= digits 'll' ;

"ull"			:= digits 'ull' ;
				:= digits 'llu' ;
				:= digits 'ULL' ;
				:= digits 'LLU' ;
				
digits			:= digit ;
				:= digits digit ;

"hex"			:= hexx ;

"lhex"			:= hexx 'l' ;
				:= hexx 'L' ;

"uhex"			:= hexx 'U' ;
				:= hexx 'u' ;

"ulhex"			:= hexx 'LU' ;
				:= hexx 'UL' ;
				:= hexx 'ul' ;
				:= hexx 'lu' ;
				:= hexx 'lU' ;
				:= hexx 'Lu' ;
				:= hexx 'uL' ;
				:= hexx 'Ul' ;

"llhex"			:= hexx 'LL' ;
				:= hexx 'll' ;

"ullhex"		:= hexx 'ull' ;
				:= hexx 'llu' ;
				:= hexx 'ULL' ;
				:= hexx 'LLU' ;


hexx			:= '0x' hexdigit ;
				:= '0X' hexdigit ;
				:= hexx hexdigit ;

hexdigit		:= '0'/'9' ;
				:= a/f ;
				:= A/F ;

"octal"			:= oct ;

"loctal"		:= oct 'l' ;
				:= oct 'L' ;

"uoctal"		:= oct 'U' ;
				:= oct 'u' ;

"uloctal"		:= oct 'LU' ;
				:= oct 'UL' ;
				:= oct 'ul' ;
				:= oct 'lu' ;
				:= oct 'lU' ;
				:= oct 'Lu' ;
				:= oct 'uL' ;
				:= oct 'Ul' ;

"lloctal"		:= oct 'LL' ;
				:= oct 'll' ;

"ulloctal"		:= oct 'ull' ;
				:= oct 'llu' ;
				:= oct 'ULL' ;
				:= oct 'LLU' ;
				
oct				:= '0' octdigit ;
				:= oct octdigit ;
octdigit		:= '0'/'7' ;

"double"		:= flt ;
"float"			:= flt 'f' ;
				:= flt 'F' ;
"ldouble"		:= flt 'l' ;
				:= flt 'L' ;

flt				:= rational ;
				:= digits exp ;
				:= rational exp ;

rational		:= digits '.' ;
				:= '.' digits ;
				:= digits '.' digits ;
exp				:= 'e' digits  ;
				:= 'E' digits ;
				:= 'e-' digits ;
				:= 'E-' digits ;
				:= 'e+' digits ;
				:= 'E+' digits ;

"literal"		:= lit ;
"wliteral"		:= 'L' lit ;
lit				:= qt lchar... qt ;
lchar			:= ch ;
				:= qt qt ;
				:= '"' ;
				:= '*' ;
				:= '/' ;
				:= escapes ; 

"string"		:= str ;
"wstring"		:= 'L' str ;

str				:= '"' [schar...] '"' ;
schar			:= ch ;
				:= qt ;
				:= '*' ;
				:= '/' ;
				:= escapes ;

escapes			:= bs qt ;
				:= bs ch ;
				:= bs '"' ;
				:= bs '*' ;
				:= bs '/' ;
				:= bs bs ;
				:= bs lf ;

spaces    		:= space... ;
space     		:= ( 9 | 10 | 12 | 32 ) ;

comment   		:= '/*' end '/' ;
end       		:= endinstar ;
          		:= end noslash endinstar	;
endinstar 		:= stars ;
          		:= notstar stars ;
stars     		:= '*'... ;
notstar   		:= nostar	;
          		:= notstar nostar	;
noslash   		:= (ch | notsl) ;
notsl			:= (10 | 12 | 39 | '"' | '*' | 92) ;
nostar    		:= (ch | notst)	;
notst			:= (10 | 12 | 39 | '"' | '/' | 92) ;


comment2		:= '//' restofline ;

restofline		:= [(ch | noteol)]... ;
noteol			:= (39 | '"' | '/' | '*' | 92) ;

ch				:= 1/254 ^(10 12 26 39 '"' '/' '*' 92) ;

letter			:= a/z ;
				:= A/Z ;
				:= '_' ;

digit			:= '0'/'9' ;

bs			:= 92 ;
qt			:= 39 ;
lf			:= 10 ;
/*--- End. ---*/

