Fixed crash on failed lookup of goto/call/etc target.
[external/ragel.git] / ragel / parsedata.cpp
index c860fef..6e2558b 100644 (file)
@@ -37,7 +37,7 @@ using namespace std;
 
 char mainMachine[] = "main";
 
-void Token::set( char *str, int len )
+void Token::set( const char *str, int len )
 {
        length = len;
        data = new char[len+1];
@@ -61,7 +61,7 @@ void Token::append( const Token &other )
 void afterOpMinimize( FsmAp *fsm, bool lastInSeq )
 {
        /* Switch on the prefered minimization algorithm. */
-       if ( minimizeOpt == MinimizeEveryOp || minimizeOpt == MinimizeMostOps && lastInSeq ) {
+       if ( minimizeOpt == MinimizeEveryOp || ( minimizeOpt == MinimizeMostOps && lastInSeq ) ) {
                /* First clean up the graph. FsmAp operations may leave these
                 * lying around. There should be no dead end states. The subtract
                 * intersection operators are the only places where they may be
@@ -108,7 +108,7 @@ Key makeFsmKeyHex( char *str, const InputLoc &loc, ParseData *pd )
 
        unsigned long ul = strtoul( str, 0, 16 );
 
-       if ( errno == ERANGE || unusedBits && ul >> (size * 8) ) {
+       if ( errno == ERANGE || ( unusedBits && ul >> (size * 8) ) ) {
                error(loc) << "literal " << str << " overflows the alphabet type" << endl;
                ul = 1 << (size * 8);
        }
@@ -130,12 +130,12 @@ Key makeFsmKeyDec( char *str, const InputLoc &loc, ParseData *pd )
        long long ll = strtoll( str, 0, 10 );
 
        /* Check for underflow. */
-       if ( errno == ERANGE && ll < 0 || ll < minVal) {
+       if ( ( errno == ERANGE && ll < 0 ) || ll < minVal) {
                error(loc) << "literal " << str << " underflows the alphabet type" << endl;
                ll = minVal;
        }
        /* Check for overflow. */
-       else if ( errno == ERANGE && ll > 0 || ll > maxVal ) {
+       else if ( ( errno == ERANGE && ll > 0 ) || ll > maxVal ) {
                error(loc) << "literal " << str << " overflows the alphabet type" << endl;
                ll = maxVal;
        }
@@ -429,8 +429,11 @@ ParseData::ParseData( char *fileName, char *sectionName,
        alphTypeSet(false),
        getKeyExpr(0),
        accessExpr(0),
+       prePushExpr(0),
+       postPopExpr(0),
        pExpr(0),
        peExpr(0),
+       eofExpr(0),
        csExpr(0),
        topExpr(0),
        stackExpr(0),
@@ -468,7 +471,7 @@ ParseData::~ParseData()
 
 /* Make a name id in the current name instantiation scope if it is not
  * already there. */
-NameInst *ParseData::addNameInst( const InputLoc &loc, char *data, bool isLabel )
+NameInst *ParseData::addNameInst( const InputLoc &loc, const char *data, bool isLabel )
 {
        /* Create the name instantitaion object and insert it. */
        NameInst *newNameInst = new NameInst( loc, curNameInst, data, nextNameId++, isLabel );
@@ -553,7 +556,7 @@ void ParseData::unsetObsoleteEntries( FsmAp *graph )
        }
 }
 
-NameSet ParseData::resolvePart( NameInst *refFrom, char *data, bool recLabelsOnly )
+NameSet ParseData::resolvePart( NameInst *refFrom, const char *data, bool recLabelsOnly )
 {
        /* Queue needed for breadth-first search, load it with the start node. */
        NameInstList nameQueue;
@@ -732,21 +735,25 @@ void ParseData::resolveNameRefs( InlineList *inlineList, Action *action )
                                /* Resolve, pass action for local search. */
                                NameInst *target = resolveStateRef( *item->nameRef, item->loc, action );
 
-                               /* Check if the target goes into a longest match. */
-                               NameInst *search = target->parent;
-                               while ( search != 0 ) {
-                                       if ( search->isLongestMatch ) {
-                                               error(item->loc) << "cannot enter inside a longest "
-                                                               "match construction as an entry point" << endl;
-                                               break;
+                               /* Name lookup error reporting is handled by resolveStateRef. */
+                               if ( target != 0 ) {
+                                       /* Check if the target goes into a longest match. */
+                                       NameInst *search = target->parent;
+                                       while ( search != 0 ) {
+                                               if ( search->isLongestMatch ) {
+                                                       error(item->loc) << "cannot enter inside a longest "
+                                                                       "match construction as an entry point" << endl;
+                                                       break;
+                                               }
+                                               search = search->parent;
                                        }
-                                       search = search->parent;
-                               }
 
-                               /* Note the reference in the name. This will cause the entry
-                                * point to survive to the end of the graph generating walk. */
-                               if ( target != 0 )
+                                       /* Record the reference in the name. This will cause the
+                                        * entry point to survive to the end of the graph
+                                        * generating walk. */
                                        target->numRefs += 1;
+                               }
+
                                item->nameTarg = target;
                                break;
                        }
@@ -816,7 +823,7 @@ void ParseData::makeNameTree( GraphDictEl *dictEl )
 }
 
 
-void ParseData::createBuiltin( char *name, BuiltinMachine builtin )
+void ParseData::createBuiltin( const char *name, BuiltinMachine builtin )
 {
        Expression *expression = new Expression( builtin );
        Join *join = new Join( expression );
@@ -849,16 +856,18 @@ void ParseData::initGraphDict( )
 }
 
 /* Set the alphabet type. If the types are not valid returns false. */
-bool ParseData::setAlphType( char *s1, char *s2 )
+bool ParseData::setAlphType( const InputLoc &loc, char *s1, char *s2 )
 {
+       alphTypeLoc = loc;
        userAlphType = findAlphType( s1, s2 );
        alphTypeSet = true;
        return userAlphType != 0;
 }
 
 /* Set the alphabet type. If the types are not valid returns false. */
-bool ParseData::setAlphType( char *s1 )
+bool ParseData::setAlphType( const InputLoc &loc, char *s1 )
 {
+       alphTypeLoc = loc;
        userAlphType = findAlphType( s1 );
        alphTypeSet = true;
        return userAlphType != 0;
@@ -872,6 +881,8 @@ bool ParseData::setVariable( char *var, InlineList *inlineList )
                pExpr = inlineList;
        else if ( strcmp( var, "pe" ) == 0 )
                peExpr = inlineList;
+       else if ( strcmp( var, "eof" ) == 0 )
+               eofExpr = inlineList;
        else if ( strcmp( var, "cs" ) == 0 )
                csExpr = inlineList;
        else if ( strcmp( var, "data" ) == 0 )
@@ -882,9 +893,9 @@ bool ParseData::setVariable( char *var, InlineList *inlineList )
                stackExpr = inlineList;
        else if ( strcmp( var, "act" ) == 0 )
                actExpr = inlineList;
-       else if ( strcmp( var, "tokstart" ) == 0 )
+       else if ( strcmp( var, "ts" ) == 0 )
                tokstartExpr = inlineList;
-       else if ( strcmp( var, "tokend" ) == 0 )
+       else if ( strcmp( var, "te" ) == 0 )
                tokendExpr = inlineList;
        else
                set = false;
@@ -906,8 +917,7 @@ void ParseData::initKeyOps( )
                thisKeyOps.maxKey = makeFsmKeyNum( upperNum, rangeHighLoc, this );
        }
 
-       thisCondData.nextCondKey = thisKeyOps.maxKey;
-       thisCondData.nextCondKey.increment();
+       thisCondData.lastCondKey = thisKeyOps.maxKey;
 }
 
 void ParseData::printNameInst( NameInst *nameInst, int level )
@@ -954,7 +964,7 @@ void ParseData::removeActionDups( FsmAp *graph )
        }
 }
 
-Action *ParseData::newAction( char *name, InlineList *inlineList )
+Action *ParseData::newAction( const char *name, InlineList *inlineList )
 {
        InputLoc loc;
        loc.line = 1;
@@ -985,13 +995,13 @@ void ParseData::initLongestMatchData()
                /* The setTokStart action sets tokstart. */
                InlineList *il5 = new InlineList;
                il5->append( new InlineItem( InputLoc(), InlineItem::LmSetTokStart ) );
-               setTokStart = newAction( "tokstart", il5 );
+               setTokStart = newAction( "ts", il5 );
                setTokStart->isLmAction = true;
 
                /* The setTokEnd action sets tokend. */
                InlineList *il3 = new InlineList;
                il3->append( new InlineItem( InputLoc(), InlineItem::LmSetTokEnd ) );
-               setTokEnd = newAction( "tokend", il3 );
+               setTokEnd = newAction( "te", il3 );
                setTokEnd->isLmAction = true;
 
                /* The action will also need an ordering: ahead of all user action
@@ -1058,11 +1068,16 @@ FsmAp *ParseData::makeInstance( GraphDictEl *gdNode )
         * All state construction is now complete.
         */
 
+       /* Transfer actions from the out action tables to eof action tables. */
+       for ( StateSet::Iter state = graph->finStateSet; state.lte(); state++ )
+               graph->transferOutActions( *state );
+
        /* Transfer global error actions. */
        for ( StateList::Iter state = graph->stateList; state.lte(); state++ )
                graph->transferErrorActions( state, 0 );
        
-       removeActionDups( graph );
+       if ( ::wantDupsRemoved )
+               removeActionDups( graph );
 
        /* Remove unreachable states. There should be no dead end states. The
         * subtract and intersection operators are the only places where they may
@@ -1111,7 +1126,7 @@ void ParseData::printNameTree()
        /* Show that the name index is correct. */
        for ( int ni = 0; ni < nextNameId; ni++ ) {
                cerr << ni << ": ";
-               char *name = nameIndex[ni]->name;
+               const char *name = nameIndex[ni]->name;
                cerr << ( name != 0 ? name : "<ANON>" ) << endl;
        }
 }
@@ -1229,31 +1244,9 @@ void ParseData::checkInlineList( Action *act, InlineList *inlineList )
                /* EOF checks. */
                if ( act->numEofRefs > 0 ) {
                        switch ( item->type ) {
-                       case InlineItem::PChar: 
-                               error(item->loc) << "pointer to current element does not exist in "
-                                               "EOF action code" << endl;
-                               break;
-                       case InlineItem::Char: 
-                               error(item->loc) << "current element does not exist in "
-                                               "EOF action code" << endl;
-                               break;
-                       case InlineItem::Hold:
-                               error(item->loc) << "changing the current element not possible in "
-                                               "EOF action code" << endl;
-                               break;
-                       case InlineItem::Exec:
-                               error(item->loc) << "changing the current element not possible in "
-                                               "EOF action code" << endl;
-                               break;
-                       case InlineItem::Goto: case InlineItem::Call: 
-                       case InlineItem::Next: case InlineItem::GotoExpr: 
-                       case InlineItem::CallExpr: case InlineItem::NextExpr:
-                       case InlineItem::Ret:
-                               error(item->loc) << "changing the current state not possible in "
-                                               "EOF action code" << endl;
-                               break;
-                       default:
-                               break;
+                               /* Currently no checks. */
+                               default:
+                                       break;
                        }
                }
 
@@ -1365,8 +1358,32 @@ void ParseData::makeExports()
 
 }
 
+/* Construct the machine and catch failures which can occur during
+ * construction. */
 void ParseData::prepareMachineGen( GraphDictEl *graphDictEl )
 {
+       try {
+               /* This machine construction can fail. */
+               prepareMachineGenTBWrapped( graphDictEl );
+       }
+       catch ( FsmConstructFail fail ) {
+               switch ( fail.reason ) {
+                       case FsmConstructFail::CondNoKeySpace: {
+                               InputLoc &loc = alphTypeSet ? alphTypeLoc : sectionLoc;
+                               error(loc) << "sorry, no more characters are "
+                                               "available in the alphabet space" << endl;
+                               error(loc) << "  for conditions, please use a "
+                                               "smaller alphtype or reduce" << endl;
+                               error(loc) << "  the span of characters on which "
+                                               "conditions are embedded" << endl;
+                               break;
+                       }
+               }
+       }
+}
+
+void ParseData::prepareMachineGenTBWrapped( GraphDictEl *graphDictEl )
+{
        beginProcessing();
        initKeyOps();
        makeRootNames();
@@ -1447,6 +1464,7 @@ void writeLanguage( std::ostream &out )
                case HostLang::D:    out << "D"; break;
                case HostLang::Java: out << "Java"; break;
                case HostLang::Ruby: out << "Ruby"; break;
+               case HostLang::CSharp: out << "C#"; break;
        }
        out << "\"";