This was the start for Harbour
https://groups.google.com/forum/#!searchin/comp.lang.clipper/cliparse%7Csort:relevance/comp.lang.clipper/rcvDzVQ3xcY/ZCsG81PxEV0J
clipper.y (yacc rules)
%{
// Clipper yacc rules.
// Developed by Antonio Linares (<!-- e --><a href="mailto:alin...@fivetech.com">alin...@fivetech.com</a><!-- e -->, <!-- m --><a class="postlink" href="http://www.fivetech.com">http://www.fivetech.com</a><!-- m -->)
// A first step for a GNU Clipper
// Build 1: March 99
// Usage: byacc.exe -d -v clipper.y
// You may find byacc.exe at <!-- m --><a class="postlink" href="ftp://ftp.iag.net/pub/clipper/utils/byacc19.zip">ftp://ftp.iag.net/pub/clipper/utils/byacc19.zip</a><!-- m -->
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
extern FILE * yyin;
void yyerror( char * );
int yylex( void );
%}
%union
{
char * string;
int number;
float fNumber;
void * pVoid;
};
%token FUNCTION IDENTIFIER RETURN NIL NUMBER INASSIGN
%token LOCAL STATIC IF ELSE END ENDIF LITERAL TRUE FALSE
%token INCLUDE EXTERN INIT EXIT AND OR NOT PUBLIC EQ NE1 NE2
%token INC DEC ALIAS DOCASE CASE OTHERWISE ENDCASE
%token WHILE EXIT LOOP END FOR NEXT TO DOWNTO LE GE
%token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ
%nonassoc NOT
%left AND OR
%left INASSIGN '='
%left PLUSEQ MINUSEQ
%left MULTEQ DIVEQ POWER
%left EXPEQ MODEQ
%left '+' '-' EQ NE1 NE2 INC DEC ALIAS
%left '*' '/' '<' '>' LE GE
%right '\n' ';'
%type <string> IDENTIFIER
%type <fNumber> NUMBER
%%
Main : Source { printf( "syntax ok\n" ); }
;
Source : Crlf
| Include
| Extern
| StaticsDef
| Function
| Source Crlf
| Source Include
| Source Extern
| Source StaticsDef
| Source Function
;
Include : NE1 INCLUDE LITERAL
;
Extern : EXTERN ExtList
;
ExtList : IDENTIFIER
| ExtList ',' IDENTIFIER
;
StaticsDef : STATIC VarList
;
Function : FunHead Statements
| FunHead VarDefs Statements
| FunScope FunHead Statements
| FunScope FunHead VarDefs Statements
;
FunHead : FUNCTION IDENTIFIER Crlf
| FUNCTION IDENTIFIER '(' ')' Crlf
| FUNCTION IDENTIFIER '(' ParamList ')' Crlf
;
ParamList : IDENTIFIER
| ParamList ',' IDENTIFIER
;
Statements : Statement
| Statements Statement
;
Statement : ExecFlow Crlf
| FunCall Crlf
| ObjectMethod Crlf
| ObjectData INC Crlf
| INC ObjectData Crlf
| Variable Crlf
| VarAssign Crlf
| RETURN Crlf
| RETURN Expression Crlf
| PUBLIC VarList Crlf
;
FunScope : INIT
| EXIT
| STATIC
;
FunCall : IDENTIFIER '(' ')'
| IDENTIFIER '(' ExpList ')'
;
ObjectMethod : IDENTIFIER ':' IDENTIFIER '(' ')'
| IDENTIFIER ':' IDENTIFIER '(' ExpList ')'
| FunCall ':' IDENTIFIER '(' ')'
| FunCall ':' IDENTIFIER '(' ExpList ')'
| ObjectMethod ':' IDENTIFIER '(' ')'
| ObjectMethod ':' IDENTIFIER '(' ExpList ')'
| ObjectData ':' IDENTIFIER '(' ')'
| ObjectData ':' IDENTIFIER '(' ExpList ')'
;
Expression : NIL
| NUMBER
| LITERAL
| Variable
| Logical
| Operators
| FunCall
| Array
| CodeBlock
| ObjectMethod
| '&' '(' Expression ')'
| AliasExp
| '(' ExpList ')'
;
AliasExp : IDENTIFIER ALIAS IDENTIFIER
| IDENTIFIER ALIAS '(' FunCall ')'
;
Variable : IDENTIFIER
| IDENTIFIER INC
| INC IDENTIFIER
| IDENTIFIER DEC
| DEC IDENTIFIER
| ObjectData
| ObjectData INC
| INC ObjectData
| ObjectData DEC
| DEC ObjectData
;
VarAssign : Variable '=' Expression
| Variable INASSIGN Expression
| Variable PLUSEQ Expression
| Variable MINUSEQ Expression
| Variable MULTEQ Expression
| Variable DIVEQ Expression
| Variable EXPEQ Expression
;
Operators : Expression '+' Expression
| Expression '-' Expression
| Expression '*' Expression
| Expression '/' Expression
| Expression '<' Expression
| Expression '>' Expression
| Expression LE Expression
| Expression GE Expression
| Expression AND Expression
| Expression OR Expression
| Expression EQ Expression
| Expression NE1 Expression
| Expression NE2 Expression
| Expression POWER Expression
| NOT Expression
| VarAssign
;
ObjectData : IDENTIFIER ':' IDENTIFIER
| FunCall ':' IDENTIFIER
| ObjectData ':' IDENTIFIER
| ObjectMethod ':' IDENTIFIER
;
Logical : TRUE
| FALSE
;
Array : '{' '}'
| '{' ExpList '}'
;
CodeBlock : '{' '|' '|' ExpList '}'
| '{' '|' ParamList '|' ExpList '}'
;
ExpList : ','
| Expression
| ExpList ','
| ExpList ',' Expression
;
VarDefs : VarScope VarList Crlf
| VarDefs VarScope VarList Crlf
;
VarScope : LOCAL
| STATIC
;
VarList : VarDef
| VarList ',' VarDef
;
VarDef : IDENTIFIER
| IDENTIFIER INASSIGN Expression
;
ExecFlow : IfEndif
| DoCase
| DoWhile
| ForNext
;
IfEndif : IfBegin EndIf
| IfBegin IfElse EndIf
;
IfBegin : IF Expression Crlf
| IF Expression Crlf Statements
;
IfElse : ELSE Crlf
| ELSE Crlf Statements
;
EndIf : ENDIF
| END
;
DoCase : DOCASE Crlf
Cases
ENDCASE
| DOCASE Crlf
Otherwise
ENDCASE
| DOCASE Crlf
Cases
Otherwise
ENDCASE
;
Cases : CASE Expression Crlf
| CASE Expression Crlf Statements
| Cases CASE Expression Crlf
| Cases CASE Expression Crlf Statements
;
Otherwise : OTHERWISE Crlf
| OTHERWISE Crlf Statements
;
DoWhile : WHILE Expression Crlf
WhileStatements
END
;
WhileStatements : Statement
| EXIT Crlf
| LOOP Crlf
| WhileStatements Statement
| WhileStatements EXIT Crlf
| WhileStatements LOOP Crlf
;
ForNext : FOR IDENTIFIER ForAssign Expression UpTo Expression Crlf
ForStatements
;
ForAssign : '='
| INASSIGN
;
UpTo : TO
| DOWNTO
;
ForStatements : Statements NEXT
| NEXT
;
Crlf : '\n'
| ';'
| '\n' Crlf
| ';' Crlf
;
%%
void yyerror( char * s )
{
printf( s );
exit( 1 );
}
int main( int argc, char * argv[] )
{
printf( "Clipper parser\n" );
printf( "build 1 March 99\n\n" );
if( argc > 1 )
{
yyin = fopen( argv[ 1 ], "r" );
yyparse();
}
else
printf( "Use: cliparse.exe <file.prg>\n" );
return 0;
}
///------------ EOF -------------------------------
Clipper.l (Clipper lex rules)
%{
// Clipper lex rules.
// Developed by Antonio Linares (<!-- e --><a href="mailto:alin...@fivetech.com">alin...@fivetech.com</a><!-- e -->, <!-- m --><a class="postlink" href="http://www.fivetech.com">http://www.fivetech.com</a><!-- m -->)
// A first step for a GNU Clipper
// Build 1: March 99
// Usage: lex -i clipper.l
// You may find lex.exe at <!-- m --><a class="postlink" href="ftp://ftp.iag.net/pub/clipper/utils/byacc19.zip">ftp://ftp.iag.net/pub/clipper/utils/byacc19.zip</a><!-- m -->
#include <alloc.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "y_tab.h"
%}
SpaceTab [ \t]+
Number ([0-9]+)|([0-9]+\.[0-9]+)|(\.[0-9]+)
Identifier @?(([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+))
String \"(([^\"]*)|([\!]*))\"
%x COMMENT1 COMMENT2
%%
"//"|"&&" BEGIN COMMENT1;
<COMMENT1>.* BEGIN 0;
"/*" BEGIN COMMENT2;
<COMMENT2>\n ;
<COMMENT2>.* ;
<COMMENT2>"*/" BEGIN 0;
{SpaceTab} ;
\n+ return '\n';
"function" return FUNCTION;
"do"[ ]+"case" return DOCASE;
("do"[ ]+"while")|"while" return WHILE;
"case" return CASE;
"downto" return DOWNTO;
"otherwise" return OTHERWISE;
"end" return END;
"endcase" return ENDCASE;
"for" return FOR;
"if"^\( return IF;
"include" return INCLUDE;
"init" return INIT;
"else" return ELSE;
"end" return END;
"endif" return ENDIF;
"exit" return EXIT;
"extern" return EXTERN;
"local" return LOCAL;
"loop" return LOOP;
"next" return NEXT;
"public" return PUBLIC;
"return" return RETURN;
"static" return STATIC;
"to" return TO;
"nil" return NIL;
"#" return NE1;
"<>"|"!=" return NE2;
":=" return INASSIGN;
"==" return EQ;
"++" return INC;
"--" return DEC;
"->" return ALIAS;
"<=" return LE;
">=" return GE;
"+=" return PLUSEQ;
"-=" return MINUSEQ;
"*=" return MULTEQ;
"/=" return DIVEQ;
"^=" return EXPEQ;
"%=" return MODEQ;
".t." return TRUE;
".f." return FALSE;
".and." return AND;
".or." return OR;
"!"|".not." return NOT;
[\(\)] return yytext[ 0 ];
[,;+\-\*\/\{\}\|\#\&\:\<\>\=] return yytext[ 0 ];
{Number} yylval.fNumber = atof( yytext ); return NUMBER;
{Identifier} yylval.string = strdup( yytext ); return IDENTIFIER;
{String} yylval.string = strdup( yytext + 1 ); yylval.string[ yyleng -
2 ] = 0; return LITERAL;
%%
///------------ EOF -------------------------------
clipper.mak
cliparse.exe : y_tab.c lexyy.c
bcc -ml -ecliparse.exe y_tab.c lexyy.c
y_tab.c : clipper.y
byacc -d -v clipper.y
lexyy.c : clipper.l
lex -i clipper.l
///------------ EOF -------------------------------
To build it:
make -fclipper.mak