/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This file is part of SableCC.                             *
 * See the file "LICENSE" for copyright information and the  *
 * terms and conditions for copying, distribution and        *
 * modification of SableCC.                                  *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

Macro:ParserHeader
/* This file was generated by SableCC (http://www.sablecc.org/). */

package $0$;

import $1$.*;
import $2$.*;
import $3$.*;
import java.util.*;

import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

@SuppressWarnings("nls")
public class Parser
{
    public final Analysis ignoredTokens = new AnalysisAdapter();

    protected ArrayList<Object> nodeList;

    private final Lexer lexer;
    private final ListIterator<Object> stack = new LinkedList<Object>().listIterator();
    private int last_pos;
    private int last_line;
    private Token last_token;
    private final TokenIndex converter = new TokenIndex();
    private final int[] action = new int[2];

    private final static int SHIFT = 0;
    private final static int REDUCE = 1;
    private final static int ACCEPT = 2;
    private final static int ERROR = 3;

    public Parser(@SuppressWarnings("hiding") Lexer lexer)
    {
        this.lexer = lexer;
    }


$

Macro:ParserInliningPushHeader
    @SuppressWarnings({"unchecked","unused"})
    private void push(int numstate, ArrayList<Object> listNode) throws ParserException, LexerException, IOException
    {
        this.nodeList = listNode;


$

Macro:ParserNoInliningPushHeader
    protected void filter() throws ParserException, LexerException, IOException
    {
        // Empty body
    }

    private void push(int numstate, ArrayList<Object> listNode, boolean hidden) throws ParserException, LexerException, IOException
    {
        this.nodeList = listNode;

        if(!hidden)
        {
            filter();
        }


$

Macro:ParserCommon
        if(!this.stack.hasNext())
        {
            this.stack.add(new State(numstate, this.nodeList));
            return;
        }

        State s = (State) this.stack.next();
        s.state = numstate;
        s.nodes = this.nodeList;
    }

    private int goTo(int index)
    {
        int state = state();
        int low = 1;
        int high = gotoTable[index].length - 1;
        int value = gotoTable[index][0][1];

        while(low <= high)
        {
            // int middle = (low + high) / 2;
            int middle = (low + high) >>> 1;

            if(state < gotoTable[index][middle][0])
            {
                high = middle - 1;
            }
            else if(state > gotoTable[index][middle][0])
            {
                low = middle + 1;
            }
            else
            {
                value = gotoTable[index][middle][1];
                break;
            }
        }

        return value;
    }

    private int state()
    {
        State s = (State) this.stack.previous();
        this.stack.next();
        return s.state;
    }

    private ArrayList<Object> pop()
    {
        return ((State) this.stack.previous()).nodes;
    }

    private int index(Switchable token)
    {
        this.converter.index = -1;
        token.apply(this.converter);
        return this.converter.index;
    }

    @SuppressWarnings("unchecked")
    public Start parse() throws ParserException, LexerException, IOException
    {
        push(0, null$0$);
        List<Node> ign = null;
        while(true)
        {
            while(index(this.lexer.peek()) == -1)
            {
                if(ign == null)
                {
                    ign = new LinkedList<Node>();
                }

                ign.add(this.lexer.next());
            }

            if(ign != null)
            {
                this.ignoredTokens.setIn(this.lexer.peek(), ign);
                ign = null;
            }

            this.last_pos = this.lexer.peek().getPos();
            this.last_line = this.lexer.peek().getLine();
            this.last_token = this.lexer.peek();

            int index = index(this.lexer.peek());
            this.action[0] = Parser.actionTable[state()][0][1];
            this.action[1] = Parser.actionTable[state()][0][2];

            int low = 1;
            int high = Parser.actionTable[state()].length - 1;

            while(low <= high)
            {
                int middle = (low + high) / 2;

                if(index < Parser.actionTable[state()][middle][0])
                {
                    high = middle - 1;
                }
                else if(index > Parser.actionTable[state()][middle][0])
                {
                    low = middle + 1;
                }
                else
                {
                    this.action[0] = Parser.actionTable[state()][middle][1];
                    this.action[1] = Parser.actionTable[state()][middle][2];
                    break;
                }
            }

            switch(this.action[0])
            {
                case SHIFT:
		    {
		        ArrayList<Object> list = new ArrayList<Object>();
		        list.add(this.lexer.next());
                        push(this.action[1], list$1$);
                    }
		    break;
                case REDUCE:
                    {
                        int reduction = this.action[1];
                        if(reduction < 500) reduce_0(reduction);

$

Macro:ParseReduceElseIf
                        else if(reduction < $0$) reduce_$1$(reduction);

$

Macro:ParserParseTail
                    }
                    break;
                case ACCEPT:
                    {
                        EOF node2 = (EOF) this.lexer.next();
                        $0$ node1 = ($0$) pop().get(0);
                        Start node = new Start(node1, node2);
                        return node;
                    }
                case ERROR:
                    throw new ParserException(this.last_token,
                        "[" + this.last_line + "," + this.last_pos + "] " +
                        Parser.errorMessages[Parser.errors[this.action[1]]]);
            }
        }
    }


$

Macro:ParserReduceHead
    private void reduce_$0$(int reduction) throws IOException, LexerException, ParserException
    {
        switch(reduction)
        {

$

Macro:ParserInliningReduce
            case $0$: /* reduce $2$ */
            {
                ArrayList<Object> list = new$0$();
                push(goTo($1$), list);
            }
            break;

$

Macro:ParserNoInliningReduce
            case $0$: /* reduce $3$ */
            {
                ArrayList<Object> list = new$0$();
                push(goTo($1$), list, $2$);
            }
            break;

$

Macro:ParserReduceTail
        }
    }


$

Macro:ParserNewHeader


    @SuppressWarnings({ "unchecked", "rawtypes" })
    ArrayList<Object> new$0$() /* reduce $1$ */
    {
        @SuppressWarnings("hiding") ArrayList<Object> nodeList = new ArrayList<Object>();


$

Macro:ParserNewBodyDecl
        @SuppressWarnings("unused") ArrayList<Object> nodeArrayList$0$ = pop();

$

Macro:ParserNewBodyDeclNull
        ArrayList<Object> nodeArrayList$0$ = null;

$

Macro:ParserBraceOpening
        {
            // Block

$

Macro:ParserBraceClosing
        }

$

Macro:ParserSimpleVariableDeclaration
        $0$ $1$Node$2$;

$

Macro:ParserListVariableDeclaration
        LinkedList<Object> listNode$0$ = new LinkedList<Object>();

$

Macro:ParserNullVariableDeclaration
        @SuppressWarnings("unused") Object nullNode$0$ = null;

$

Macro:ParserSimpleTerm
        $0$Node$1$ = ($2$)nodeArrayList$3$.get($4$);

$

Macro:ParserNewBodyNew

        $0$Node$1$ = new $2$(
$

Macro:ParserNew&ListBodyParams
$0$Node$1$
$

Macro:ParserNew&ListBodyParamsNull
$0$
$

Macro:ParserNewBodyNewTail
);

$

Macro:ParserTypedLinkedListAdd
	if($2$Node$3$ != null)
	{
	  $0$Node$1$.add($2$Node$3$);
	}

$

Macro:ParserTypedLinkedListAddAll
	if($2$Node$3$ != null)
	{
	  $0$Node$1$.addAll($2$Node$3$);
	}

$

Macro:ParserTypedLinkedListAddAll2
	if($2$ != null)
	{
	  $0$Node$1$.addAll($2$);
	}

$

Macro:ParserNewBodyListAdd
	nodeList.add($0$Node$1$);

$

Macro:ParserNewTail
        return nodeList;
    }


$

Macro:ParserActionHeader


    private static int[][][] actionTable;
/*      {

$

Macro:ParserActionTail
        };*/

$

Macro:ParserGotoHeader
    private static int[][][] gotoTable;
/*      {

$

Macro:ParserGotoTail
        };*/

$

Macro:ParserErrorsHeader
    private static String[] errorMessages;
/*      {

$

Macro:ParserErrorsTail
        };*/

$

Macro:ParserErrorIndexHeader
    private static int[] errors;
/*      {

$

Macro:ParserErrorIndexTail

        };*/

$

Macro:ParserTail

    static 
    {
        try
        {
            DataInputStream s = new DataInputStream(
                new BufferedInputStream(
                Parser.class.getResourceAsStream("parser.dat")));

            // read actionTable
            int length = s.readInt();
            Parser.actionTable = new int[length][][];
            for(int i = 0; i < Parser.actionTable.length; i++)
            {
                length = s.readInt();
                Parser.actionTable[i] = new int[length][3];
                for(int j = 0; j < Parser.actionTable[i].length; j++)
                {
                for(int k = 0; k < 3; k++)
                {
                    Parser.actionTable[i][j][k] = s.readInt();
                }
                }
            }

            // read gotoTable
            length = s.readInt();
            gotoTable = new int[length][][];
            for(int i = 0; i < gotoTable.length; i++)
            {
                length = s.readInt();
                gotoTable[i] = new int[length][2];
                for(int j = 0; j < gotoTable[i].length; j++)
                {
                for(int k = 0; k < 2; k++)
                {
                    gotoTable[i][j][k] = s.readInt();
                }
                }
            }

            // read errorMessages
            length = s.readInt();
            errorMessages = new String[length];
            for(int i = 0; i < errorMessages.length; i++)
            {
                length = s.readInt();
                StringBuffer buffer = new StringBuffer();

                for(int j = 0; j < length; j++)
                {
                buffer.append(s.readChar());
                }
                errorMessages[i] = buffer.toString();
            }

            // read errors
            length = s.readInt();
            errors = new int[length];
            for(int i = 0; i < errors.length; i++)
            {
                errors[i] = s.readInt();
            }

            s.close();
        }
        catch(Exception e)
        {
            throw new RuntimeException("The file \"parser.dat\" is either missing or corrupted.");
        }
    }
}

$

Macro:TokenIndexHeader
/* This file was generated by SableCC (http://www.sablecc.org/). */

package $0$;

import $1$.*;
import $2$.*;

class TokenIndex extends AnalysisAdapter
{
    int index;

$

Macro:TokenIndexBody

    @Override
    public void case$0$(@SuppressWarnings("unused") $0$ node)
    {
        this.index = $1$;
    }

$

Macro:TokenIndexTail

    @Override
    public void caseEOF(@SuppressWarnings("unused") EOF node)
    {
        this.index = $0$;
    }
}

$

Macro:ParserException
/* This file was generated by SableCC (http://www.sablecc.org/). */

package $0$;

import $1$.*;

@SuppressWarnings("serial")
public class ParserException extends Exception
{
    private Token token;

    public ParserException(@SuppressWarnings("hiding") Token token, String  message)
    {
        super(message);
        this.token = token;
    }

    public Token getToken()
    {
        return this.token;
    }
}

$

Macro:State
/* This file was generated by SableCC (http://www.sablecc.org/). */

package $0$;

import java.util.ArrayList;

final class State
{
    int state;
    ArrayList<Object> nodes;

    State(@SuppressWarnings("hiding") int state, @SuppressWarnings("hiding") ArrayList<Object> nodes)
    {
        this.state = state;
        this.nodes = nodes;
    }
}

$
