The Yacc grammar of GRAIL. The idea to this grammar can be devoted to Lars Nilsson.

Step 2 (The grail grammar with symbol table mechanism implemented).

The homepage of Mats Luspa.



%{
#include <stdio.h>
%}
%token MAIN END ID VARIABLE ARRAY NUM INTNUM OF STRUCTURE INTEGER REAL
%token IF THEN ELSE FOR DO WHILE REPEAT UNTIL AT BY WITH POINTPOINT NOT
%token FUNCTION PROCEDURE ASSIGNOP MULOP RELOP TO 
%token LT LE EQ NE GT GE RETURN
%token ADDOP COMMENT COLON SEMICOLON TYPEDEF AS STRUCTID
%token LPAR RPAR

%right '='
%left '-' '+'
%left '*' '/'

%%
program:
    	opt_typedef_declarations opt_declarations subprogram_declarations MAIN opt_declarations optional_statements END 
    	;

opt_typedef_declarations: 
	| typedef_declarations
	;

typedef_declarations:
	typedef_declaration SEMICOLON
	| typedef_declarations typedef_declaration SEMICOLON
	;

typedef_declaration:
	TYPEDEF ID AS type
	;
	
idlist:
    	ID 
    	| idlist ',' ID
    	;

opt_declarations: 
	| declarations 
	;

declarations:
     	declaration SEMICOLON
    	|declarations declaration SEMICOLON
    	;

declaration: 
	VARIABLE idlist COLON type
	;

type:
    	ID /* Must check that this type has been defined with typedef */
    	| standard_type
    	| ARRAY '[' INTNUM POINTPOINT INTNUM ']' OF type
    	| STRUCTURE struct_tags END
    	;

struct_tags:
	ID COLON type SEMICOLON
	| struct_tags ID COLON type SEMICOLON
	;

standard_type:
    	INTEGER
    	| REAL
    	;

subprogram_declarations:
    	| subprogram_declarations subprogram_pro_declaration SEMICOLON 
	| subprogram_declarations subprogram_fun_declaration SEMICOLON
    	;

subprogram_fun_declaration:
    	subprogram_fun_head opt_declarations optional_statements RETURN expression END
	;

subprogram_pro_declaration:
	subprogram_pro_head opt_declarations optional_statements END
    	;

subprogram_fun_head:
    	FUNCTION ID arguments COLON standard_type
	;

subprogram_pro_head:
   	PROCEDURE ID arguments
    	;

arguments:
	| LPAR parameter_list RPAR 
    	;

parameter_list:
    	| idlist COLON type 
    	| parameter_list SEMICOLON idlist COLON type 
    	;

optional_statements:
    	| statements 
    	;

statements:
	statement SEMICOLON 
	| statements statement SEMICOLON 
	;

statement:
    	ID ASSIGNOP expression 
    	| procedure_statement
    	| IF expression THEN optional_statements ELSE optional_statements END
    	| IF expression THEN optional_statements END
    	| FOR ID ASSIGNOP expression TO expression DO optional_statements END
    	| FOR ID ASSIGNOP expression TO expression BY expression DO optional_statements END
    	| WHILE expression DO optional_statements END
    	| REPEAT optional_statements UNTIL expression END
    	| AT time_expression DO optional_statements END 
    	| AT time_expression UNTIL time_expression DO optional_statements END
    	| AT time_expression UNTIL time_expression BY expression DO optional_statements END 
    	| WITH station_expression DO optional_statements END
    	;

time_expression:
    	expression COLON expression COLON expression COLON expression COLON expression COLON expression;

station_expression:
    	expression POINTPOINT expression
    	| station_expression ',' expression POINTPOINT expression
    	;


var:
    	ID
    	| ID '[' expression ']'
    	| STRUCTID 
    	;

procedure_statement:
    	ID
    	| ID LPAR expression_list RPAR
    	;

expression_list:
    	expression
    	| expression_list ',' expression
    	;

expression:
    	simple_expression
    	| simple_expression RELOP simple_expression
    	;

simple_expression:
    	term
    	| sign term
    	| simple_expression ADDOP term
    	;

term:
    	factor
    	| term MULOP factor
    	;

factor:
    	ID
    	| STRUCTID	
    	| ID LPAR expression_list RPAR 
	| NUM
    	| LPAR expression RPAR 
    	| NOT factor
    	;

sign: ADDOP;
%%
int lineno=1;

main (int argc, char** argv)
{
    char*
    progname = argv[1];
    extern yydebug;    

    yydebug = 1;
    if (!freopen(progname,"r",stdin))
    {
	fprintf(stderr,"Couldn't open %s\n", progname);
	exit(1);
    }
    yyparse();    
}

yyerror(char* s)
{
    fprintf(stderr,"%s line = %d\n",s,lineno);
}