source_text:
	/* empty */
	| source_text module
	;
 
module:
	VL_MODULE VL_ID list_of_ports_opt ';' module_item_opt VL_ENDMODULE
	;
 
list_of_ports_opt:
	/* empty */
	|'(' ports ')'
	;
 
ports:
	port
	| ports ',' port
	;
 
port:
	/* empty */
	|
	lvalue
	| '.' VL_ID  '(' lvalue ')'
	;
 
/**************EOP**************/
 
name_of_variable
	: VL_ID
	;
 
module_item_opt:
	/*empty*/
	| module_item_opt module_item
	;
 
module_item
	: parameters_declaration
	| input_declaration
	| output_declaration
	| inout_declaration
	| net_declaration
	| reg_declaration
	| module_declaration
	| initial_statement
	| always_statement
	| guarded_always_statement
	| task_declaration
	| assign_declaration
	;
 
assign_declaration
	: VL_ASSIGN
	statement
	;
 
task_declaration
	: VL_TASK VL_ID ';'
	io_declaration_opt_list
	statement VL_ENDTASK
	;
 
io_declaration_opt_list
	: io_declaration_opt
	| io_declaration_opt_list io_declaration_opt
	;
 
io_declaration_opt
	: input_declaration
	| output_declaration
	| inout_declaration
	;
 
module_declaration
	: VL_ID VL_ID list_of_ports_opt ';'
 
input_declaration
	: VL_INPUT range_opt list_of_variables ';'
        ;
 
output_declaration
        : VL_OUTPUT range_opt list_of_variables ';'
        ;
 
inout_declaration
        : VL_INOUT range_opt list_of_variables ';'
        ;
 
parameters_declaration
	: VL_PARAMETER list_of_parameter_declaration ';'
	;
 
parameter_declaration
	: identifier '=' constant_expression
	;
 
list_of_parameter_declaration
	: parameter_declaration
	| list_of_parameter_declaration ',' parameter_declaration
	;
 
net_declaration
	: VL_WIRE range_opt list_of_variables ';'
	;
 
reg_declaration
        : VL_REG range_opt list_of_register_variables ';'
        ;
 
initial_statement
	: VL_INITIAL
	 statement
	;
 
always_statement
	: VL_ALWAYS
	statement
	;
 
guarded_always_statement
	: VL_ALWAYS event_control
	statement
	;
 
statement_or_null
	: ';'
	| statement
	;
 
/* if statement gives 1 shift/reduce conflict */
statement
	: assignment ';'
	| ifLine
	| ifLine VL_ELSE
	statement_or_null
	| VL_CASE '(' expression ')'
	case_items VL_ENDCASE
	| VL_FOR '(' assignment ';' expression ';' assignment ')'
	statement
	| VL_FOREVER
	statement
	| VL_WHILE '(' expression ')'
	statement
	| delay_control
 	statement_or_null
	| event_control
	statement_or_null
	| seq_block
	| VL_ASSIGN assignment ';'
	| task_call
	;
 
task_call
	: VL_ID list_of_parameters_opt ';'
	;
 
list_of_parameters_opt
	: /*empty*/
	| '(' list_of_expressions ')'
	;
 
list_of_expressions
	: expression
	| list_of_expressions ',' expression
	;
 
 
ifLine: VL_IF '(' expression ')'
	statement_or_null
	;
 
seq_block
	: VL_BEGIN
	 statements VL_END
	;
 
statements:
	/* empty */
	| statements statement
	;
 
assignment
	: lvalue '=' expression
	;
 
case_items
	: case_item
	| case_items case_item
	;
 
case_item
	: expressions ':'
	statement_or_null
	| VL_DEFAULT ':'
	statement_or_null
	| VL_DEFAULT statement_or_null
	;
 
/**********************************************/
 
list_of_register_variables
        : register_variable
        | list_of_register_variables ',' register_variable
        ;
 
register_variable
        : name_of_register
        | name_of_memory '[' constant_expression ':' constant_expression ']'
        ;
 
name_of_register
        : VL_ID
        ;
 
name_of_memory
        : VL_ID
        ;
 
name_of_variable
	: VL_ID
	;
 
list_of_variables
	: name_of_variable
	| list_of_variables ',' name_of_variable
	;
 
range_opt
        : /* empty */
        | range
        ;
 
range
        : '[' constant_expression ':' constant_expression ']'
        ;
 
/**********************************/
 
lvalue
	: identifier
	| identifier '[' expression ']'
	| identifier '[' constant_expression ':' constant_expression ']'
	;
 
 
expressions
	: expression
	| expressions ',' expression
	;
 
constant_expression
	: expression
	;
 
expression
        : primary
        | '+' expression %prec VL_UNARYOPERATOR
        | '-' expression %prec VL_UNARYOPERATOR
        | '!' expression %prec VL_UNARYOPERATOR
        | '~' expression %prec VL_UNARYOPERATOR
        | '&' expression %prec VL_UNARYOPERATOR
        | '|' expression %prec VL_UNARYOPERATOR
        | VL_LOGNAND expression %prec VL_UNARYOPERATOR
        | VL_LOGNOR expression %prec VL_UNARYOPERATOR
        | VL_LOGXNOR expression %prec VL_UNARYOPERATOR
        | expression '+' expression
        | expression '-' expression
        | expression '*' expression
        | expression '/' expression
        | expression '%' expression
        | expression VL_LOGEQUALITY expression
        | expression VL_LOGINEQUALITY expression
        | expression VL_CASEEQUALITY expression
        | expression VL_CASEINEQUALITY expression
        | expression VL_LOGAND expression
        | expression VL_LOGOR expression
        | expression '<' expression
        | expression '>' expression
        | expression '&' expression
        | expression '|' expression
        | expression '^' expression
        | expression VL_LEQ expression
        | expression VL_NBASSIGN expression
        | expression VL_GEQ expression
        | expression VL_LSHIFT expression
        | expression VL_RSHIFT expression
        | expression VL_LOGXNOR expression
	| '(' expression ')'
        ;
 
primary
        : VL_INUMBER
	| VL_BNUMBER
        | VL_RNUMBER
        | VL_ONUMBER
	| VL_DNUMBER
	| VL_HNUMBER
	| identifier
        | identifier '[' expression ']'
        | identifier '[' constant_expression ':'  constant_expression ']'
        ;
 
/*********************************/
 
identifier
        : VL_ID
        ;
 
delay_control
	: '#' VL_INUMBER
	| '#' VL_RNUMBER
/*
	| '#' identifier
	| '#' mintypmax_expression
*/
	;
event_control
	: '@' identifier
	| '@' '(' event_expression ')'
	;
 
event_expression
	: expression
	| VL_POSEDGE scalar_event_expression
	| VL_NEGEDGE scalar_event_expression
	| event_expression VL_OR event_expression
	;
 
scalar_event_expression
	: expression
	;