NetBSD/usr.bin/lex/parse.y

914 lines
17 KiB
Plaintext
Raw Normal View History

1993-03-21 12:45:37 +03:00
/* parse.y - parser for flex input */
1995-05-05 09:35:08 +04:00
%token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
%token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
%token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
%token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
1993-03-21 12:45:37 +03:00
%{
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
1993-05-04 11:44:39 +04:00
* Vern Paxson.
1993-03-21 12:45:37 +03:00
*
* The United States Government has rights in this work pursuant
* to contract no. DE-AC03-76SF00098 between the United States
* Department of Energy and the University of California.
*
1993-05-04 11:44:39 +04:00
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1993-03-21 12:45:37 +03:00
*/
1998-01-05 08:15:43 +03:00
/* $NetBSD: parse.y,v 1.9 1998/01/05 05:15:57 perry Exp $ */
1993-12-02 22:17:24 +03:00
/* Some versions of bison are broken in that they use alloca() but don't
* declare it properly. The following is the patented (just kidding!)
* #ifdef chud to fix the problem, courtesy of Francois Pinard.
*/
#ifdef YYBISON
1995-05-05 09:35:08 +04:00
/* AIX requires this to be the first thing in the file. What a piece. */
# ifdef _AIX
1993-12-02 22:17:24 +03:00
#pragma alloca
1995-05-05 09:35:08 +04:00
# endif
#endif
#include "flexdef.h"
/* The remainder of the alloca() cruft has to come after including flexdef.h,
* so HAVE_ALLOCA_H is (possibly) defined.
*/
#ifdef YYBISON
# ifdef __GNUC__
# ifndef alloca
# define alloca __builtin_alloca
# endif
# else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef __hpux
void *alloca ();
# else
# ifdef __TURBOC__
# include <malloc.h>
# else
1993-12-02 22:17:24 +03:00
char *alloca ();
1995-05-05 09:35:08 +04:00
# endif
# endif
# endif
# endif
#endif
1993-12-02 22:17:24 +03:00
/* Bletch, ^^^^ that was ugly! */
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
int *scon_stk;
int scon_stk_ptr;
1993-03-21 12:45:37 +03:00
static int madeany = false; /* whether we've made the '.' character class */
int previous_continued_action; /* whether the previous rule's action was '|' */
1995-05-05 09:35:08 +04:00
/* Expand a POSIX character class expression. */
#define CCL_EXPR(func) \
{ \
int c; \
for ( c = 0; c < csize; ++c ) \
if ( isascii(c) && func(c) ) \
ccladd( currccl, c ); \
}
/* While POSIX defines isblank(), it's not ANSI C. */
#define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
1993-12-02 22:17:24 +03:00
/* On some over-ambitious machines, such as DEC Alpha's, the default
* token type is "long" instead of "int"; this leads to problems with
* declaring yylval in flexdef.h. But so far, all the yacc's I've seen
* wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
* following should ensure that the default token type is "int".
*/
#define YYSTYPE int
1993-03-21 12:45:37 +03:00
%}
%%
1993-12-02 22:17:24 +03:00
goal : initlex sect1 sect1end sect2 initforrule
1993-03-21 12:45:37 +03:00
{ /* add default rule */
int def_rule;
pat = cclinit();
cclnegate( pat );
def_rule = mkstate( -pat );
1993-12-02 22:17:24 +03:00
/* Remember the number of the default rule so we
* don't generate "can't match" warnings for it.
*/
default_rule = num_rules;
1993-03-21 12:45:37 +03:00
finish_rule( def_rule, false, 0, 0 );
for ( i = 1; i <= lastsc; ++i )
1993-12-02 22:17:24 +03:00
scset[i] = mkbranch( scset[i], def_rule );
1993-03-21 12:45:37 +03:00
if ( spprdflt )
1993-12-02 22:17:24 +03:00
add_action(
"YY_FATAL_ERROR( \"flex scanner jammed\" )" );
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
add_action( "ECHO" );
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
add_action( ";\n\tYY_BREAK\n" );
1993-03-21 12:45:37 +03:00
}
;
1993-12-02 22:17:24 +03:00
initlex :
{ /* initialize for processing rules */
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
/* Create default DFA start condition. */
1993-03-21 12:45:37 +03:00
scinstal( "INITIAL", false );
}
;
1995-05-05 09:35:08 +04:00
sect1 : sect1 startconddecl namelist1
| sect1 options
1993-03-21 12:45:37 +03:00
|
1995-05-05 09:35:08 +04:00
| error
1993-03-21 12:45:37 +03:00
{ synerr( "unknown error processing section 1" ); }
;
sect1end : SECTEND
{
1995-05-05 09:35:08 +04:00
check_options();
scon_stk = allocate_integer_array( lastsc + 1 );
scon_stk_ptr = 0;
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
;
startconddecl : SCDECL
{ xcluflg = false; }
1993-03-21 12:45:37 +03:00
| XSCDECL
{ xcluflg = true; }
;
1995-05-05 09:35:08 +04:00
namelist1 : namelist1 NAME
1993-03-21 12:45:37 +03:00
{ scinstal( nmstr, xcluflg ); }
| NAME
{ scinstal( nmstr, xcluflg ); }
| error
1993-12-02 22:17:24 +03:00
{ synerr( "bad start condition list" ); }
1993-03-21 12:45:37 +03:00
;
1995-05-05 09:35:08 +04:00
options : OPTION_OP optionlist
;
optionlist : optionlist option
|
;
option : OPT_OUTFILE '=' NAME
{
outfilename = copy_string( nmstr );
did_outfilename = 1;
}
| OPT_PREFIX '=' NAME
{ prefix = copy_string( nmstr ); }
| OPT_YYCLASS '=' NAME
{ yyclass = copy_string( nmstr ); }
;
sect2 : sect2 scon initforrule flexrule '\n'
{ scon_stk_ptr = $2; }
| sect2 scon '{' sect2 '}'
{ scon_stk_ptr = $2; }
1993-03-21 12:45:37 +03:00
|
;
1993-12-02 22:17:24 +03:00
initforrule :
1993-03-21 12:45:37 +03:00
{
1993-12-02 22:17:24 +03:00
/* Initialize for a parse of one rule. */
1993-03-21 12:45:37 +03:00
trlcontxt = variable_trail_rule = varlength = false;
trailcnt = headcnt = rulelen = 0;
current_state_type = STATE_NORMAL;
previous_continued_action = continued_action;
1995-05-05 09:35:08 +04:00
in_rule = true;
1993-03-21 12:45:37 +03:00
new_rule();
}
;
1995-05-05 09:35:08 +04:00
flexrule : '^' rule
1993-12-02 22:17:24 +03:00
{
1995-05-05 09:35:08 +04:00
pat = $2;
1993-03-21 12:45:37 +03:00
finish_rule( pat, variable_trail_rule,
1993-12-02 22:17:24 +03:00
headcnt, trailcnt );
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
if ( scon_stk_ptr > 0 )
1993-12-02 22:17:24 +03:00
{
1995-05-05 09:35:08 +04:00
for ( i = 1; i <= scon_stk_ptr; ++i )
scbol[scon_stk[i]] =
mkbranch( scbol[scon_stk[i]],
pat );
1993-12-02 22:17:24 +03:00
}
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
else
{
/* Add to all non-exclusive start conditions,
* including the default (0) start condition.
*/
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
for ( i = 1; i <= lastsc; ++i )
if ( ! scxclu[i] )
scbol[i] = mkbranch( scbol[i],
pat );
}
1993-03-21 12:45:37 +03:00
if ( ! bol_needed )
1993-12-02 22:17:24 +03:00
{
bol_needed = true;
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
if ( performance_report > 1 )
pinpoint_message(
"'^' operator results in sub-optimal performance" );
}
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
| rule
1993-03-21 12:45:37 +03:00
{
pat = $1;
finish_rule( pat, variable_trail_rule,
1993-12-02 22:17:24 +03:00
headcnt, trailcnt );
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
if ( scon_stk_ptr > 0 )
{
for ( i = 1; i <= scon_stk_ptr; ++i )
scset[scon_stk[i]] =
mkbranch( scset[scon_stk[i]],
pat );
}
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
else
{
for ( i = 1; i <= lastsc; ++i )
if ( ! scxclu[i] )
scset[i] =
mkbranch( scset[i],
pat );
}
}
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
| EOF_OP
1993-03-21 12:45:37 +03:00
{
1995-05-05 09:35:08 +04:00
if ( scon_stk_ptr > 0 )
build_eof_action();
else
{
/* This EOF applies to all start conditions
* which don't already have EOF actions.
*/
for ( i = 1; i <= lastsc; ++i )
if ( ! sceof[i] )
scon_stk[++scon_stk_ptr] = i;
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
if ( scon_stk_ptr == 0 )
warn(
1993-12-02 22:17:24 +03:00
"all start conditions already have <<EOF>> rules" );
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
else
build_eof_action();
}
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
| error
1993-03-21 12:45:37 +03:00
{ synerr( "unrecognized rule" ); }
;
1995-05-05 09:35:08 +04:00
scon_stk_ptr :
{ $$ = scon_stk_ptr; }
;
scon : '<' scon_stk_ptr namelist2 '>'
{ $$ = $2; }
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
| '<' '*' '>'
{
1995-05-05 09:35:08 +04:00
$$ = scon_stk_ptr;
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
for ( i = 1; i <= lastsc; ++i )
1995-05-05 09:35:08 +04:00
{
int j;
for ( j = 1; j <= scon_stk_ptr; ++j )
if ( scon_stk[j] == i )
break;
if ( j > scon_stk_ptr )
scon_stk[++scon_stk_ptr] = i;
}
1993-03-21 12:45:37 +03:00
}
1995-05-05 09:35:08 +04:00
|
{ $$ = scon_stk_ptr; }
1993-12-02 22:17:24 +03:00
;
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
namelist2 : namelist2 ',' sconname
1995-05-05 09:35:08 +04:00
| sconname
1993-12-02 22:17:24 +03:00
| error
{ synerr( "bad start condition list" ); }
;
sconname : NAME
1993-03-21 12:45:37 +03:00
{
if ( (scnum = sclookup( nmstr )) == 0 )
1993-12-02 22:17:24 +03:00
format_pinpoint_message(
"undeclared start condition %s",
nmstr );
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
{
1995-05-05 09:35:08 +04:00
for ( i = 1; i <= scon_stk_ptr; ++i )
if ( scon_stk[i] == scnum )
{
format_warn(
"<%s> specified twice",
scname[scnum] );
break;
}
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
if ( i > scon_stk_ptr )
scon_stk[++scon_stk_ptr] = scnum;
1993-12-02 22:17:24 +03:00
}
}
1993-03-21 12:45:37 +03:00
;
1993-12-02 22:17:24 +03:00
rule : re2 re
1993-03-21 12:45:37 +03:00
{
if ( transchar[lastst[$2]] != SYM_EPSILON )
1993-12-02 22:17:24 +03:00
/* Provide final transition \now/ so it
* will be marked as a trailing context
* state.
*/
$2 = link_machines( $2,
mkstate( SYM_EPSILON ) );
1993-03-21 12:45:37 +03:00
mark_beginning_as_normal( $2 );
current_state_type = STATE_NORMAL;
if ( previous_continued_action )
{
1993-12-02 22:17:24 +03:00
/* We need to treat this as variable trailing
* context so that the backup does not happen
* in the action but before the action switch
* statement. If the backup happens in the
* action, then the rules "falling into" this
* one's action will *also* do the backup,
* erroneously.
*/
if ( ! varlength || headcnt != 0 )
warn(
"trailing context made variable due to preceding '|' action" );
/* Mark as variable. */
varlength = true;
headcnt = 0;
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
if ( lex_compat || (varlength && headcnt == 0) )
{ /* variable trailing context rule */
/* Mark the first part of the rule as the
* accepting "head" part of a trailing
* context rule.
*
* By the way, we didn't do this at the
* beginning of this production because back
* then current_state_type was set up for a
* trail rule, and add_accept() can create
* a new state ...
*/
add_accept( $1,
num_rules | YY_TRAILING_HEAD_MASK );
variable_trail_rule = true;
}
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
trailcnt = rulelen;
1993-03-21 12:45:37 +03:00
$$ = link_machines( $1, $2 );
}
| re2 re '$'
{ synerr( "trailing context used twice" ); }
| re '$'
1993-12-02 22:17:24 +03:00
{
1993-12-14 05:09:50 +03:00
headcnt = 0;
trailcnt = 1;
rulelen = 1;
varlength = false;
current_state_type = STATE_TRAILING_CONTEXT;
1993-03-21 12:45:37 +03:00
if ( trlcontxt )
1993-12-02 22:17:24 +03:00
{
synerr( "trailing context used twice" );
$$ = mkstate( SYM_EPSILON );
}
1993-03-21 12:45:37 +03:00
else if ( previous_continued_action )
{
1993-12-02 22:17:24 +03:00
/* See the comment in the rule for "re2 re"
* above.
*/
1993-12-14 05:09:50 +03:00
warn(
1993-12-02 22:17:24 +03:00
"trailing context made variable due to preceding '|' action" );
varlength = true;
1993-03-21 12:45:37 +03:00
}
1993-12-14 05:09:50 +03:00
if ( lex_compat || varlength )
1993-12-02 22:17:24 +03:00
{
/* Again, see the comment in the rule for
* "re2 re" above.
*/
add_accept( $1,
num_rules | YY_TRAILING_HEAD_MASK );
variable_trail_rule = true;
}
1993-03-21 12:45:37 +03:00
1993-05-04 11:44:39 +04:00
trlcontxt = true;
1993-03-21 12:45:37 +03:00
eps = mkstate( SYM_EPSILON );
$$ = link_machines( $1,
1993-12-02 22:17:24 +03:00
link_machines( eps, mkstate( '\n' ) ) );
1993-03-21 12:45:37 +03:00
}
| re
{
1993-12-02 22:17:24 +03:00
$$ = $1;
1993-03-21 12:45:37 +03:00
if ( trlcontxt )
1993-12-02 22:17:24 +03:00
{
if ( lex_compat || (varlength && headcnt == 0) )
/* Both head and trail are
* variable-length.
*/
variable_trail_rule = true;
else
trailcnt = rulelen;
}
}
1993-03-21 12:45:37 +03:00
;
1993-12-02 22:17:24 +03:00
re : re '|' series
{
1993-03-21 12:45:37 +03:00
varlength = true;
$$ = mkor( $1, $3 );
}
| series
{ $$ = $1; }
;
re2 : re '/'
{
1993-12-02 22:17:24 +03:00
/* This rule is written separately so the
* reduction will occur before the trailing
* series is parsed.
1993-03-21 12:45:37 +03:00
*/
if ( trlcontxt )
1993-12-02 22:17:24 +03:00
synerr( "trailing context used twice" );
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
trlcontxt = true;
1993-03-21 12:45:37 +03:00
if ( varlength )
1993-12-02 22:17:24 +03:00
/* We hope the trailing context is
* fixed-length.
*/
varlength = false;
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
headcnt = rulelen;
1993-03-21 12:45:37 +03:00
rulelen = 0;
current_state_type = STATE_TRAILING_CONTEXT;
$$ = $1;
}
;
1993-12-02 22:17:24 +03:00
series : series singleton
{
/* This is where concatenation of adjacent patterns
* gets done.
1993-03-21 12:45:37 +03:00
*/
$$ = link_machines( $1, $2 );
}
| singleton
{ $$ = $1; }
;
1993-12-02 22:17:24 +03:00
singleton : singleton '*'
{
1993-03-21 12:45:37 +03:00
varlength = true;
$$ = mkclos( $1 );
}
| singleton '+'
{
varlength = true;
$$ = mkposcl( $1 );
}
| singleton '?'
{
varlength = true;
$$ = mkopt( $1 );
}
| singleton '{' NUMBER ',' NUMBER '}'
{
varlength = true;
if ( $3 > $5 || $3 < 0 )
1993-12-02 22:17:24 +03:00
{
synerr( "bad iteration values" );
$$ = $1;
}
1993-03-21 12:45:37 +03:00
else
1993-05-04 11:44:39 +04:00
{
1993-12-02 22:17:24 +03:00
if ( $3 == 0 )
{
if ( $5 <= 0 )
{
synerr(
"bad iteration values" );
$$ = $1;
}
else
$$ = mkopt(
mkrep( $1, 1, $5 ) );
}
1993-05-04 11:44:39 +04:00
else
1993-12-02 22:17:24 +03:00
$$ = mkrep( $1, $3, $5 );
1993-05-04 11:44:39 +04:00
}
1993-03-21 12:45:37 +03:00
}
| singleton '{' NUMBER ',' '}'
{
varlength = true;
if ( $3 <= 0 )
1993-12-02 22:17:24 +03:00
{
synerr( "iteration value must be positive" );
$$ = $1;
}
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
$$ = mkrep( $1, $3, INFINITY );
1993-03-21 12:45:37 +03:00
}
| singleton '{' NUMBER '}'
{
1993-12-02 22:17:24 +03:00
/* The singleton could be something like "(foo)",
1993-03-21 12:45:37 +03:00
* in which case we have no idea what its length
* is, so we punt here.
*/
varlength = true;
if ( $3 <= 0 )
1993-12-02 22:17:24 +03:00
{
synerr( "iteration value must be positive" );
$$ = $1;
}
1993-03-21 12:45:37 +03:00
else
1993-12-02 22:17:24 +03:00
$$ = link_machines( $1,
copysingl( $1, $3 - 1 ) );
1993-03-21 12:45:37 +03:00
}
| '.'
{
if ( ! madeany )
1993-12-02 22:17:24 +03:00
{
/* Create the '.' character class. */
anyccl = cclinit();
ccladd( anyccl, '\n' );
cclnegate( anyccl );
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
if ( useecs )
mkeccl( ccltbl + cclmap[anyccl],
ccllen[anyccl], nextecm,
ecgroup, csize, csize );
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
madeany = true;
}
1993-03-21 12:45:37 +03:00
++rulelen;
$$ = mkstate( -anyccl );
}
| fullccl
{
if ( ! cclsorted )
1993-12-02 22:17:24 +03:00
/* Sort characters for fast searching. We
* use a shell sort since this list could
* be large.
*/
cshell( ccltbl + cclmap[$1], ccllen[$1], true );
1993-03-21 12:45:37 +03:00
if ( useecs )
1993-12-02 22:17:24 +03:00
mkeccl( ccltbl + cclmap[$1], ccllen[$1],
nextecm, ecgroup, csize, csize );
1993-03-21 12:45:37 +03:00
++rulelen;
$$ = mkstate( -$1 );
}
| PREVCCL
{
++rulelen;
$$ = mkstate( -$1 );
}
| '"' string '"'
{ $$ = $2; }
| '(' re ')'
{ $$ = $2; }
| CHAR
{
++rulelen;
if ( caseins && $1 >= 'A' && $1 <= 'Z' )
1993-12-02 22:17:24 +03:00
$1 = clower( $1 );
1993-03-21 12:45:37 +03:00
$$ = mkstate( $1 );
}
;
fullccl : '[' ccl ']'
{ $$ = $2; }
| '[' '^' ccl ']'
{
cclnegate( $3 );
$$ = $3;
}
;
1993-12-02 22:17:24 +03:00
ccl : ccl CHAR '-' CHAR
{
if ( caseins )
1993-03-21 12:45:37 +03:00
{
if ( $2 >= 'A' && $2 <= 'Z' )
1993-12-02 22:17:24 +03:00
$2 = clower( $2 );
1993-03-21 12:45:37 +03:00
if ( $4 >= 'A' && $4 <= 'Z' )
1993-12-02 22:17:24 +03:00
$4 = clower( $4 );
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
if ( $2 > $4 )
synerr( "negative range in character class" );
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
else
{
for ( i = $2; i <= $4; ++i )
ccladd( $1, i );
/* Keep track if this ccl is staying in
* alphabetical order.
*/
cclsorted = cclsorted && ($2 > lastchar);
lastchar = $4;
}
1993-03-21 12:45:37 +03:00
$$ = $1;
}
| ccl CHAR
1993-12-02 22:17:24 +03:00
{
if ( caseins && $2 >= 'A' && $2 <= 'Z' )
1993-03-21 12:45:37 +03:00
$2 = clower( $2 );
ccladd( $1, $2 );
cclsorted = cclsorted && ($2 > lastchar);
lastchar = $2;
$$ = $1;
}
1995-05-05 09:35:08 +04:00
| ccl ccl_expr
{
/* Too hard to properly maintain cclsorted. */
cclsorted = false;
$$ = $1;
}
1993-03-21 12:45:37 +03:00
|
{
cclsorted = true;
lastchar = 0;
1995-05-05 09:35:08 +04:00
currccl = $$ = cclinit();
1993-03-21 12:45:37 +03:00
}
;
1995-05-05 09:35:08 +04:00
ccl_expr: CCE_ALNUM { CCL_EXPR(isalnum) }
| CCE_ALPHA { CCL_EXPR(isalpha) }
| CCE_BLANK { CCL_EXPR(IS_BLANK) }
| CCE_CNTRL { CCL_EXPR(iscntrl) }
| CCE_DIGIT { CCL_EXPR(isdigit) }
| CCE_GRAPH { CCL_EXPR(isgraph) }
| CCE_LOWER { CCL_EXPR(islower) }
| CCE_PRINT { CCL_EXPR(isprint) }
| CCE_PUNCT { CCL_EXPR(ispunct) }
| CCE_SPACE { CCL_EXPR(isspace) }
| CCE_UPPER {
if ( caseins )
CCL_EXPR(islower)
else
CCL_EXPR(isupper)
}
| CCE_XDIGIT { CCL_EXPR(isxdigit) }
;
1993-03-21 12:45:37 +03:00
string : string CHAR
1993-12-02 22:17:24 +03:00
{
if ( caseins && $2 >= 'A' && $2 <= 'Z' )
1993-03-21 12:45:37 +03:00
$2 = clower( $2 );
++rulelen;
$$ = link_machines( $1, mkstate( $2 ) );
}
|
{ $$ = mkstate( SYM_EPSILON ); }
;
%%
/* build_eof_action - build the "<<EOF>>" action for the active start
* conditions
*/
void build_eof_action()
1993-12-02 22:17:24 +03:00
{
register int i;
char action_text[MAXLINE];
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
for ( i = 1; i <= scon_stk_ptr; ++i )
1993-12-02 22:17:24 +03:00
{
1995-05-05 09:35:08 +04:00
if ( sceof[scon_stk[i]] )
1993-12-02 22:17:24 +03:00
format_pinpoint_message(
"multiple <<EOF>> rules for start condition %s",
1995-05-05 09:35:08 +04:00
scname[scon_stk[i]] );
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
else
{
1995-05-05 09:35:08 +04:00
sceof[scon_stk[i]] = true;
1993-12-02 22:17:24 +03:00
sprintf( action_text, "case YY_STATE_EOF(%s):\n",
1995-05-05 09:35:08 +04:00
scname[scon_stk[i]] );
1993-12-02 22:17:24 +03:00
add_action( action_text );
}
}
1995-05-05 09:35:08 +04:00
line_directive_out( (FILE *) 0, 1 );
1993-12-02 22:17:24 +03:00
/* This isn't a normal rule after all - don't count it as
* such, so we don't have any holes in the rule numbering
* (which make generating "rule can never match" warnings
* more difficult.
*/
--num_rules;
++num_eof_rules;
1993-03-21 12:45:37 +03:00
}
1993-12-02 22:17:24 +03:00
/* format_synerr - write out formatted syntax error */
void format_synerr( msg, arg )
char msg[], arg[];
{
char errmsg[MAXLINE];
(void) sprintf( errmsg, msg, arg );
synerr( errmsg );
}
1993-03-21 12:45:37 +03:00
/* synerr - report a syntax error */
void synerr( str )
char str[];
1993-12-02 22:17:24 +03:00
{
syntaxerror = true;
pinpoint_message( str );
}
1993-03-21 12:45:37 +03:00
1995-05-05 09:35:08 +04:00
/* format_warn - write out formatted warning */
void format_warn( msg, arg )
char msg[], arg[];
{
char warn_msg[MAXLINE];
(void) sprintf( warn_msg, msg, arg );
warn( warn_msg );
}
1993-12-02 22:17:24 +03:00
/* warn - report a warning, unless -w was given */
void warn( str )
char str[];
{
line_warning( str, linenum );
}
1993-03-21 12:45:37 +03:00
/* format_pinpoint_message - write out a message formatted with one string,
* pinpointing its location
*/
void format_pinpoint_message( msg, arg )
char msg[], arg[];
1993-12-02 22:17:24 +03:00
{
char errmsg[MAXLINE];
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
(void) sprintf( errmsg, msg, arg );
pinpoint_message( errmsg );
}
1993-03-21 12:45:37 +03:00
/* pinpoint_message - write out a message, pinpointing its location */
void pinpoint_message( str )
char str[];
1993-12-02 22:17:24 +03:00
{
line_pinpoint( str, linenum );
}
/* line_warning - report a warning at a given line, unless -w was given */
void line_warning( str, line )
char str[];
int line;
{
char warning[MAXLINE];
if ( ! nowarn )
{
sprintf( warning, "warning, %s", str );
line_pinpoint( warning, line );
}
}
1993-03-21 12:45:37 +03:00
1993-12-02 22:17:24 +03:00
/* line_pinpoint - write out a message, pinpointing it at the given line */
void line_pinpoint( str, line )
char str[];
int line;
{
fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
}
1993-03-21 12:45:37 +03:00
/* yyerror - eat up an error message from the parser;
* currently, messages are ignore
*/
void yyerror( msg )
char msg[];
1993-12-02 22:17:24 +03:00
{
}