342 lines
6.1 KiB
Plaintext
342 lines
6.1 KiB
Plaintext
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
/* $Header$ */
|
|
/* EXPRESSION SYNTAX PARSER */
|
|
|
|
{
|
|
#include "arith.h"
|
|
#include "LLlex.h"
|
|
#include "type.h"
|
|
#include "idf.h"
|
|
#include "label.h"
|
|
#include "expr.h"
|
|
#include "noRoption.h"
|
|
|
|
extern char options[];
|
|
extern struct expr *intexpr();
|
|
}
|
|
|
|
/* 7.1 */
|
|
primary(register struct expr **expp;) :
|
|
IDENTIFIER
|
|
{dot2expr(expp);}
|
|
|
|
|
constant(expp)
|
|
|
|
|
STRING
|
|
{dot2expr(expp);}
|
|
|
|
|
'(' expression(expp) ')'
|
|
{(*expp)->ex_flags |= EX_PARENS;}
|
|
;
|
|
|
|
secundary(register struct expr **expp;) :
|
|
primary(expp)
|
|
[
|
|
index_pack(expp)
|
|
|
|
|
parameter_pack(expp)
|
|
|
|
|
selection(expp)
|
|
]*
|
|
;
|
|
|
|
index_pack(struct expr **expp;)
|
|
{struct expr *e1;}
|
|
:
|
|
'[' expression(&e1) ']'
|
|
{ch7bin(expp, '[', e1);}
|
|
;
|
|
|
|
parameter_pack(struct expr **expp;)
|
|
{struct expr *e1 = 0;}
|
|
:
|
|
'(' parameter_list(&e1)? ')'
|
|
{ch7bin(expp, '(', e1);}
|
|
;
|
|
|
|
selection(struct expr **expp;)
|
|
{int oper; struct idf *idf;}
|
|
:
|
|
[ '.' | ARROW ]
|
|
{oper = DOT;}
|
|
identifier(&idf)
|
|
{ch7sel(expp, oper, idf);}
|
|
;
|
|
|
|
parameter_list(struct expr **expp;)
|
|
{struct expr *e1 = 0;}
|
|
:
|
|
assignment_expression(expp)
|
|
{any2opnd(expp, PARCOMMA);}
|
|
[ ','
|
|
assignment_expression(&e1)
|
|
{any2opnd(&e1, PARCOMMA);}
|
|
{ch7bin(expp, PARCOMMA, e1);}
|
|
]*
|
|
;
|
|
|
|
/* 7.2 */
|
|
postfixed(struct expr **expp;)
|
|
{int oper;}
|
|
:
|
|
secundary(expp)
|
|
[
|
|
postop(&oper)
|
|
{ch7incr(expp, oper);}
|
|
|
|
|
empty
|
|
]
|
|
;
|
|
|
|
%first first_of_type_specifier, type_specifier;
|
|
|
|
unary(register struct expr **expp;)
|
|
{struct type *tp; int oper;}
|
|
:
|
|
%if (first_of_type_specifier(AHEAD))
|
|
cast(&tp) unary(expp)
|
|
{ ch7cast(expp, CAST, tp);
|
|
(*expp)->ex_flags |= EX_CAST;
|
|
}
|
|
|
|
|
postfixed(expp)
|
|
|
|
|
unop(&oper) unary(expp)
|
|
{ch7mon(oper, expp);}
|
|
|
|
|
size_of(expp)
|
|
;
|
|
|
|
size_of(register struct expr **expp;)
|
|
{struct type *tp;}
|
|
:
|
|
SIZEOF
|
|
[%if (first_of_type_specifier(AHEAD))
|
|
cast(&tp)
|
|
{
|
|
*expp = intexpr(size_of_type(tp, "type"), INT);
|
|
(*expp)->ex_flags |= EX_SIZEOF;
|
|
}
|
|
|
|
|
unary(expp)
|
|
{ch7mon(SIZEOF, expp);}
|
|
]
|
|
;
|
|
|
|
/* 7.3-7.12 */
|
|
/* The set of operators in C is stratified in 15 levels, with level
|
|
N being treated in RM 7.N. In principle each operator is
|
|
assigned a rank, ranging from 1 to 15. Such an expression can
|
|
be parsed by a construct like:
|
|
binary_expression(int maxrank;)
|
|
{int oper;}
|
|
:
|
|
binary_expression(maxrank - 1)
|
|
[%if (rank_of(DOT) <= maxrank)
|
|
binop(&oper)
|
|
binary_expression(rank_of(oper)-1)
|
|
]?
|
|
;
|
|
except that some call of 'unary' is necessary, depending on the
|
|
grammar.
|
|
|
|
This simple view is marred by three complications:
|
|
1. Level 15 (comma operator) is not allowed in many
|
|
contexts and is different.
|
|
2. Level 13 (conditional operator) is a ternary operator,
|
|
which does not fit this scheme at all.
|
|
3. Level 14 (assignment operators) group right-to-left, as
|
|
opposed to 2-12, which group left-to-right (or are
|
|
immaterial).
|
|
4. The operators in level 14 start with operators in levels
|
|
2-13 (RM 7.14: The two parts of a compound assignment
|
|
operator are separate tokens.) This causes LL1 problems.
|
|
This forces us to have four rules:
|
|
binary_expression for level 2-12
|
|
conditional_expression for level 13
|
|
assignment_expression for level 14 and
|
|
expression for the most general expression
|
|
*/
|
|
|
|
binary_expression(int maxrank; struct expr **expp;)
|
|
{int oper; struct expr *e1;}
|
|
:
|
|
unary(expp)
|
|
[%while (rank_of(DOT) <= maxrank && AHEAD != '=')
|
|
/* '?', '=', and ',' are no binops, and the test
|
|
for AHEAD != '=' keeps the other assignment
|
|
operators out
|
|
*/
|
|
binop(&oper)
|
|
binary_expression(rank_of(oper)-1, &e1)
|
|
{
|
|
ch7bin(expp, oper, e1);
|
|
}
|
|
]*
|
|
;
|
|
|
|
/* 7.13 */
|
|
conditional_expression(struct expr **expp;)
|
|
/* There is some unfortunate disagreement about what is allowed
|
|
between the '?' and the ':' of a conditional_expression.
|
|
Although the Ritchie compiler does not even allow
|
|
conditional_expressions there, some other compilers (e.g., VAX)
|
|
accept a full assignment_expression there, and programs
|
|
(like, e.g., emacs) rely on it. So we have little choice.
|
|
*/
|
|
{struct expr *e1 = 0, *e2 = 0;}
|
|
:
|
|
/* allow all binary operators */
|
|
binary_expression(rank_of('?') - 1, expp)
|
|
[ '?'
|
|
expression(&e1)
|
|
{
|
|
#ifndef NOROPTION
|
|
check_conditional(e1, '?', "between ? and :");
|
|
#endif
|
|
}
|
|
':'
|
|
assignment_expression(&e2)
|
|
{
|
|
#ifndef NOROPTION
|
|
check_conditional(e2, '=', "after :");
|
|
#endif
|
|
ch7bin(&e1, ':', e2);
|
|
opnd2test(expp, '?');
|
|
ch7bin(expp, '?', e1);
|
|
}
|
|
]?
|
|
;
|
|
|
|
/* 7.14 */
|
|
assignment_expression(struct expr **expp;)
|
|
{
|
|
int oper;
|
|
struct expr *e1 = 0;
|
|
}
|
|
:
|
|
conditional_expression(expp)
|
|
[%prefer /* (rank_of(DOT) <= maxrank) for any asgnop */
|
|
asgnop(&oper)
|
|
assignment_expression(&e1)
|
|
{ch7asgn(expp, oper, e1);}
|
|
|
|
|
empty /* LLgen artefact ??? */
|
|
]
|
|
;
|
|
|
|
/* 7.15 */
|
|
expression(struct expr **expp;)
|
|
{struct expr *e1;}
|
|
:
|
|
assignment_expression(expp)
|
|
[ ','
|
|
assignment_expression(&e1)
|
|
{
|
|
ch7bin(expp, ',', e1);
|
|
}
|
|
]*
|
|
;
|
|
|
|
unop(int *oper;) :
|
|
['*' | '&' | '-' | '!' | '~' | PLUSPLUS | MINMIN]
|
|
{*oper = DOT;}
|
|
;
|
|
|
|
postop(int *oper;):
|
|
PLUSPLUS {*oper = POSTINCR;}
|
|
|
|
|
MINMIN {*oper = POSTDECR;}
|
|
;
|
|
|
|
multop:
|
|
'*' | '/' | '%'
|
|
;
|
|
|
|
addop:
|
|
'+' | '-'
|
|
;
|
|
|
|
shiftop:
|
|
LEFT | RIGHT
|
|
;
|
|
|
|
relop:
|
|
'<' | '>' | LESSEQ | GREATEREQ
|
|
;
|
|
|
|
eqop:
|
|
EQUAL | NOTEQUAL
|
|
;
|
|
|
|
arithop:
|
|
multop | addop | shiftop
|
|
|
|
|
'&' | '^' | '|'
|
|
;
|
|
|
|
binop(int *oper;) :
|
|
[ arithop | relop | eqop | AND | OR ]
|
|
{*oper = DOT;}
|
|
;
|
|
|
|
asgnop(register int *oper;):
|
|
'=' {*oper = DOT;}
|
|
|
|
|
'+' '=' {*oper = PLUSAB;}
|
|
|
|
|
'-' '=' {*oper = MINAB;}
|
|
|
|
|
'*' '=' {*oper = TIMESAB;}
|
|
|
|
|
'/' '=' {*oper = DIVAB;}
|
|
|
|
|
'%' '=' {*oper = MODAB;}
|
|
|
|
|
LEFT '=' {*oper = LEFTAB;}
|
|
|
|
|
RIGHT '=' {*oper = RIGHTAB;}
|
|
|
|
|
'&' '=' {*oper = ANDAB;}
|
|
|
|
|
'^' '=' {*oper = XORAB;}
|
|
|
|
|
'|' '=' {*oper = ORAB;}
|
|
|
|
|
[ PLUSAB | MINAB | TIMESAB | DIVAB | MODAB |
|
|
LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
|
|
{
|
|
char *symbol2str();
|
|
|
|
warning("old-fashioned assignment operator, use %s",
|
|
symbol2str(DOT));
|
|
*oper = DOT;
|
|
}
|
|
;
|
|
|
|
constant(struct expr **expp;) :
|
|
[
|
|
INTEGER
|
|
|
|
|
FLOATING
|
|
] {dot2expr(expp);}
|
|
;
|
|
|
|
/* 15 */
|
|
constant_expression (struct expr **expp;) :
|
|
assignment_expression(expp)
|
|
{chk_cst_expr(expp);}
|
|
;
|
|
|
|
identifier(struct idf **idfp;) :
|
|
[
|
|
IDENTIFIER
|
|
|
|
|
TYPE_IDENTIFIER
|
|
]
|
|
{*idfp = dot.tk_idf;}
|
|
;
|