std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
{
- if ( lowKey > keyOps->maxKey ) {
- GenCondSpace *condSpace = findCondSpace( lowKey, highKey );
+ GenCondSpace *condSpace;
+ if ( lowKey > keyOps->maxKey && (condSpace=findCondSpace(lowKey, highKey) ) ) {
Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();
lowKey = keyOps->minKey +
struct FsmAp;
struct Action;
struct LongestMatchPart;
+struct LengthDef;
/* State list element for unambiguous access to list element. */
struct FsmListEl
{
Expression *expression = new Expression( builtin );
Join *join = new Join( expression );
- JoinOrLm *joinOrLm = new JoinOrLm( join );
- VarDef *varDef = new VarDef( name, joinOrLm );
+ MachineDef *machineDef = new MachineDef( join );
+ VarDef *varDef = new VarDef( name, machineDef );
GraphDictEl *graphDictEl = new GraphDictEl( name, varDef );
graphDict.insert( graphDictEl );
}
NameInst *prevLocalScope;
};
+struct LengthDef
+{
+ LengthDef( char *name )
+ : name(name) {}
+
+ char *name;
+ LengthDef *prev, *next;
+};
+
+typedef DList<LengthDef> LengthDefList;
+
/* Class to collect information about the machine during the
* parse of input. */
struct ParseData
KeyOps thisKeyOps;
ExportList exportList;
+ LengthDefList lengthDefList;
CodeGenData *cgd;
};
NameFrame nameFrame = pd->enterNameScope( true, 1 );
/* Recurse on the expression. */
- FsmAp *rtnVal = joinOrLm->walk( pd );
+ FsmAp *rtnVal = machineDef->walk( pd );
/* Do the tranfer of local error actions. */
LocalErrDictEl *localErrDictEl = pd->localErrDict.find( name );
/* If the expression below is a join operation with multiple expressions
* then it just had epsilon transisions resolved. If it is a join
* with only a single expression then run the epsilon op now. */
- if ( joinOrLm->type == JoinOrLm::JoinType && joinOrLm->join->exprList.length() == 1 )
+ if ( machineDef->type == MachineDef::JoinType && machineDef->join->exprList.length() == 1 )
rtnVal->epsilonOp();
/* We can now unset entry points that are not longer used. */
NameInst *prevNameInst = pd->curNameInst;
pd->curNameInst = pd->addNameInst( loc, name, false );
- if ( joinOrLm->type == JoinOrLm::LongestMatchType )
+ if ( machineDef->type == MachineDef::LongestMatchType )
pd->curNameInst->isLongestMatch = true;
/* Recurse. */
- joinOrLm->makeNameTree( pd );
+ machineDef->makeNameTree( pd );
/* The name scope ends, pop the name instantiation. */
pd->curNameInst = prevNameInst;
NameFrame nameFrame = pd->enterNameScope( true, 1 );
/* Recurse. */
- joinOrLm->resolveNameRefs( pd );
+ machineDef->resolveNameRefs( pd );
/* The name scope ends, pop the name instantiation. */
pd->popNameScope( nameFrame );
return rtnVal;
}
-FsmAp *JoinOrLm::walk( ParseData *pd )
+FsmAp *MachineDef::walk( ParseData *pd )
{
FsmAp *rtnVal = 0;
switch ( type ) {
case LongestMatchType:
rtnVal = longestMatch->walk( pd );
break;
+ case LengthDefType:
+ condData->lastCondKey.increment();
+ rtnVal = new FsmAp();
+ rtnVal->concatFsm( condData->lastCondKey );
+ break;
}
return rtnVal;
}
-void JoinOrLm::makeNameTree( ParseData *pd )
+void MachineDef::makeNameTree( ParseData *pd )
{
switch ( type ) {
case JoinType:
case LongestMatchType:
longestMatch->makeNameTree( pd );
break;
+ case LengthDefType:
+ break;
}
}
-void JoinOrLm::resolveNameRefs( ParseData *pd )
+void MachineDef::resolveNameRefs( ParseData *pd )
{
switch ( type ) {
case JoinType:
case LongestMatchType:
longestMatch->resolveNameRefs( pd );
break;
+ case LengthDefType:
+ break;
}
}
struct Factor;
struct Expression;
struct Join;
-struct JoinOrLm;
+struct MachineDef;
struct LongestMatch;
struct LongestMatchPart;
struct LmPartList;
struct Range;
+struct LengthDef;
/* Type of augmentation. Describes locations in the machine. */
enum AugType
*/
struct VarDef
{
- VarDef( const char *name, JoinOrLm *joinOrLm )
- : name(name), joinOrLm(joinOrLm), isExport(false) { }
+ VarDef( const char *name, MachineDef *machineDef )
+ : name(name), machineDef(machineDef), isExport(false) { }
/* Parse tree traversal. */
FsmAp *walk( ParseData *pd );
void resolveNameRefs( ParseData *pd );
const char *name;
- JoinOrLm *joinOrLm;
+ MachineDef *machineDef;
bool isExport;
};
/* List of Expressions. */
typedef DList<Expression> ExprList;
-struct JoinOrLm
+struct MachineDef
{
enum Type {
JoinType,
- LongestMatchType
+ LongestMatchType,
+ LengthDefType
};
- JoinOrLm( Join *join ) :
- join(join), longestMatch(0), type(JoinType) {}
- JoinOrLm( LongestMatch *longestMatch ) :
- join(0), longestMatch(longestMatch), type(LongestMatchType) {}
+ MachineDef( Join *join )
+ : join(join), longestMatch(0), lengthDef(0), type(JoinType) {}
+ MachineDef( LongestMatch *longestMatch )
+ : join(0), longestMatch(longestMatch), lengthDef(0), type(LongestMatchType) {}
+ MachineDef( LengthDef *lengthDef )
+ : join(0), longestMatch(0), lengthDef(lengthDef), type(LengthDefType) {}
FsmAp *walk( ParseData *pd );
void makeNameTree( ParseData *pd );
Join *join;
LongestMatch *longestMatch;
+ LengthDef *lengthDef;
Type type;
};
token KW_Machine, KW_Include, KW_Import, KW_Write, KW_Action, KW_AlphType,
KW_Range, KW_GetKey, KW_Include, KW_Write, KW_Machine, KW_InWhen,
KW_When, KW_OutWhen, KW_Eof, KW_Err, KW_Lerr, KW_To, KW_From,
- KW_Export, KW_PrePush, KW_PostPop;
+ KW_Export, KW_PrePush, KW_PostPop, KW_Length;
# Specials in code blocks.
token KW_Break, KW_Exec, KW_Hold, KW_PChar, KW_Char, KW_Goto, KW_Call,
int token( InputLoc &loc, int tokId, char *tokstart, int toklen );
void tryMachineDef( InputLoc &loc, char *name,
- JoinOrLm *joinOrLm, bool isInstance );
+ MachineDef *machineDef, bool isInstance );
/* Report an error encountered by the parser. */
ostream &parse_error( int tokId, Token &token );
statement: export_block commit;
statement: pre_push_spec commit;
statement: post_pop_spec commit;
+statement: length_spec commit;
+
+length_spec:
+ KW_Length TK_Word ';'
+ final {
+ LengthDef *lengthDef = new LengthDef( $2->data );
+ pd->lengthDefList.append( lengthDef );
+
+ /* Generic creation of machine for instantiation and assignment. */
+ MachineDef *machineDef = new MachineDef( lengthDef );
+ tryMachineDef( $2->loc, $2->data, machineDef, false );
+ };
pre_push_spec:
KW_PrePush '{' inline_block '}'
}
/* Generic creation of machine for instantiation and assignment. */
- JoinOrLm *joinOrLm = new JoinOrLm( $4->join );
- tryMachineDef( $2->token.loc, $2->token.data, joinOrLm, isInstance );
+ MachineDef *machineDef = new MachineDef( $4->join );
+ tryMachineDef( $2->token.loc, $2->token.data, machineDef, isInstance );
if ( $1->isSet )
exportContext.remove( exportContext.length()-1 );
instantiation:
opt_export machine_name TK_ColonEquals join_or_lm ';' final {
/* Generic creation of machine for instantiation and assignment. */
- tryMachineDef( $2->token.loc, $2->token.data, $4->joinOrLm, true );
+ tryMachineDef( $2->token.loc, $2->token.data, $4->machineDef, true );
if ( $1->isSet )
exportContext.remove( exportContext.length()-1 );
/* Pass a location to join_or_lm */
- if ( $4->joinOrLm->join != 0 )
- $4->joinOrLm->join->loc = $3->loc;
+ if ( $4->machineDef->join != 0 )
+ $4->machineDef->join->loc = $3->loc;
};
type token_type
nonterm join_or_lm
{
- JoinOrLm *joinOrLm;
+ MachineDef *machineDef;
};
join_or_lm:
join final {
- $$->joinOrLm = new JoinOrLm( $1->join );
+ $$->machineDef = new MachineDef( $1->join );
};
join_or_lm:
TK_BarStar lm_part_list '*' '|' final {
pd->lmList.append( lm );
for ( LmPartList::Iter lmp = *($2->lmPartList); lmp.lte(); lmp++ )
lmp->longestMatch = lm;
- $$->joinOrLm = new JoinOrLm( lm );
+ $$->machineDef = new MachineDef( lm );
};
nonterm lm_part_list
}
void Parser::tryMachineDef( InputLoc &loc, char *name,
- JoinOrLm *joinOrLm, bool isInstance )
+ MachineDef *machineDef, bool isInstance )
{
GraphDictEl *newEl = pd->graphDict.insert( name );
if ( newEl != 0 ) {
/* New element in the dict, all good. */
- newEl->value = new VarDef( name, joinOrLm );
+ newEl->value = new VarDef( name, machineDef );
newEl->isInstance = isInstance;
newEl->loc = loc;
newEl->value->isExport = exportContext[exportContext.length()-1];
# Parser definitions.
parser_def := |*
+ 'length_cond' => { token( KW_Length ); };
'machine' => { token( KW_Machine ); };
'include' => { token( KW_Include ); };
'import' => { token( KW_Import ); };