Files
epics-base/src/sequencer/snc.y
1997-06-25 06:47:47 +00:00

388 lines
12 KiB
Plaintext

%{
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
snc.y,v 1.2 1995/06/27 15:26:07 wright Exp
ENVIRONMENT: UNIX
HISTORY:
20nov91,ajk Added new "option" statement.
08nov93,ajk Implemented additional declarations (see VC_CLASS in parse.h).
08nov93,ajk Implemented assignment of array elements to pv's.
02may93,ajk Removed "parameter" definition for functions, and added "%prec"
qualifications to some "expr" definitions.
31may94,ajk Changed method for handling global C code.
20jul95,ajk Added "unsigned" types (see UNSIGNED token).
11jul96,ajk Added character constants (CHAR_CONST).
***************************************************************************/
/* SNC - State Notation Compiler.
* The general structure of a state program is:
* program-name
* declarations
* ss { state { event { action ...} new-state } ... } ...
*
* The following yacc definitions call the various parsing routines, which
* are coded in the file "parse.c". Their major action is to build
* a structure for each SNL component (state, event, action, etc.) and
* build linked lists from these structures. The linked lists have a
* hierarchical structure corresponding to the SNL block structure.
* For instance, a "state" structure is linked to a chain of "event",
* structures, which are, in turn, linked to a chain of "action"
* structures.
* The lexical analyser (see snc_lax.l) reads the input
* stream and passes tokens to the yacc-generated code. The snc_lex
* and parsing routines may also pass data elements that take on one
* of the types defined under the %union definition.
*
*/
#include <stdio.h>
#include <ctype.h>
#include "parse.h"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif /* TRUE */
extern int line_num; /* input file line no. */
%}
%start state_program
%union
{
int ival;
char *pchar;
void *pval;
Expr *pexpr;
}
%token <pchar> STATE STATE_SET
%token <pchar> NUMBER NAME
%token <pchar> CHAR_CONST
%token <pchar> DEBUG_PRINT
%token PROGRAM EXIT OPTION
%token R_SQ_BRACKET L_SQ_BRACKET
%token BAD_CHAR L_BRACKET R_BRACKET
%token COLON SEMI_COLON EQUAL
%token L_PAREN R_PAREN PERIOD POINTER COMMA OR AND
%token MONITOR ASSIGN TO WHEN
%token UNSIGNED CHAR SHORT INT LONG FLOAT DOUBLE STRING_DECL
%token EVFLAG SYNC
%token ASTERISK AMPERSAND
%token AUTO_INCR AUTO_DECR
%token PLUS MINUS SLASH GT GE EQ LE LT NE NOT BIT_OR BIT_AND
%token L_SHIFT R_SHIFT COMPLEMENT MODULO
%token PLUS_EQUAL MINUS_EQUAL MULT_EQUAL DIV_EQUAL AND_EQUAL OR_EQUAL
%token MODULO_EQUAL LEFT_EQUAL RIGHT_EQUAL CMPL_EQUAL
%token <pchar> STRING
%token <pchar> C_STMT
%token IF ELSE WHILE FOR BREAK
%token PP_SYMBOL CR
%type <ival> type
%type <pchar> subscript binop asgnop unop
%type <pexpr> state_set_list state_set state_list state transition_list transition
%type <pexpr> expr compound_expr assign_list bracked_expr
%type <pexpr> statement stmt_list compound_stmt if_stmt else_stmt while_stmt
%type <pexpr> for_stmt escaped_c_list
/* precidence rules for expr evaluation */
%right EQUAL COMMA
%left OR AND
%left GT GE EQ NE LE LT
%left PLUS MINUS
%left ASTERISK SLASH
%left NOT UOP /* unary operators: e.g. -x */
%left SUBSCRIPT
%% /* Begin rules */
state_program /* define a state program */
: program_name definitions state_set_list { program($3); }
| program_name definitions state_set_list global_c { program($3); }
| pp_code program_name definitions state_set_list { program($4); }
| pp_code program_name definitions state_set_list global_c{ program($4); }
| error { snc_err("state program"); }
;
program_name /* program name */
: PROGRAM NAME { program_name($2, ""); }
| PROGRAM NAME L_PAREN STRING R_PAREN { program_name($2, $4); }
;
definitions /* definitions block */
: defn_stmt
| definitions defn_stmt
;
defn_stmt /* individual definitions for SNL (preceeds state sets) */
: assign_stmt
| monitor_stmt
| decl_stmt
| debug_stmt
| sync_stmt
| option_stmt
| defn_c_stmt
| pp_code
| error { snc_err("definitions/declarations"); }
;
assign_stmt /* assign <var name> to <db name>; */
: ASSIGN NAME TO STRING SEMI_COLON { assign_single($2, $4); }
/* assign <var name>[<n>] to <db name>; */
| ASSIGN NAME subscript TO STRING SEMI_COLON { assign_subscr($2, $3, $5); }
/* assign <var name> to {<db name>, ... }; */
| ASSIGN NAME TO L_BRACKET assign_list R_BRACKET SEMI_COLON
{ assign_list($2, $5); }
;
assign_list /* {"<db name>", .... } */
: STRING { $$ = expression(E_STRING, $1, 0, 0); }
| assign_list COMMA STRING
{ $$ = link_expr($1, expression(E_STRING, $3, 0, 0)); }
;
monitor_stmt /* variable to be monitored; delta is optional */
: MONITOR NAME SEMI_COLON { monitor_stmt($2, NULL); }
| MONITOR NAME subscript SEMI_COLON { monitor_stmt($2, $3); }
;
subscript /* e.g. [10] */
: L_SQ_BRACKET NUMBER R_SQ_BRACKET { $$ = $2; }
;
debug_stmt
: DEBUG_PRINT NUMBER SEMI_COLON { set_debug_print($2); }
;
decl_stmt /* variable declarations (e.g. float x[20];)
* decl_stmt(type, class, name, <1-st dim>, <2-nd dim>, value) */
: type NAME SEMI_COLON
{ decl_stmt($1, VC_SIMPLE, $2, NULL, NULL, NULL); }
| type NAME EQUAL NUMBER SEMI_COLON
{ decl_stmt($1, VC_SIMPLE, $2, NULL, NULL, $4 ); }
| type NAME subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAY1, $2, $3, NULL, NULL); }
| type NAME subscript subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAY2, $2, $3, $4, NULL); }
| type ASTERISK NAME SEMI_COLON
{ decl_stmt($1, VC_POINTER, $3, NULL, NULL, NULL); }
| type ASTERISK NAME subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAYP, $3, $4, NULL, NULL); }
;
type /* types for variables defined in SNL */
: CHAR { $$ = V_CHAR; }
| SHORT { $$ = V_SHORT; }
| INT { $$ = V_INT; }
| LONG { $$ = V_LONG; }
| UNSIGNED CHAR { $$ = V_UCHAR; }
| UNSIGNED SHORT { $$ = V_USHORT; }
| UNSIGNED INT { $$ = V_UINT; }
| UNSIGNED LONG { $$ = V_ULONG; }
| FLOAT { $$ = V_FLOAT; }
| DOUBLE { $$ = V_DOUBLE; }
| STRING_DECL { $$ = V_STRING; }
| EVFLAG { $$ = V_EVFLAG; }
;
sync_stmt /* sync <variable> <event flag> */
: SYNC NAME TO NAME SEMI_COLON { sync_stmt($2, NULL, $4); }
| SYNC NAME NAME SEMI_COLON { sync_stmt($2, NULL, $3); }
| SYNC NAME subscript TO NAME SEMI_COLON { sync_stmt($2, $3, $5); }
| SYNC NAME subscript NAME SEMI_COLON { sync_stmt($2, $3, $4); }
;
defn_c_stmt /* escaped C in definitions */
: escaped_c_list { defn_c_stmt($1); }
;
option_stmt /* option +/-<option>; e.g. option +a; */
: OPTION PLUS NAME SEMI_COLON { option_stmt($3, TRUE); }
| OPTION MINUS NAME SEMI_COLON { option_stmt($3, FALSE); }
;
state_set_list /* a program body is one or more state sets */
: state_set { $$ = $1; }
| state_set_list state_set { $$ = link_expr($1, $2); }
;
state_set /* define a state set */
: STATE_SET NAME L_BRACKET state_list R_BRACKET
{ $$ = expression(E_SS, $2, $4, 0); }
| EXIT L_BRACKET stmt_list R_BRACKET
{ exit_code($3); $$ = 0; }
| error { snc_err("state set"); }
;
state_list /* define a state set body (one or more states) */
: state { $$ = $1; }
| state_list state { $$ = link_expr($1, $2); }
| error { snc_err("state set"); }
;
state /* a block that defines a single state */
: STATE NAME L_BRACKET transition_list R_BRACKET
{ $$ = expression(E_STATE, $2, $4, 0); }
| error { snc_err("state block"); }
;
transition_list /* all transitions for one state */
: transition { $$ = $1; }
| transition_list transition { $$ = link_expr($1, $2); }
| error { snc_err("transition"); }
;
transition /* define a transition ("when" statment ) */
: WHEN L_PAREN expr R_PAREN L_BRACKET stmt_list R_BRACKET STATE NAME
{ $$ = expression(E_WHEN, $9, $3, $6); }
;
expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
/* Expr *expression(int type, char *value, Expr *left, Expr *right) */
: compound_expr { $$ = $1; }
| expr binop expr %prec UOP { $$ = expression(E_BINOP, $2, $1, $3); }
| expr asgnop expr { $$ = expression(E_ASGNOP, $2, $1, $3); }
| unop expr %prec UOP { $$ = expression(E_UNOP, $1, $2, 0); }
| AUTO_INCR expr %prec UOP { $$ = expression(E_PRE, "++", $2, 0); }
| AUTO_DECR expr %prec UOP { $$ = expression(E_PRE, "--", $2, 0); }
| expr AUTO_INCR %prec UOP { $$ = expression(E_POST, "++", $1, 0); }
| expr AUTO_DECR %prec UOP { $$ = expression(E_POST, "--", $1, 0); }
| NUMBER { $$ = expression(E_CONST, $1, 0, 0); }
| CHAR_CONST { $$ = expression(E_CONST, $1, 0, 0); }
| STRING { $$ = expression(E_STRING, $1, 0, 0); }
| NAME { $$ = expression(E_VAR, $1, 0, 0); }
| NAME L_PAREN expr R_PAREN { $$ = expression(E_FUNC, $1, $3, 0); }
| EXIT L_PAREN expr R_PAREN { $$ = expression(E_FUNC, "exit", $3, 0); }
| L_PAREN expr R_PAREN { $$ = expression(E_PAREN, "", $2, 0); }
| expr bracked_expr %prec SUBSCRIPT { $$ = expression(E_SUBSCR, "", $1, $2); }
| /* empty */ { $$ = 0; }
;
compound_expr
: expr COMMA expr { $$ = link_expr($1, $3); }
| compound_expr COMMA expr { $$ = link_expr($1, $3); }
;
bracked_expr /* e.g. [k-1] */
: L_SQ_BRACKET expr R_SQ_BRACKET { $$ = $2; }
;
unop /* Unary operators */
: PLUS { $$ = "+"; }
| MINUS { $$ = "-"; }
| ASTERISK { $$ = "*"; }
| AMPERSAND { $$ = "&"; }
| NOT { $$ = "!"; }
;
binop /* Binary operators */
: MINUS { $$ = "-"; }
| PLUS { $$ = "+"; }
| ASTERISK { $$ = "*"; }
| SLASH { $$ = "/"; }
| GT { $$ = ">"; }
| GE { $$ = ">="; }
| EQ { $$ = "=="; }
| NE { $$ = "!="; }
| LE { $$ = "<="; }
| LT { $$ = "<"; }
| OR { $$ = "||"; }
| AND { $$ = "&&"; }
| L_SHIFT { $$ = "<<"; }
| R_SHIFT { $$ = ">>"; }
| BIT_OR { $$ = "|"; }
| BIT_AND { $$ = "&"; }
| COMPLEMENT { $$ = "^"; }
| MODULO { $$ = "%"; }
| PERIOD { $$ = "."; } /* fudges structure elements */
| POINTER { $$ = "->"; } /* fudges ptr to structure elements */
;
asgnop /* Assignment operators */
: EQUAL { $$ = "="; }
| PLUS_EQUAL { $$ = "+="; }
| MINUS_EQUAL { $$ = "-="; }
| AND_EQUAL { $$ = "&="; }
| OR_EQUAL { $$ = "|="; }
| DIV_EQUAL { $$ = "/="; }
| MULT_EQUAL { $$ = "*="; }
| MODULO_EQUAL { $$ = "%="; }
| LEFT_EQUAL { $$ = "<<="; }
| RIGHT_EQUAL { $$ = ">>="; }
| CMPL_EQUAL { $$ = "^="; }
;
compound_stmt /* compound statement e.g. { ...; ...; ...; } */
: L_BRACKET stmt_list R_BRACKET { $$ = expression(E_CMPND, "",$2, 0); }
| error { snc_err("action statements"); }
;
stmt_list
: statement { $$ = $1; }
| stmt_list statement { $$ = link_expr($1, $2); }
| /* empty */ { $$ = 0; }
;
statement
: compound_stmt { $$ = $1; }
| expr SEMI_COLON { $$ = expression(E_STMT, "", $1, 0); }
| BREAK SEMI_COLON { $$ = expression(E_BREAK, "", 0, 0); }
| if_stmt { $$ = $1; }
| else_stmt { $$ = $1; }
| while_stmt { $$ = $1; }
| for_stmt { $$ = $1; }
| C_STMT { $$ = expression(E_TEXT, "", $1, 0); }
| pp_code { $$ = 0; }
| error { snc_err("action statement"); }
;
if_stmt
: IF L_PAREN expr R_PAREN statement { $$ = expression(E_IF, "", $3, $5); }
;
else_stmt
: ELSE statement { $$ = expression(E_ELSE, "", $2, 0); }
;
while_stmt
: WHILE L_PAREN expr R_PAREN statement { $$ = expression(E_WHILE, "", $3, $5); }
;
for_stmt
: FOR L_PAREN expr SEMI_COLON expr SEMI_COLON expr R_PAREN statement
{ $$ = expression(E_FOR, "", expression(E_X, "", $3, $5),
expression(E_X, "", $7, $9) ); }
;
pp_code /* pre-processor code (e.g. # 1 "test.st") */
: PP_SYMBOL NUMBER STRING CR { pp_code($2, $3, ""); }
| PP_SYMBOL NUMBER STRING NUMBER CR { pp_code($2, $3, $4); }
;
global_c
: escaped_c_list { global_c_stmt($1); }
;
escaped_c_list
: C_STMT { $$ = expression(E_TEXT, "", $1, 0); }
| escaped_c_list C_STMT { $$ = link_expr($1, expression(E_TEXT, "", $2, 0)); }
;
%%
#include "snc_lex.c"
static int yyparse (void);
/* yyparse() is static, so we create global access to it */
void Global_yyparse (void)
{
yyparse ();
}