Beispiel #1
0
    // Algorithm's description here:
    // https://www.haskell.org/onlinereport/haskell2010/haskellch10.html
    // https://en.wikibooks.org/wiki/Haskell/Indentation
    public override IToken NextToken()
    {
        if (tokenQueue.Any())
        {
            return(tokenQueue.DequeueBottom());
        }
        IToken next = base.NextToken();
        var    type = next.Type;

        if (type == HaskellLexer.OpenPragmaBracket)
        {
            inPragmas = true;
        }
        if (startIndent == -1 &&
            type != HaskellLexer.NEWLINE &&
            type != HaskellLexer.WS &&
            type != HaskellLexer.TAB &&
            type != HaskellLexer.OCURLY)
        {
            if (type == HaskellLexer.MODULE)
            {
                moduleStartIndent = true;
                wasModuleExport   = true;
            }
            if (type != HaskellLexer.MODULE && !moduleStartIndent && !inPragmas)
            {
                startIndent = next.Column;
            }
            else if (lastKeyWord.Equals("where") && moduleStartIndent)
            {
                lastKeyWord       = "";
                prevWasKeyWord    = false;
                nestedLevel       = 0;
                moduleStartIndent = false;
                prevWasEndl       = false;
                startIndent       = next.Column;
                tokenQueue.Push(createToken(HaskellLexer.VOCURLY, "VOCURLY", next));
                tokenQueue.Push(createToken(type, next.Text, next));
                return(tokenQueue.DequeueBottom());
            }
        }
        if (type == HaskellLexer.ClosePragmaBracket)
        {
            inPragmas = false;
        }
        if (type == HaskellLexer.OCURLY)
        {
            if (prevWasKeyWord)
            {
                nestedLevel--;
                prevWasKeyWord = false;
            }
            if (moduleStartIndent)
            {
                moduleStartIndent = false;
                // because will be  HaskellLexer.CCURLY in the end of file
                wasModuleExport = false;
            }
            ignoreIndent = true;
            prevWasEndl  = false;
        }
        if (prevWasKeyWord && !prevWasEndl &&
            !moduleStartIndent &&
            type != HaskellLexer.WS &&
            type != HaskellLexer.NEWLINE &&
            type != HaskellLexer.TAB &&
            type != HaskellLexer.OCURLY)
        {
            prevWasKeyWord = false;
            indentStack.Push(new Pair <string, int>(lastKeyWord, next.Column));
            tokenQueue.Push(createToken(HaskellLexer.VOCURLY, "VOCURLY", next));
        }
        if (ignoreIndent &&
            (type == HaskellLexer.WHERE ||
             type == HaskellLexer.DO ||
             type == HaskellLexer.MDO ||
             type == HaskellLexer.LET ||
             type == HaskellLexer.OF ||
             type == HaskellLexer.LCASE ||
             type == HaskellLexer.REC ||
             type == HaskellLexer.CCURLY)
            )
        {
            ignoreIndent = false;
        }
        if (pendingDent &&
            prevWasKeyWord &&
            !ignoreIndent &&
            indentCount <= getSavedIndent() &&
            type != HaskellLexer.NEWLINE &&
            type != HaskellLexer.WS)
        {
            tokenQueue.Push(createToken(HaskellLexer.VOCURLY, "VOCURLY", next));
            prevWasKeyWord = false;
            prevWasEndl    = true;
        }
        if (pendingDent && prevWasEndl &&
            !ignoreIndent &&
            indentCount <= getSavedIndent() &&
            type != HaskellLexer.NEWLINE &&
            type != HaskellLexer.WS &&
            type != HaskellLexer.WHERE &&
            type != HaskellLexer.IN &&
            type != HaskellLexer.DO &&
            type != HaskellLexer.MDO &&
            type != HaskellLexer.OF &&
            type != HaskellLexer.LCASE &&
            type != HaskellLexer.REC &&
            type != HaskellLexer.CCURLY &&
            type != Antlr4.Runtime.TokenConstants.EOF)
        {
            while (nestedLevel > indentStack.Count())
            {
                if (nestedLevel > 0)
                {
                    nestedLevel--;
                }
                tokenQueue.Push(createToken(HaskellLexer.SEMI, "SEMI", next));
                tokenQueue.Push(createToken(HaskellLexer.VCCURLY, "VCCURLY", next));
            }
            while (indentCount < getSavedIndent())
            {
                if (indentStack.Any() && nestedLevel > 0)
                {
                    indentStack.Pop();
                    nestedLevel--;
                }
                tokenQueue.Push(createToken(HaskellLexer.SEMI, "SEMI", next));
                tokenQueue.Push(createToken(HaskellLexer.VCCURLY, "VCCURLY", next));
            }
            if (indentCount == getSavedIndent())
            {
                tokenQueue.Push(createToken(HaskellLexer.SEMI, "SEMI", next));
            }
            prevWasEndl = false;
            if (indentCount == startIndent)
            {
                pendingDent = false;
            }
        }
        if (pendingDent && prevWasKeyWord &&
            !moduleStartIndent &&
            !ignoreIndent &&
            indentCount > getSavedIndent() &&
            type != HaskellLexer.NEWLINE &&
            type != HaskellLexer.WS &&
            type != Antlr4.Runtime.TokenConstants.EOF)
        {
            prevWasKeyWord = false;
            if (prevWasEndl)
            {
                indentStack.Push(new Pair <string, int>(lastKeyWord, indentCount));
                prevWasEndl = false;
            }
            tokenQueue.Push(createToken(HaskellLexer.VOCURLY, "VOCURLY", next));
        }
        if (pendingDent &&
            initialIndentToken == null &&
            HaskellLexer.NEWLINE != type)
        {
            initialIndentToken = next;
        }
        if (next != null && type == HaskellLexer.NEWLINE)
        {
            prevWasEndl = true;
        }
        if (type == HaskellLexer.WHERE ||
            type == HaskellLexer.LET ||
            type == HaskellLexer.DO ||
            type == HaskellLexer.MDO ||
            type == HaskellLexer.OF ||
            type == HaskellLexer.LCASE ||
            type == HaskellLexer.REC)
        {
            // if next will be HaskellLexer.OCURLY need to decrement nestedLevel
            nestedLevel++;
            prevWasKeyWord = true;
            prevWasEndl    = false;
            lastKeyWord    = next.Text;
            if (type == HaskellLexer.WHERE)
            {
                if (indentStack.Any() &&
                    (indentStack.Peek().first().Equals("do") ||
                     indentStack.Peek().first().Equals("mdo")))
                {
                    tokenQueue.Push(createToken(HaskellLexer.SEMI, "SEMI", next));
                    tokenQueue.Push(createToken(HaskellLexer.VCCURLY, "VCCURLY", next));
                    indentStack.Pop();
                    nestedLevel--;
                }
            }
        }
        if (next != null && type == HaskellLexer.OCURLY)
        {
            prevWasKeyWord = false;
        }
        if (next == null || Antlr4.Runtime.TokenConstants.HiddenChannel == next.Channel || HaskellLexer.NEWLINE == type)
        {
            return(next);
        }
        if (type == HaskellLexer.IN)
        {
            processINToken(next);
        }
        if (type == Antlr4.Runtime.TokenConstants.EOF)
        {
            processEOFToken(next);
        }
        pendingDent = true;
        tokenQueue.Push(next);
        return(tokenQueue.DequeueBottom());
    }