/*
- * Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
+ * Copyright 2001-2006 Adrian Thurston <thurston@complang.org>
*/
/* This file is part of Ragel.
/* Convert the literal string which comes in from the scanner into an array of
* characters with escapes and options interpreted. Also null terminates the
* string. Though this null termination should not be relied on for
- * interpreting literals in the parser because the string may contain a
- * literal string with \0 */
-void Token::prepareLitString( Token &result, bool &caseInsensitive )
+ * interpreting literals in the parser because the string may contain \0 */
+char *prepareLitString( const InputLoc &loc, const char *data, long length,
+ long &resLen, bool &caseInsensitive )
{
- result.data = new char[this->length+1];
+ char *resData = new char[length+1];
caseInsensitive = false;
- char *src = this->data + 1;
- char *end = this->data + this->length - 1;
+ const char *src = data + 1;
+ const char *end = data + length - 1;
while ( *end != '\'' && *end != '\"' ) {
if ( *end == 'i' )
caseInsensitive = true;
else {
- error( this->loc ) << "literal string '" << *end <<
+ error( loc ) << "literal string '" << *end <<
"' option not supported" << endl;
}
end -= 1;
}
- char *dest = result.data;
- int len = 0;
+ char *dest = resData;
+ long len = 0;
while ( src != end ) {
if ( *src == '\\' ) {
switch ( src[1] ) {
dest[len++] = *src++;
}
}
- result.length = len;
- result.data[result.length] = 0;
-}
+ resLen = len;
+ resData[resLen] = 0;
+ return resData;
+}
FsmAp *VarDef::walk( ParseData *pd )
{
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 );
InputLoc loc;
loc.line = 1;
loc.col = 1;
+ loc.fileName = "NONE";
/* Create the error action. */
InlineList *il6 = new InlineList;
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;
}
}
pd->curNameInst->start = resolved[0];
if ( resolved.length() > 1 ) {
/* Complain about the multiple references. */
- error(loc) << "multiple start labels" << endl;
+ error(loc) << "join operation has multiple start labels" << endl;
errorStateLabels( resolved );
}
}
pd->curNameInst->start->numRefs += 1;
}
else {
- /* No start label. Complain and recover by adding a label to the
- * adding one. Recover ignoring the problem. */
- error(loc) << "no start label" << endl;
+ /* No start label. */
+ error(loc) << "join operation has no start label" << endl;
}
/* Recurse into all expressions in the list. */
if ( retFsm->startState->isFinState() ) {
warning(loc) << "applying kleene star to a machine that "
"accepts zero length word" << endl;
+ retFsm->unsetFinState( retFsm->startState );
}
/* Shift over the start action orders then do the kleene star. */
retFsm = factorWithRep->walk( pd );
if ( retFsm->startState->isFinState() ) {
warning(loc) << "applying plus operator to a machine that "
- "accpets zero length word" << endl;
+ "accepts zero length word" << endl;
}
/* Need a duplicated for the star end. */
}
case LitString: {
/* Make the array of keys in int format. */
- Token interp;
+ long length;
bool caseInsensitive;
- token.prepareLitString( interp, caseInsensitive );
- Key *arr = new Key[interp.length];
- makeFsmKeyArray( arr, interp.data, interp.length, pd );
+ char *data = prepareLitString( token.loc, token.data, token.length,
+ length, caseInsensitive );
+ Key *arr = new Key[length];
+ makeFsmKeyArray( arr, data, length, pd );
/* Make the new machine. */
rtnVal = new FsmAp();
if ( caseInsensitive )
- rtnVal->concatFsmCI( arr, interp.length );
+ rtnVal->concatFsmCI( arr, length );
else
- rtnVal->concatFsm( arr, interp.length );
- delete[] interp.data;
+ rtnVal->concatFsm( arr, length );
+ delete[] data;
delete[] arr;
break;
}}
if ( star ) {
if ( rtnVal->startState->isFinState() ) {
warning(loc) << "applying kleene star to a machine that "
- "accpets zero length word" << endl;
+ "accepts zero length word" << endl;
}
rtnVal->starOp();