/* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */
/* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */
/* 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. */
/* This file is part of flex. */
/* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */
/* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */
/* 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. */
#include"flexdef.h"
/* declare functions that have forward references */
int dupmachine PROTO ((int)); void mkxtion PROTO ((int, int));
/* add_accept - add an accepting state to a machine * *accepting_numberbecomesmach'sacceptingnumber.
*/
void add_accept (mach, accepting_number) int mach, accepting_number;
{ /* Hang the accepting number off an epsilon state. if it is associated *withastatethathasanon-epsilonout-transition,thenthestate *willacceptBEFOREitmakesthattransition,i.e.,onecharacter *toosoon.
*/
if (transchar[finalst[mach]] == SYM_EPSILON)
accptnum[finalst[mach]] = accepting_number;
/* copysingl - make a given number of copies of a singleton machine * *synopsis * *newsng=copysingl(singl,num); * *newsng-anewsingletoncomposedofnumcopiesofsingl *singl-asingletonmachine *num-thenumberofcopiesofsingltobepresentinnewsng
*/
int copysingl (singl, num) int singl, num;
{ int copy, i;
copy = mkstate (SYM_EPSILON);
for (i = 1; i <= num; ++i)
copy = link_machines (copy, dupmachine (singl));
return copy;
}
/* dumpnfa - debugging routine to write out an nfa */
void dumpnfa (state1) int state1;
{ int sym, tsp1, tsp2, anum, ns;
fprintf (stderr,
_
("\n\n********** beginning dump of nfa with start state %d\n"),
state1);
/* We probably should loop starting at firstst[state1] and going to *lastst[state1],butthey'renotmaintainedproperlywhenwe"or" *alloftherulestogether.Soweuseourknowledgethatthemachine *startsatstate1andendsatlastnfa.
*/
fprintf (stderr, _("********** end of dump\n"));
}
/* dupmachine - make a duplicate of a given machine * *synopsis * *copy=dupmachine(mach); * *copy-holdsduplicateofmach *mach-machinetobeduplicated * *notethatthecopyofmachisNOTanexactduplicate;rather,allthe *transitionstatesvaluesareadjustedsothatthecopyisself-contained, *astheoriginalshouldhavebeen. * *alsonotethattheoriginalMUSTbecontiguous,withitslowandhigh *statesaccessiblebythearraysfirststandlastst
*/
int dupmachine (mach) int mach;
{ int i, init, state_offset; int state = 0; int last = lastst[mach];
for (i = firstst[mach]; i <= last; ++i) {
state = mkstate (transchar[i]);
if (trans1[i] != NO_TRANSITION) {
mkxtion (finalst[state], trans1[i] + state - i);
if (transchar[i] == SYM_EPSILON &&
trans2[i] != NO_TRANSITION)
mkxtion (finalst[state],
trans2[i] + state - i);
}
accptnum[state] = accptnum[i];
}
if (state == 0)
flexfatal (_("empty machine in dupmachine()"));
/* finish_rule - finish up the processing for a rule * *Anacceptingnumberisaddedtothegivenmachine.Ifvariable_trail_rule *istruethentherulehastrailingcontextandboththeheadandtrail *arevariablesize.Otherwiseifheadcntortrailcntisnon-zerothen *themachinerecognizesapatternwithtrailingcontextandheadcntis *thenumberofcharactersinthematchedpartofthepattern,orzero *ifthematchedparthasvariablelength.trailcntisthenumberof *trailingcontextcharactersinthepattern,orzeroifthetrailing *contexthasvariablelength.
*/
/* We did this in new_rule(), but it often gets the wrong *numberbecausewedoitbeforewestartparsingthecurrentrule.
*/
rule_linenum[num_rules] = linenum;
/* If this is a continued action, then the line-number has already *beenupdated,givingusthewrongnumber.
*/ if (continued_action)
--rule_linenum[num_rules];
/* If the previous rule was continued action, then we inherit the *previousnewlineflag,possiblyoverridingthecurrentone.
*/ if (pcont_act && rule_has_nl[num_rules - 1])
rule_has_nl[num_rules] = true;
snprintf (action_text, sizeof(action_text), "case %d:\n", num_rules);
add_action (action_text); if (rule_has_nl[num_rules]) {
snprintf (action_text, sizeof(action_text), "/* rule %d can match eol */\n",
num_rules);
add_action (action_text);
}
if (variable_trail_rule) {
rule_type[num_rules] = RULE_VARIABLE;
if (performance_report > 0)
fprintf (stderr,
_
("Variable trailing context rule at line %d\n"),
rule_linenum[num_rules]);
variable_trailing_context_rules = true;
}
else {
rule_type[num_rules] = RULE_NORMAL;
if (headcnt > 0 || trailcnt > 0) { /* Do trailing context magic to not match the trailing *characters.
*/ char *scanner_cp = "YY_G(yy_c_buf_p) = yy_cp"; char *scanner_bp = "yy_bp";
add_action
("*yy_cp = YY_G(yy_hold_char); /* undo effects of setting up yytext */\n");
add_action
("YY_DO_BEFORE_ACTION; /* set up yytext again */\n");
}
}
/* Okay, in the action code at this point yytext and yyleng have *theirproperfinalvaluesforthisrule,sohere'sthepoint *todoanyuseraction.Butdon'tdoitforcontinuedactions, *asthat'llresultinmultipleYY_RULE_SETUP's.
*/ if (!continued_action)
add_action ("YY_RULE_SETUP\n");
int link_machines (first, last) int first, last;
{ if (first == NIL) return last;
elseif (last == NIL) return first;
else {
mkxtion (finalst[first], last);
finalst[first] = finalst[last];
lastst[first] = MAX (lastst[first], lastst[last]);
firstst[first] = MIN (firstst[first], firstst[last]);
return first;
}
}
/* mark_beginning_as_normal - mark each "beginning" state in a machine *asbeinga"normal"(i.e.,nottrailingcontext- *associated)states * *The"beginning"statesaretheepsilonclosureofthefirststate
*/
void mark_beginning_as_normal (mach) int mach;
{ switch (state_type[mach]) { case STATE_NORMAL: /* Oh, we've already visited here. */ return;
case STATE_TRAILING_CONTEXT:
state_type[mach] = STATE_NORMAL;
if (transchar[mach] == SYM_EPSILON) { if (trans1[mach] != NO_TRANSITION)
mark_beginning_as_normal (trans1[mach]);
if (trans2[mach] != NO_TRANSITION)
mark_beginning_as_normal (trans2[mach]);
} break;
default:
flexerror (_
("bad state type in mark_beginning_as_normal()")); break;
}
}
/* mkbranch - make a machine that branches to two machines * *synopsis * *branch=mkbranch(first,second); * *branch-amachinewhichmatcheseitherfirst'spatternorsecond's *first,second-machineswhosepatternsaretobeor'ed(the|operator) * *NotethatfirstandsecondareNEITHERdestroyedbytheoperation.Also, *theresultingmachineCANNOTbeusedwithanyother"mk"operationexcept *moremkbranch's.Comparewithmkor()
*/
int mkbranch (first, second) int first, second;
{ int eps;
if (first == NO_TRANSITION) return second;
elseif (second == NO_TRANSITION) return first;
eps = mkstate (SYM_EPSILON);
mkxtion (eps, first);
mkxtion (eps, second);
return eps;
}
/* mkclos - convert a machine into a closure * *synopsis *new=mkclos(state); * *new-anewstatewhichmatchestheclosureof"state"
*/
int mkclos (state) int state;
{ return mkopt (mkposcl (state));
}
/* mkopt - make a machine optional * *synopsis * *new=mkopt(mach); * *new-amachinewhichoptionallymatcheswhatevermachmatched *mach-themachinetomakeoptional * *notes: *1.machmustbethelastmachinecreated *2.machisdestroyedbythecall
*/
/* Can't skimp on the following if FREE_EPSILON(mach) is true because *somestateinteriorto"mach"mightpointbacktothebeginning *foraclosure.
*/
eps = mkstate (SYM_EPSILON);
mach = link_machines (eps, mach);
mkxtion (mach, finalst[mach]);
return mach;
}
/* mkor - make a machine that matches either one of two machines * *synopsis * *new=mkor(first,second); * *new-amachinewhichmatcheseitherfirst'spatternorsecond's *first,second-machineswhosepatternsaretobeor'ed(the|operator) * *notethatfirstandsecondarebothdestroyedbytheoperation *thecodeisratherconvolutedbecauseanattemptismadetominimize *thenumberofepsilonstatesneeded
*/
int mkor (first, second) int first, second;
{ int eps, orend;
if (first == NIL) return second;
elseif (second == NIL) return first;
else { /* See comment in mkopt() about why we can't use the first *stateof"first"or"second"iftheysatisfy"FREE_EPSILON".
*/
eps = mkstate (SYM_EPSILON);
/* mkstate - create a state with a transition on a given symbol * *synopsis * *state=mkstate(sym); * *state-anewstatematchingsym *sym-thesymbolthenewstateistohaveanout-transitionon * *notethatthisroutinemakesnewstatesinascendingorderthroughthe *statearray(andincrementsLASTNFAaccordingly).TheroutineDUPMACHINE *reliesonmachinesbeingmadeinascendingorderandthattheyare *CONTIGUOUS.ChangeitandyouwillhavetorewriteDUPMACHINE(kludge *thatitadmittedlyis)
*/
int mkstate (sym) int sym;
{ if (++lastnfa >= current_mns) { if ((current_mns += MNS_INCREMENT) >= maximum_mns)
lerr(_
("input rules are too complicated (>= %d NFA states)"),
current_mns);
/* Fix up equivalence classes base on this transition. Note that any *characterwhichhasitsowntransitiongetsitsownequivalence *class.Thusonlycharacterswhichareonlyincharacterclasses *haveachanceatbeinginthesameequivalenceclass.E.g."a|b" *puts'a'and'b'intotwodifferentequivalenceclasses."[ab]" *putstheminthesameequivalenceclass(barringotherdifferences *elsewhereintheinput).
*/
if (sym < 0) { /* We don't have to update the equivalence classes since *thatwasalreadydonewhenthecclwascreatedforthe *firsttime.
*/
}
elseif (sym == SYM_EPSILON)
++numeps;
else {
check_char (sym);
if (useecs) /* Map NUL's to csize. */
mkechar (sym ? sym : csize, nextecm, ecgroup);
}
return lastnfa;
}
/* mkxtion - make a transition from one state to another * *synopsis * *mkxtion(statefrom,stateto); * *statefrom-thestatefromwhichthetransitionistobemade *stateto-thestatetowhichthetransitionistobemade
*/
void mkxtion (statefrom, stateto) int statefrom, stateto;
{ if (trans1[statefrom] == NO_TRANSITION)
trans1[statefrom] = stateto;
elseif ((transchar[statefrom] != SYM_EPSILON) ||
(trans2[statefrom] != NO_TRANSITION))
flexfatal (_("found too many transitions in mkxtion()"));
else { /* second out-transition for an epsilon state */
++eps2;
trans2[statefrom] = stateto;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.