* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)pas.y 5.4 (Berkeley) 1/3/88
* Yacc grammar for UNIX Pascal
* This grammar is processed by the commands in the shell script
* "gram" to yield parse tables and semantic routines in the file
* "y.tab.c" and a header defining the lexical tokens in "yy.h".
* In order for the syntactic error recovery possible with this
* grammar to work, the grammar must be processed by a yacc which
* has been modified to fully enumerate possibilities in states
* which involve the symbol "error".
* The parser used for Pascal also uses a different encoding of
* the test entries in the action table which speeds the parse.
* A version of yacc which will work for Pascal is included on
* the distribution table as "eyacc".
* The "gram" script also makes the following changes to the "y.tab.c"
* 1) Causes yyval to be declared int *.
* 2) Loads the variable yypv into a register as yyYpv so that
* the arguments $1, ... are available as yyYpv[1] etc.
* This produces much smaller code in the semantic actions.
* 3) Deletes the unused array yysterm.
* 4) Moves the declarations up to the flag line containing
* '##' to the file yy.h so that the routines which use
* these "magic numbers" don't have to all be compiled at
* 5) Creates the semantic restriction checking routine yyEactr
* by processing action lines containing `@@'.
* This compiler uses a different version of the yacc parser, a
* different yyerror which is called yerror, and requires more
* lookahead sets than normally provided by yacc.
* Source for the yacc used with this grammar is included on
* Some of the terminal declarations are out of the most natural
* alphabetic order because the error recovery
* will guess the first of equal cost non-terminals.
* This makes, e.g. YTO preferable to YDOWNTO.
YFOR YFORWARD YPROCEDURE YGOTO
YFUNCTION YPROG YRECORD YREPEAT
YSET YSTRING YTHEN YDOWNTO
YCASELAB YILLCH YEXTERN YLAST
* PRECEDENCE DECLARATIONS
* Highest precedence is the unary logical NOT.
* Next are the multiplying operators, signified by '*'.
* Lower still are the binary adding operators, signified by '+'.
* Finally, at lowest precedence and non-associative are the relationals.
%left '*' '/' YDIV YMOD YAND '&'
/* Copyright (c) 1979 Regents of the University of California */
/* static char sccsid[] = "@(#)pas.y 5.4 1/3/88"; */
* The following line marks the end of the yacc
* Constant definitions which are removed from
* y.tab.c and placed in the file y.tab.h.
/* Copyright (c) 1979 Regents of the University of California */
static char sccsid[] = "@(#)pas.y 5.4 1/3/88";
#include "tree_ty.h" /* must be included for yy.h */
prog_hedr decls block '.'
= funcend($1.nl_entry, $3.tr_entry, lineof($4.i_entry));
YPROG YID '(' id_list ')' ';'
= $$.nl_entry = funcbody(funchdr(tree5(T_PROG, lineof($1.i_entry), $2.tr_entry, fixlist($4.tr_entry), TR_NIL)));
= $$.nl_entry = funcbody(funchdr(tree5(T_PROG, lineof($1.i_entry), $2.tr_entry, TR_NIL, TR_NIL)));
yyPerror("Malformed program statement", PPROG);
* Should make a program statement
* with "input" and "output" here.
$$.nl_entry = funcbody(funchdr(tree5(T_PROG, lineof($1.i_entry), TR_NIL, TR_NIL, TR_NIL)));
$$.tr_entry = tree3(T_BSTL, lineof($1.i_entry), fixlist($2.tr_entry));
brerror($1.i_entry, "begin");
constend(), typeend(), varend(), trfree();
yyPerror("Malformed declaration", PDECL);
= label(fixlist($2.tr_entry), lineof($1.i_entry));
= $$.tr_entry = newlist($1.i_entry == NIL ? TR_NIL :
(struct tnode *) *hash($1.cptr, 1));
= $$.tr_entry = addlist($1.tr_entry, $3.i_entry == NIL ?
TR_NIL : (struct tnode *) *hash($3.cptr, 1));
= constbeg($1.i_entry, lineof($1.i_entry)),
constant(lineof($3.i_entry), $2.cptr, $4.tr_entry);
const_decl YID '=' const ';'
= constant(lineof($3.i_entry), $2.cptr, $4.tr_entry);
yyPerror("Malformed const declaration", PDECL);
= typebeg($1.i_entry, line2of($2.i_entry)), type(lineof($3.i_entry), $2.cptr, $4.tr_entry);
type_decl YID '=' type ';'
= type(lineof($3.i_entry), $2.cptr, $4.tr_entry);
typebeg($1.i_entry, line2of($1.i_entry));
yyPerror("Malformed type declaration", PDECL);
YVAR id_list ':' type ';'
= varbeg($1.i_entry, line2of($3.i_entry)), var(lineof($3.i_entry), fixlist($2.tr_entry), $4.tr_entry);
var_decl id_list ':' type ';'
= var(lineof($3.i_entry), fixlist($2.tr_entry), $4.tr_entry);
varbeg($1.i_entry, line2of($1.i_entry));
yyPerror("Malformed var declaration", PDECL);
* PROCEDURE AND FUNCTION DECLARATION PART
= (void) funcext($1.nl_entry);
= funcend($1.nl_entry, $3.tr_entry, lineof($4.i_entry));
= (void) funcbody($1.nl_entry);
porf YID params ftype ';'
= $$.nl_entry = funchdr(tree5($1.i_entry, lineof($5.i_entry),
$2.tr_entry, $3.tr_entry, $4.tr_entry));
= $$.tr_entry = fixlist($2.tr_entry);
= $$.tr_entry = tree3(T_PVAL, (int) fixlist($1.tr_entry), $3.tr_entry);
= $$.tr_entry = tree3(T_PVAR, (int) fixlist($2.tr_entry), $4.tr_entry);
YFUNCTION id_list params ftype
= $$.tr_entry = tree5(T_PFUNC, (int) fixlist($2.tr_entry),
$4.tr_entry, $3.tr_entry,
(struct tnode *) lineof($1.i_entry));
YPROCEDURE id_list params ftype
= $$.tr_entry = tree5(T_PPROC, (int) fixlist($2.tr_entry),
$4.tr_entry, $3.tr_entry,
(struct tnode *) lineof($1.i_entry));
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = tree2(T_CSTRNG, $1.i_entry);
= $$.tr_entry = tree2(T_PLUSC, $2.i_entry);
= $$.tr_entry = tree2(T_MINUSC, $2.i_entry);
= $$.tr_entry = tree2(T_ID, $1.i_entry);
= $$.tr_entry = tree2(T_CINT, $1.i_entry);
= $$.tr_entry = tree2(T_CBINT, $1.i_entry);
= $$.tr_entry = tree2(T_CFINT, $1.i_entry);
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = tree3(T_TYPTR, lineof($1.i_entry), tree2(T_ID,
= $$.tr_entry = tree3(T_TYPACK, lineof($1.i_entry), $2.tr_entry);
= $$.tr_entry = tree3(T_TYSCAL, lineof($1.i_entry), fixlist($2.tr_entry));
= $$.tr_entry = tree4(T_TYRANG, lineof($2.i_entry), $1.tr_entry,
YARRAY '[' simple_type_list ']' YOF type
= $$.tr_entry = tree4(T_TYARY, lineof($1.i_entry),
fixlist($3.tr_entry), $6.tr_entry);
= $$.tr_entry = tree3(T_TYFILE, lineof($1.i_entry), $3.tr_entry);
= $$.tr_entry = tree3(T_TYSET, lineof($1.i_entry), $3.tr_entry);
$$.tr_entry = setuptyrec( lineof( $1.i_entry ) , $2.tr_entry);
brerror($1.i_entry, "record");
= $$.tr_entry = newlist($1.tr_entry);
simple_type_list ',' simple_type
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = tree4(T_FLDLST, lineof(NIL),
fixlist($1.tr_entry), $2.tr_entry);
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= yyPerror("Malformed record declaration", PDECL);
= $$.tr_entry = tree4(T_RFIELD, lineof($2.i_entry),
fixlist($1.tr_entry), $3.tr_entry);
YCASE type_id YOF variant_list
= $$.tr_entry = tree5(T_TYVARPT, lineof($1.i_entry), TR_NIL,
$2.tr_entry, fixlist($4.tr_entry));
YCASE YID ':' type_id YOF variant_list
= $$.tr_entry = tree5(T_TYVARPT, lineof($1.i_entry),
$2.tr_entry, $4.tr_entry,
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= yyPerror("Malformed record declaration", PDECL);
const_list ':' '(' field_list ')'
= $$.tr_entry = tree4(T_TYVARNT,lineof($2.i_entry), fixlist($1.tr_entry),
= $$.tr_entry = newlist($1.tr_entry);
if ((p = $1.tr_entry) != TR_NIL && (q = p->list_node.list)->tag == T_IFX) {
q->if_node.else_stmnt = $2.tr_entry;
$$.tr_entry= addlist($1.tr_entry, $2.tr_entry);
= if ((q = $1.tr_entry) != TR_NIL && (p = q->list_node.list) != TR_NIL && p->tag == T_IF) {
if (yyshifts >= 2 && yychar == YELSE) {
copy((char *) (&Y), (char *) (&OY), sizeof Y);
yerror("Deleted ';' before keyword else");
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
yyPerror("Malformed statement in case", PSTAT);
= $$.tr_entry = tree4(T_CSTAT, lineof($2.i_entry),
fixlist($1.tr_entry), $3.tr_entry);
= $$.tr_entry = tree4(T_CSTAT, lineof($1.i_entry), TR_NIL,
= $$.tr_entry = tree4(T_LABEL, lineof($2.i_entry),
$1.tr_entry == TR_NIL ? TR_NIL :
(struct tnode *) *hash($1.cptr, 1), $3.tr_entry);
= $$.tr_entry = tree4(T_PCALL, lineof(yyline), $1.tr_entry,
proc_id '(' wexpr_list ')'
= $$.tr_entry = tree4(T_PCALL, lineof($2.i_entry), $1.tr_entry,
$$.tr_entry = tree3(T_BLOCK, lineof($1.i_entry),
brerror($1.i_entry, "begin");
YCASE expr YOF cstat_list YEND
$$.tr_entry = tree4(T_CASE, lineof($1.i_entry),
$2.tr_entry, fixlist($4.tr_entry));
brerror($1.i_entry, "case");
= $$.tr_entry = tree4(T_WITH, lineof($1.i_entry),
fixlist($2.tr_entry), $4.tr_entry);
= $$.tr_entry = tree4(T_WHILE, lineof($1.i_entry), $2.tr_entry,
YREPEAT stat_list YUNTIL expr
= $$.tr_entry = tree4(T_REPEAT, lineof($3.i_entry),
fixlist($2.tr_entry), $4.tr_entry);
YFOR assign YTO expr YDO stat
= $$.tr_entry = tree5(T_FORU, lineof($1.i_entry), $2.tr_entry,
$4.tr_entry, $6.tr_entry);
YFOR assign YDOWNTO expr YDO stat
= $$.tr_entry = tree5(T_FORD, lineof($1.i_entry), $2.tr_entry,
$4.tr_entry, $6.tr_entry);
= $$.tr_entry = tree3(T_GOTO, lineof($1.i_entry),
(struct tnode *) *hash($2.cptr, 1));
= $$.tr_entry = tree5(T_IF, lineof($1.i_entry), $2.tr_entry,
YIF expr YTHEN stat YELSE stat
= $$.tr_entry = tree5(T_IFEL, lineof($1.i_entry), $2.tr_entry,
$4.tr_entry, $6.tr_entry);
yyPerror("Malformed statement", PSTAT);
= $$.tr_entry = tree4(T_ASGN, lineof($2.i_entry), $1.tr_entry,
yyPerror("Missing/malformed expression", PEXPR);
expr relop expr %prec '<'
= $$.tr_entry = tree4($2.i_entry,
$1.tr_entry->expr_node.const_tag == SAWCON ?
$3.tr_entry->expr_node.const_tag :
$1.tr_entry->expr_node.const_tag,
$1.tr_entry, $3.tr_entry);
= $$.tr_entry = tree3(T_PLUS, $2.tr_entry->expr_node.const_tag,
= $$.tr_entry = tree3(T_MINUS, $2.tr_entry->expr_node.const_tag,
expr addop expr %prec '+'
= $$.tr_entry = tree4($2.i_entry,
$1.tr_entry->expr_node.const_tag == SAWCON ?
$3.tr_entry->expr_node.const_tag :
$1.tr_entry->expr_node.const_tag, $1.tr_entry,
expr divop expr %prec '*'
= $$.tr_entry = tree4($2.i_entry,
$1.tr_entry->expr_node.const_tag == SAWCON ?
$3.tr_entry->expr_node.const_tag :
$1.tr_entry->expr_node.const_tag, $1.tr_entry,
= $$.tr_entry = tree2(T_NIL, NOCON);
= $$.tr_entry = tree3(T_STRNG, SAWCON, $1.tr_entry);
= $$.tr_entry = tree3(T_INT, NOCON, $1.tr_entry);
= $$.tr_entry = tree3(T_BINT, NOCON, $1.tr_entry);
= $$.tr_entry = tree3(T_FINT, NOCON, $1.tr_entry);
func_id '(' wexpr_list ')'
= $$.tr_entry = tree4(T_FCALL, NOCON, $1.tr_entry,
= $$.tr_entry = $2.tr_entry;
= $$.tr_entry = tree3(T_NOT, NOCON, $2.tr_entry);
= $$.tr_entry = tree3(T_CSET, SAWCON, fixlist($2.tr_entry));
= $$.tr_entry = tree3(T_CSET, SAWCON, TR_NIL);
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = tree3(T_RANG, $1.i_entry, $3.tr_entry);
@@ return (identis(var, VAR));
$$.tr_entry = setupvar($1.cptr, TR_NIL);
= $1.tr_entry->var_node.qual =
fixlist($1.tr_entry->var_node.qual);
array_id '[' expr_list ']'
= $$.tr_entry = setupvar($1.cptr, tree2(T_ARY,
(int) fixlist($3.tr_entry)));
qual_var '[' expr_list ']'
= $1.tr_entry->var_node.qual =
addlist($1.tr_entry->var_node.qual,
tree2(T_ARY, (int) fixlist($3.tr_entry)));
= $$.tr_entry = setupvar($1.cptr, setupfield($3.tr_entry,
= $1.tr_entry->var_node.qual =
addlist($1.tr_entry->var_node.qual,
setupfield($3.tr_entry, TR_NIL));
= $$.tr_entry = setupvar($1.cptr, tree1(T_PTR));
= $1.tr_entry->var_node.qual =
addlist($1.tr_entry->var_node.qual, tree1(T_PTR));
* Expression with write widths
= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry, TR_NIL);
= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry,
= $$.tr_entry = tree4(T_WEXP, $1.i_entry, TR_NIL, $2.tr_entry);
= $$.tr_entry = tree4(T_WEXP, $1.i_entry, $3.tr_entry,
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
'<' '>' = $$.i_entry = T_NE;
'<' '=' = $$.i_entry = T_LE;
'>' '=' = $$.i_entry = T_GE;
'+' = $$.i_entry = T_ADD;
'-' = $$.i_entry = T_SUB;
'*' = $$.i_entry = T_MULT;
'/' = $$.i_entry = T_DIVD;
YDIV = $$.i_entry = T_DIV;
YMOD = $$.i_entry = T_MOD;
YAND = $$.i_entry = T_AND;
'&' = $$.i_entry = T_AND;
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
= $$.tr_entry = newlist($1.tr_entry);
= $$.tr_entry = addlist($1.tr_entry, $3.tr_entry);
* Identifier productions with semantic restrictions
* For these productions, the characters @@ signify
* that the associated C statement is to provide
* the semantic restriction for this reduction.
* These lines are made into a procedure yyEactr, similar to
* yyactr, which determines whether the corresponding reduction
* is permitted, or whether an error is to be signaled.
* A zero return from yyEactr is considered an error.
* YyEactr is called with an argument "var" giving the string
* name of the variable in question, essentially $1, although
* $1 will not work because yyEactr is called from loccor in
= @@ return (identis(var, CONST));
@@ return (identis(var, TYPE));
$$.tr_entry = tree3(T_TYID, lineof(yyline), $1.tr_entry);
= @@ return (identis(var, VAR));
= @@ return (identis(var, ARRAY));
= @@ return (identis(var, PTRFILE));
= @@ return (identis(var, RECORD));
= @@ return (identis(var, FIELD));
= @@ return (identis(var, PROC));
= @@ return (identis(var, FUNC));