%{
/* Parser 
	Id: $Id: vb.y,v 1.31 2004/04/13 04:48:36 tommieb Exp tommieb $
	Revision: $Revision: 1.31 $
	Date: $Date: 2004/04/13 04:48:36 $
	Author: $Author: tommieb $

    This program is free software; you can redistribute it and/or modify
    it under the terms of version 2 of the GNU General Public License as 
    published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Thanks to www.programmar.com (Norken Technologies) for the idea which was
    translated from EBNF to YACC Grammar.

    Send me an email if you find this useful. 
    vbp.y is heavily borrowed from this version.
    Tom P. Brennan. 2004.

*/
#include 
#include "lb.h"
extern char yytext[];
extern int tokenpos, lineno, errorflag, maincode;
long grammar_action = 0;
%}

%union
{
	char *string;
	int integer;
	float numeral;
}

%token  OP_EQUAL OP_SEMICOLON OP_HASH OP_COMMA OP_LBRACKET OP_RBRACKET
%token  OP_STAR CAT_OP_ONE CAT_OP_TWO CMP_OP_ONE CMP_OP_TWO CMP_OP_THREE
%token  CMP_OP_FOUR CMP_OP_FIVE CMP_OP_SIX CMP_OP_SEVEN CMP_OP_EIGHT
%token  ADD_OP_ONE ADD_OP_TWO MULT_OP_ONE MULT_OP_TWO MULT_OP_THREE
%token  EXP_OP ASSIGN_OP_ONE ASSIGN_OP_TWO ASSIGN_OP_THREE
%token  VERSION VB_BEGIN END BEGINPROPERTY ENDPROPERTY ATTRIBUTE CLASS
%token  CASE DECLARE SUB FUNCTION LIB ALIAS ENUM PUBLIC PRIVATE ERASE
%token  EVENT EXECUTE EXECUTEGLOBAL ON ERROR RESUME NEXT GOTO 
%token  OPEN FOR AS APPEND BINARY INPUT ACCESS READ WRITE READ_WRITE
%token  SHARED LOCK_READ LOCK_WRITE LOCK_READ_WRITE LEN GET CLOSE SEEK
%token  LINE LOCK TO UNLOCK PUT OPTION EXPLICIT COMPARE TEXT DATABASE
%token  MODULE BASE NAME PROPERTY LET SET RANDOMIZE REDIM GLOBAL FRIEND
%token  STATIC CONST DEFAULT BYVAL BYREF OPTIONAL DIM WITHEVENTS NEW
%token  TYPE SELECT ELSE IS IF THEN ELSEIF HASH_IF HASH_END HASH_ELSEIF
%token  HASH_ELSE IN DO WHILE LOOP WEND CALL GOSUB VB_NULL RETURN
%token  STOP PRESERVE WITH BOOLEAN BYTE CONTROL CURRENCY DATE DECIMAL
%token  DOUBLE FORM INTEGER LONG OBJECT SINGLE STRING VARIANT
%token  OR XOR AND MOD ADDRESSOF NOT PRINT EXIT TRUE FALSE RANDOM TYPEOF
%token  OUTPUT IMPLEMENTS DEFBOOL DEFBYTE DEFINT DEFLNG DEFCUR 
%token  DEFSNG DEFDBL DEFDEC DEFDATE DEFSTR DEFOBJ DEFVAR NOTHING
%token  ENDIF ENDSUB ENDFUNCTION ENDWITH ENDPROPERTY2 ENDSELECT EACH PARAMARRAY
%token  LOOPUNTIL LOOPWHILE MID VBFORM DOLLAR SHORTCUT SHORTCUT_KEY DOWHILE DOUNTIL
	/*%token  ENDCLASS*/
%token  LITERAL_STRING LITERAL_HEX IDENTIFIER LITERAL_CHAR_CONSTANT LITERAL_GUID
%token  NUMERIC_CONSTANT
%type  simple_name subroutine_name
%nonassoc ELSE ELSEIF HASH_ELSE HASH_ELSEIF
%left AND OR XOR 
%left OP_EQUAL CMP_OP_ONE CMP_OP_TWO CMP_OP_THREE CMP_OP_FOUR CMP_OP_FIVE CMP_OP_SIX CMP_OP_SEVEN CMP_OP_EIGHT
%left ADD_OP_ONE ADD_OP_TWO MOD
%left uminus
%left OP_STAR MULT_OP_ONE MULT_OP_TWO MULT_OP_THREE
%left EXP_OP
%right IS NOT
%start program

%%
/*
**--------------------------------------- (Start State) Program! ---------------------------------------
*/
program:
	statements
	;
	
statements:
	| statements statement
	;
	
statement:
	version_stmt
	| class_stmt
	| object_instance_stmt
	| property_decl
	| attribute_stmt
	| declare_sub_stmt
	| declare_function_stmt
	| enum_stmt
	| erase_stmt
	| event_stmt
	| execute_stmt
	| execute_global_stmt
	| get_stmt
	| close_stmt
	| seek_stmt
	| write_stmt
	| input_stmt
	| line_input_stmt
	| lock_stmt
	| unlock_stmt
	| put_stmt
	| on_error_stmt
	| open_stmt
	| option_explicit_stmt
	| option_compare_stmt
	| option_private_stmt
	| option_base_stmt
	| name_stmt
	| property_get_stmt
	| property_let_stmt
	| property_set_stmt
	| randomize_stmt
	| redim_stmt
	| resume_stmt
	| with_stmt
	| subroutine_decl
	| function_decl
	| dimension_stmt
	| set_stmt
	| type_stmt
	| conditional_stmt
	| iteration_stmt
	| program_control_stmt
	| assignment_stmt
	| print_stmt
	| end_stmt
	| implicit_call
	| label_stmt
	| implements_stmt
	| declare_defxxxx_vars_stmt
	| declare_directive_const_stmt
	| mid_stmt
	| line_stmt
	| OP_SEMICOLON
	;

/*
**--------------------------------------- Version/Form Statement! ---------------------------------------
*/	
version_stmt:
	version_number version_wclass_stmt
	| OBJECT OP_EQUAL LITERAL_STRING CAT_OP_TWO LITERAL_STRING
	| VB_BEGIN VBFORM simple_name /* {	printf("Analysing %s Form..", $3); }*/ form_elements_list 
		END /*{	printf("Finished analysing %s Form..\nContinuing Code analysis....", $3); }*/
	| VB_BEGIN VBFORM simple_name END
	;

version_number:
	VERSION NUMERIC_CONSTANT
	;
	
version_wclass_stmt:
	| CLASS version_info_opt
	;
	
version_info_opt:
	VB_BEGIN version_info_attribute_list END
	;
	
version_info_attribute_list:
	attribute_stmt
	| version_info_attribute_list attribute_stmt
	;
	
form_elements_list:
	form_element
	| form_elements_list form_element
	;
	
form_element:
	simple_name OP_EQUAL dollar_opt constant_value semicolon_opt_hex
	| TEXT OP_EQUAL dollar_opt constant_value semicolon_opt_hex
	| DEFAULT OP_EQUAL dollar_opt constant_value semicolon_opt_hex
	| NAME OP_EQUAL dollar_opt constant_value semicolon_opt_hex
	| SHORTCUT OP_EQUAL SHORTCUT_KEY
	| SHORTCUT OP_EQUAL MULT_OP_THREE shortcut_opt
	| VB_BEGIN vbcontrol_name simple_name form_elements_list END
	| beginproperties
	;

dollar_opt:
	| DOLLAR
	;
	
shortcut_opt:
	simple_name
	;
	
semicolon_opt_hex:
	| OP_SEMICOLON constant_value
	;
	
beginproperties:
	beginproperty_stmt
	| beginproperties beginproperty_stmt
	;
	
beginproperty_stmt:
	BEGINPROPERTY simple_name guid_opt ENDPROPERTY
	| BEGINPROPERTY simple_name guid_opt form_elements_list ENDPROPERTY
	;
	
guid_opt:
	| LITERAL_GUID
	;
	
vbcontrol_name:
	simple_name
	;

attribute_stmt:
	ATTRIBUTE simple_name OP_EQUAL expression
	| simple_name OP_EQUAL expression
	;

/*
**--------------------------------------- Class Statement! ---------------------------------------
*/		
class_stmt:
	CLASS class_name statements END CLASS
	;
	
class_name:
	simple_name
	;

/*
**--------------------------------------- Object Statement! ---------------------------------------
*/		
object_instance_stmt:
	VB_BEGIN simple_name object_name object_instance_stmt_decl END
	;
	
object_name:
	simple_name
	;
	
object_instance_stmt_decl:
	object_instance_stmt
	| property_decl
	| assign_property
	;
	
implements_stmt:
	IMPLEMENTS complex_name
	;
	
property_decl:
	BEGINPROPERTY property_name property_name property_decl_stmt ENDPROPERTY
	;

property_decl_stmt:
	| property_decl
	| assign_property
	;
	
assign_property:
	assign_property_name OP_EQUAL assign_property_value
	;
	
assign_property_name:
	simple_name 
	;
	
assign_property_value:
	simple_name
	;

/*
**--------------------------------------- Declare Sub/Function Statement! ---------------------------------------
*/	
declare_sub_stmt:
	DECLARE SUB subroutine_name LIB libname alias_name param_decls_opt
	| access_specifier_list DECLARE SUB subroutine_name LIB libname alias_name param_decls_opt
	;

declare_function_stmt:
	DECLARE FUNCTION function_name LIB libname alias_name param_decls_opt return_value_opt
	| access_specifier_list DECLARE FUNCTION function_name LIB libname alias_name param_decls_opt return_value_opt
	;

libname:
	string_constant
	;
	
alias_name:
	| ALIAS aliasname
	;
	
aliasname:
	string_constant
	;

return_value_opt:
	| return_value
	;


declare_directive_const_stmt:
	OP_HASH CONST member_name
	;
			
end_stmt:
	END
	;

/*
**--------------------------------------- Enum Statement! ---------------------------------------
*/		
enum_stmt:
	ENUM enum_name enum_list END ENUM
	| enum_specifier_opt ENUM enum_name enum_list END ENUM
	;

enum_specifier_opt:
	PUBLIC
	| PRIVATE
	;
	
enum_list:
	member_name 
	| enum_list member_name
	;
	
enum_name:
	simple_name
	;
	
member_name:
	simple_name enum_assignment_opt
	;
	
enum_assignment_opt:
	| OP_EQUAL expression
	;
	
/*
**--------------------------------------- Erase Statement! ---------------------------------------
*/	
erase_stmt:
	ERASE array_name_list
	;
	
array_name:
	simple_name
	;
	
array_name_list:
	array_name
	| array_name_list OP_COMMA array_name
	;

/*
**--------------------------------------- Event Statement! ---------------------------------------
*/		
event_stmt:
	EVENT subroutine_name param_decls_opt
	| event_modifier EVENT subroutine_name param_decls_opt
	;
	
event_modifier:
	PUBLIC
	;
	
/*
**--------------------------------------- Execute Statement! ---------------------------------------
*/	
execute_stmt:
	EXECUTE string_expression
	;
	
execute_global_stmt:
	EXECUTEGLOBAL string_expression
	;
	
/*
**--------------------------------------- On Error Statement! ---------------------------------------
*/	
on_error_stmt:
	ON ERROR RESUME NEXT
	| ON ERROR GOTO label
	| ON ERROR GOTO NUMERIC_CONSTANT	/* { if ($4 != 0) yyerror("\nOn Error GoTo statement requires either zero or a label identifier\n"); }*/
	;

/*
**--------------------------------------- File I/O Statement! ---------------------------------------
*/		
open_stmt:
	OPEN pathname FOR mode access_opt lock_opt AS filenumber len_rec_opt
	;

get_stmt:
	GET filenumber OP_COMMA recnumber_opt OP_COMMA complex_name
	;

close_stmt:
	singular_close_stmt
	| CLOSE filenumber_list
	;

singular_close_stmt:
	CLOSE
	;
	
seek_stmt:
	SEEK filenumber OP_COMMA position
	;

write_stmt:
	WRITE filenumber comma_opt write_list
	;

input_stmt:
	INPUT filenumber OP_COMMA var_list
	;

line_input_stmt:
	LINE INPUT filenumber OP_COMMA var_name
	;

lock_stmt:
	LOCK filenumber record_range_opt
	;

unlock_stmt:
	UNLOCK filenumber record_range_opt
	;
	
put_stmt:
	PUT filenumber OP_COMMA start_recnumber_opt OP_COMMA expression
	;

name_stmt:
	NAME old_pathname AS new_pathname
	;

print_stmt:
	PRINT filenumber
	| PRINT filenumber OP_COMMA
	| PRINT filenumber OP_COMMA var_list
	;
		
pathname:
	string_expression
	;
	
mode:
	APPEND
	| BINARY
	| INPUT
	| OUTPUT
	| RANDOM
	;
	
access_opt:
	| ACCESS READ
	| ACCESS WRITE
	| ACCESS READ_WRITE
	;
	
lock_opt:
	| SHARED
	| LOCK_READ
	| LOCK_WRITE
	| LOCK_READ_WRITE
	;
	
filenumber:
	simple_name
	| numeric_constant
	| OP_HASH simple_name
	| OP_HASH numeric_constant
/*	hash_opt simple_name
	| hash_opt numeric_constant*/
	;
/*
hash_opt:
	| OP_HASH
	;
*/
len_rec_opt:
	| LEN OP_EQUAL reclength
	;
	
reclength:
	expression
	;
		
recnumber_opt:
	| expression
	;
		
filenumber_list:
	filenumber
	| filenumber_list OP_COMMA filenumber
	;
		
position:
	expression
	;
		
comma_opt:
	| OP_COMMA
	;
	
write_list:
	expression
	| write_list OP_COMMA expression 
	;
		
var_list:
	var_name
	| var_list OP_COMMA var_name 
	;
		
var_name:
	simple_name dimensioned_array_opt
	| expression
	;
	
record_range_opt:
	OP_COMMA start_recnumber 
	| OP_COMMA start_recnumber to_end_recnumber_opt
	| OP_COMMA to_end_recnumber_opt
	;
	
start_recnumber:
	expression
	;
	
to_end_recnumber_opt:
	TO end_recnumber
	;
	
end_recnumber:
	expression
	;
		
start_recnumber_opt:
	| start_recnumber
	;
	
old_pathname:
	string_expression
	;
	
new_pathname:
	string_expression
	;

/*
**--------------------------------------- Option Statement! ---------------------------------------
*/		
option_explicit_stmt:
	OPTION EXPLICIT
	;
	
option_compare_stmt:
	OPTION COMPARE binary_text_database
	;
	
binary_text_database:
	BINARY
	| TEXT
	| DATABASE
	;
	
option_private_stmt:
	OPTION PRIVATE MODULE
	;
	
option_base_stmt:
	OPTION BASE zero_or_one
	;
	
zero_or_one:
	NUMERIC_CONSTANT
	;

/*
**--------------------------------------- Randomize Statement! ---------------------------------------
*/				
randomize_stmt:
	RANDOMIZE
	| RANDOMIZE expression
	;

/*
**--------------------------------------- Resume Statement! ---------------------------------------
*/	
resume_stmt:
	/*RESUME
	|*/ RESUME NEXT
	| RESUME NUMERIC_CONSTANT
	| RESUME IDENTIFIER
	;

/*
**--------------------------------------- Label Statement! ---------------------------------------
*/	
label_stmt:
	simple_name OP_SEMICOLON /*statements*/
	| numeric_constant OP_SEMICOLON /*statements*/
	;
	
/*
**--------------------------------------- With Statement! ---------------------------------------
*/	
with_stmt:
	WITH complex_name statements ENDWITH
	;

/*
**--------------------------------------- Mid Statement! ---------------------------------------
*/		
mid_stmt:
	MID OP_LBRACKET param_list OP_RBRACKET ass_expr_opt
/*	| MID OP_LBRACKET param_list OP_RBRACKET OP_EQUAL expression*/
	;

/*
**--------------------------------------- Line Statement! ---------------------------------------
*/	
line_stmt:
	LINE OP_LBRACKET param_list OP_RBRACKET ADD_OP_TWO OP_LBRACKET param_list OP_RBRACKET line_opt_stmt
	;
	
line_opt_stmt:
	| OP_COMMA complex_name
	;

/*
**--------------------------------------- Implicit Call Statement! ---------------------------------------
*/	
implicit_call:
	complex_name 
	;
	
/*
**--------------------------------------- Set Statement! ---------------------------------------
*/	
set_stmt:
	SET set_name OP_EQUAL new_tag_new_type
	| SET set_name OP_EQUAL set_value
	;
	
set_name:
	complex_name
	;
	
set_value:
	expression
	;
	
new_tag_new_type:
	new_tag new_type
	;

new_tag:
	NEW
	;
	
new_type:
	type
	;

/*
**--------------------------------------- Property Get/Let/Set Statement! ---------------------------------------
*/	
property_get_stmt:
	PROPERTY GET property_name param_decls_opt AS type statements ENDPROPERTY2
	| access_specifier_list PROPERTY GET property_name param_decls_opt AS type statements ENDPROPERTY2
	;
	
property_name:
	simple_name
	;
	
property_let_stmt:
	PROPERTY LET property_name param_decls_opt statements ENDPROPERTY2
	| access_specifier_list PROPERTY LET property_name param_decls_opt statements ENDPROPERTY2
	;

property_set_stmt:
	PROPERTY SET property_name param_decls_opt statements ENDPROPERTY2
	| access_specifier_list PROPERTY SET property_name param_decls_opt statements ENDPROPERTY2
	;

/*
**--------------------------------------- Subroutine/Function Statement! ---------------------------------------
*/	
subroutine_decl:
	SUB subroutine_name param_decls_opt statements ENDSUB	{	if (!strcmp($2, "Main")) maincode = 1; }
	| access_specifier_list SUB subroutine_name param_decls_opt statements ENDSUB
	;
	
function_decl:
	FUNCTION subroutine_name param_decls_opt statements ENDFUNCTION
	| FUNCTION subroutine_name param_decls_opt return_value statements ENDFUNCTION
	| access_specifier_list FUNCTION subroutine_name param_decls_opt statements ENDFUNCTION
	| access_specifier_list FUNCTION subroutine_name param_decls_opt return_value statements ENDFUNCTION
	;

access_specifier_list:
	access_specifier
	| access_specifier_list access_specifier
	;
	
access_specifier:
	PRIVATE
	| PUBLIC public_default_opt
	| GLOBAL
	| FRIEND
	| STATIC
	| CONST
	;
	
public_default_opt:
	| DEFAULT
	;
	
subroutine_name:
	simple_name	{ $$ = $1; }
	;
	
function_name:
	simple_name
	;
	
param_decls_opt:
	OP_LBRACKET OP_RBRACKET
	| OP_LBRACKET param_decl_list OP_RBRACKET
	;
	
param_decl_list:
	param_decl
	| param_decl_list OP_COMMA param_decl
	;
	
param_decl:
	simple_name func_param_opt as_type_opt ass_expr_opt
	| param_flag_list_opt simple_name func_param_opt as_type_opt ass_expr_opt
	;
	
func_param_opt:
	| OP_LBRACKET OP_RBRACKET
	;
	
as_type_opt:
	| AS type
	;
	
param_flag_list_opt:
	param_flag
	| param_flag_list_opt param_flag
	;
	
param_flag:
	BYVAL
	| BYREF
	| OPTIONAL
	| PARAMARRAY
	;

ass_expr_opt:
	| OP_EQUAL expression
	;

return_value:
	AS type
	;

/*
**--------------------------------------- ReDim Statement! ---------------------------------------
*/	
redim_stmt:
	REDIM preserve_tag_opt dimensioned_item_list
	;

preserve_tag_opt:
	| PRESERVE
	;

/*
**--------------------------------------- DefXXXX Statement! ---------------------------------------
*/	
declare_defxxxx_vars_stmt:
	def_var_reqd letter_ranges_reqd
	;

def_var_reqd:
	DEFBOOL
	| DEFBYTE
	| DEFINT
	| DEFLNG
	| DEFCUR
	| DEFSNG
	| DEFDBL
	| DEFDEC
	| DEFDATE
	| DEFSTR
	| DEFOBJ
	| DEFVAR
	;

letter_ranges_reqd:
	letter_range
	| letter_ranges_reqd OP_COMMA letter_range
	;

letter_range:
	simple_name high_letter_opt
	;
	
high_letter_opt:
	| ADD_OP_TWO simple_name
	;

/*
**--------------------------------------- Dimension Statement! ---------------------------------------
*/	
dimension_stmt:
	DIM dimensioned_item_list
	| access_specifier_list DIM dimensioned_item_list
	| access_specifier_list dimensioned_item_list
	;

dimensioned_item_list:
	dimensioned_item
	| dimensioned_item_list OP_COMMA dimensioned_item 
	;
	
dimensioned_item:
	simple_name dimensioned_array_opt dimensioned_as_type_opt ass_expr_opt
	| WITHEVENTS simple_name dimensioned_array_opt dimensioned_as_type_opt ass_expr_opt
	;
	
dimensioned_array_opt:
	| OP_LBRACKET subscript_list_opt OP_RBRACKET
	;
	
dimensioned_as_type_opt:
	| AS new_tag_opt type
	;
	
new_tag_opt:
	| NEW
	;
	
subscript_list_opt:
	| subscripts_list_opt
	;
	
subscripts_list_opt:
	subscript
	| subscripts_list_opt OP_COMMA subscript
	;
	
subscript:
	upper
	| lower_to_opt upper
	;
	
lower_to_opt:
	lower TO
	;
	
lower:
	expression
	;
	
upper:
	expression
	;
	
/*
**--------------------------------------- Type Statement! ---------------------------------------
*/	
type_stmt:
	TYPE type_name typedef_list END TYPE
	| access_specifier TYPE type_name typedef_list END TYPE
	;
	
typedef_list:
	typedef_member
	| typedef_list typedef_member
	;
	
typedef_member:
	element_name dimensioned_array_opt as_type_opt
	;
	
type_name:
	simple_name
	;
	
element_name:
	simple_name
	;

/*
**--------------------------------------- Conditional Statement! ---------------------------------------
*/
conditional_stmt:
	/*case_stmt
	|*/ 
	select_case_stmt
	| if_stmt
	| if_directive
	;
/*
case_stmt:
	VB_BEGIN CASE case_item END CASE
	;
	
case_item:
	CASE expression
	| CASE statements
	;
*/

/*
**--------------------------------------- (Conditional Statement) Select Case Statement! ---------------------------------------
*/
select_case_stmt:
	SELECT CASE expression select_case_item_list ENDSELECT
	;
	
select_case_item_list:
	select_case_item
	| select_case_item_list select_case_item
	;
	
select_case_item:
	CASE expression statements 
	| CASE ELSE statements
	| CASE ELSE case_expression_list statements
	;

case_expression_list:
	case_expression
	| case_expression_list OP_COMMA case_expression 
	;

case_expression:
	IS cmp_level_op expression
	| expression to_expression_opt
	;
	
to_expression_opt:
	| TO expression
	;

/*
**--------------------------------------- (Conditional Statement) If..Then..Else.. Statement! ---------------------------------------
*/	
if_stmt:
	IF expression THEN statements elseif_else_clause_opt endif_clause_opt
	;
	
endif_clause_opt:
	| ENDIF
	;
	
elseif_else_clause_opt:
	| elseif_clause
	| else_clause
	;
	
elseif_clause:
	ELSEIF expression THEN statements elseif_else_clause_opt endif_clause_opt
	;
	
else_clause:
	ELSE statements /* Change to statement to resolve 76s/r!*/
	;

/*
**--------------------------------------- (Conditional Statement) If..Then..Else Directive Statement! ---------------------------------------
*/
if_directive:
	HASH_IF expression THEN statements elseif_else_directive_clause_opt
	;
	
elseif_else_directive_clause_opt:
	| elseif_directive_clause
	| else_directive_clause
	;
	
elseif_directive_clause:
	HASH_ELSEIF expression THEN statements elseif_else_directive_clause_opt
	;
	
else_directive_clause:
	HASH_ELSE statements HASH_END IF
	;
	
/*
**--------------------------------------- Iteration Statement! ---------------------------------------
*/
iteration_stmt:
	for_each_stmt
	| for_stmt
	| do_loop_stmt
	| while_stmt
	;

/*
**--------------------------------------- (Iteration Statement) For..Each Statement! ---------------------------------------
*/			
for_each_stmt:
	FOR EACH for_name IN group_name statements NEXT 
	;

/*
**--------------------------------------- (Iteration Statement) For Statement! ---------------------------------------
*/	
for_stmt:
	FOR for_name OP_EQUAL for_start TO for_end statements NEXT
	| FOR for_name OP_EQUAL for_start TO for_end step_amount_opt statements NEXT
	;

for_name:
	simple_name
	;
	
group_name:
	complex_name
	;
	
for_start:
	expression
	;
	
for_end:
	expression
	;
	
step_amount_opt:
	expression
	;

/*
**--------------------------------------- (Iteration Statement) Do..Loop Statement! ---------------------------------------
*/	
do_loop_stmt:
	DOWHILE expression statements LOOP
	| DOUNTIL expression statements LOOP
	| DO statements LOOPWHILE expression 
	| DO statements  LOOPUNTIL expression 
	;

/*
**--------------------------------------- (Iteration Statement) While..Wend Statement! ---------------------------------------
*/
while_stmt:
	WHILE expression statements WEND
	;

/*
**--------------------------------------- Program Control Statement! ---------------------------------------
*/
program_control_stmt:
	call_stmt
	| gosub_stmt
	| goto_stmt
	| null_stmt
	| on_gosub_stmt
	| on_goto_stmt
	| return_stmt
	| stop_stmt
	| exit_stmt
	;
	
/*
**--------------------------------------- (Program Control Statement) Call Statement! ---------------------------------------
*/	
call_stmt:
	CALL complex_name
	;
	
/*
**--------------------------------------- (Program Control Statement) GoSub Statement! ---------------------------------------
*/
gosub_stmt:
	GOSUB label
	;
	
/*
**--------------------------------------- (Program Control Statement) GoTo Statement! ---------------------------------------
*/
goto_stmt:
	GOTO label
	;

/*
**--------------------------------------- (Program Control Statement) Null Statement! ---------------------------------------
*/
null_stmt:
	VB_NULL
	;

/*
**--------------------------------------- (Program Control Statement) On GoSub Statement! ---------------------------------------
*/
on_gosub_stmt:
	ON expression GOSUB label_list
	;
	
label_list:
	label
	| label_list OP_COMMA label 
	;
	
/*
**--------------------------------------- (Program Control Statement) On GoTo Statement! ---------------------------------------
*/
on_goto_stmt:
	ON expression GOTO label_list
	;

/*
**--------------------------------------- (Program Control Statement) Return Statement! ---------------------------------------
*/
return_stmt:
	RETURN
/*	| RETURN expression */
	;

/*
**--------------------------------------- (Program Control Statement) Stop Statement! ---------------------------------------
*/
stop_stmt:
	STOP
/*	| STOP expression*/
	;
	
/*
**--------------------------------------- (Program Control Statement) Exit Statement! ---------------------------------------
*/
exit_stmt:
	EXIT do_for_prop_func_sub_stmt
	;
	
do_for_prop_func_sub_stmt:
	DO
	| FOR
	| FUNCTION
	| PROPERTY
	| SUB
	;

/*
**--------------------------------------- Data Type! ---------------------------------------
*/
basic_type:
	BOOLEAN
	| BYTE
	| CONTROL
	| CURRENCY
	| DATE
	| DECIMAL
	| DOUBLE
	| FORM
	| INTEGER
	| LONG
	| OBJECT
	| SINGLE
	| STRING
	| string_wlength_opt
	| VARIANT
	| PROPERTY
	;
	
string_wlength_opt:
	STRING OP_STAR string_length
	;

string_length:
	simple_name
	| NUMERIC_CONSTANT
	;
	
type:
	basic_type
	| simple_name
	;

/*
**--------------------------------------- TypeOf Expression! ---------------------------------------
*/	
typeof_expression:
	TYPEOF complex_name
/*	| TYPEOF OP_LBRACKET expression OP_RBRACKET*/
	;

is_object_type_expression:
	IS type	
	| IS NOTHING
	| IS null_stmt
	;

/*
**--------------------------------------- Expressions! ---------------------------------------
*/
/*
numeric_expression:
	expression
	;
*/
string_expression:
	expression
	;
	
simple_name:
	IDENTIFIER { $$ = $1; }
	;

label:
	simple_name
/*	| numeric_expression*/
	;
	
expression:
	term
	| term exp_level_op expression
	| term mult_level_op expression 
	| term add_level_op expression 
	| term cmp_level_op expression 
	| term cat_level_op expression 
	| term and_level_op expression 
	| term or_level_op expression 
	;
	
or_level_op:
	OR
	| XOR
	;
	
and_level_op:
	AND
	;

cat_level_op:
	CAT_OP_ONE
	| CAT_OP_TWO
	;
	
cmp_level_op:
	OP_EQUAL
	| CMP_OP_ONE
	| CMP_OP_TWO
	| CMP_OP_THREE
	| CMP_OP_FOUR
	| CMP_OP_FIVE
	| CMP_OP_SIX
	| CMP_OP_SEVEN
	| CMP_OP_EIGHT
	;
	
add_level_op:
	ADD_OP_ONE
	| ADD_OP_TWO
	;
	
mult_level_op:
	OP_STAR
	| MULT_OP_ONE
	| MULT_OP_TWO
	| MOD
	| MULT_OP_THREE
	;
	
exp_level_op:
	EXP_OP
	;

/*
**--------------------------------------- (Expressions) Term! ---------------------------------------
*/	
term:
	constant_value
	| complex_name_list
	| not_expression
	| OP_LBRACKET expression OP_RBRACKET
	| unary_op expression %prec uminus
	| address_of_op_opt simple_name
	| typeof_expression
	| is_object_type_expression
	| NOTHING
	| null_stmt
	| LEN OP_LBRACKET param_list OP_RBRACKET	/* A BIT IFFY!!!! */
	| STRING OP_LBRACKET param_list OP_RBRACKET	/* A BIT IFFY!!!! */
	| SEEK OP_LBRACKET param_list OP_RBRACKET	/* A BIT IFFY!!!! */
	| mid_stmt
	| date_function
	| error_function
	;
	
date_function:
	DATE
	;
	
error_function:
	ERROR 
	;
	
address_of_op_opt:
	ADDRESSOF
	;
	
not_expression:
	NOT expression
	;
	
unary_op:
	ADD_OP_TWO
	;

/*
**--------------------------------------- Complex Name! ---------------------------------------
*/	
complex_name_list:
	complex_name 
	| complex_name_list complex_name
	;

complex_name:
	simple_name modifiers
	;
	
/*
**--------------------------------------- (Complex Name) Modifiers! ---------------------------------------
*/		
modifiers:
	| param_list
	| OP_LBRACKET OP_RBRACKET /*Comment this out to resolve 1s/r! - clashing with dimensioned_array_opt*/
	| OP_LBRACKET param_list OP_RBRACKET
	;

param_list:
	param
	| param_list OP_COMMA param
	;
	
param:
	expression
	| byval_opt expression
	| simple_name ASSIGN_OP_THREE expression
	| byval_opt simple_name ASSIGN_OP_THREE expression
	;
	
byval_opt:
	BYVAL
	;

/*
**--------------------------------------- Assignment Statement! ---------------------------------------
*/		
assignment_stmt:
	lvalue assign_op rvalue
	;

lvalue:
	complex_name
	;
	
assign_op:
	OP_EQUAL
	| ASSIGN_OP_ONE
	| ASSIGN_OP_TWO
	| ASSIGN_OP_THREE
	;
	
rvalue:
	expression
	;

/*
**--------------------------------------- Constant Value! ---------------------------------------
*/
constant_value:
	hex_constant
	| numeric_constant
	| string_constant
	| char_constant
	| hash_delimited_value
	| boolean_constant
	;

/*
**--------------------------------------- (Constant Value) Hex Constant! ---------------------------------------
*/
hex_constant:
	LITERAL_HEX
	;

/*
**--------------------------------------- (Constant Value) Numeric Constant! ---------------------------------------
*/
numeric_constant:
	NUMERIC_CONSTANT
	;

/*
**--------------------------------------- (Constant Value) String Constant! ---------------------------------------
*/
string_constant:
	LITERAL_STRING
	;

/*
**--------------------------------------- (Constant Value) Character Constant! ---------------------------------------
*/
char_constant:
	LITERAL_CHAR_CONSTANT
	;
	
/*
**--------------------------------------- (Constant Value) Hash Delimited Constant! ---------------------------------------
*/
hash_delimited_value:
	OP_HASH NUMERIC_CONSTANT
	;
	
/*
**--------------------------------------- (Constant Value) Boolean Constant! ---------------------------------------
*/
boolean_constant:
	TRUE
	| FALSE
	;
	
/*
**--------------------------------------- (End Of Grammar!) ---------------------------------------
*/
%%
yyerror(char *msg)
{
	printf("Bison error (VB) at line: (%d). %s\n", lineno, msg);
	yyclearin; errorflag = 1;
}

    Source: geocities.com/wabbitty2002