/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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 de.hhu.stups.sablecc.patch.*;


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

@SuppressWarnings({"rawtypes","unchecked","unused"})
public class Parser implements IParser
{
    public final Analysis ignoredTokens = new AnalysisAdapter();

    protected ArrayList nodeList;

    private final Lexer lexer;
    private final ListIterator stack = new LinkedList().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;
    
    private ArrayList firstPopped = null;
    private ArrayList lastPopped = null;
    private ITokenListContainer lex;

    public Parser(  Lexer lexer)
    {
        this.lexer = lexer;
        this.lex = lexer; 
    }
    
     
    private Map<PositionedNode, SourcecodeRange> mapping = new HashMap<PositionedNode, SourcecodeRange>();    
    public Map<PositionedNode, SourcecodeRange> getMapping() { 	return this.mapping; }

   private void checkResult(Object elementToCheck) {
       checkResult(elementToCheck, false);
   }

	 
	private void checkResult(Object elementToCheck, boolean slurp) {
		// nodes with no tokens or sub nodes at all may exist
		if (this.firstPopped == null) {
			return;
		}

		if (elementToCheck instanceof LinkedList) {
			/*
			 * special case: this is a list of nodes, for example an identifier
			 * list, so we don't want to check the list but the last element
			 * added to it
			 */
			final LinkedList nodeList = (LinkedList) elementToCheck;

			if (nodeList.size() > 0) {
				elementToCheck = nodeList.get(nodeList.size() - 1);
			} else {
				// no positions for empty lists...
				return;
			}
		}

		if (!(elementToCheck instanceof PositionedNode)) {
			throw new Error(
					"Unexpected elementToCheck (not instanceof PositionedNode): "
							+ elementToCheck.getClass().getSimpleName() + "/"
							+ elementToCheck);
		}

		if (!this.getMapping().containsKey(elementToCheck) || slurp ) {
			final PositionedNode node = (PositionedNode) elementToCheck;

			// dealing with a one-token element
			if (this.lastPopped == null) {
				this.lastPopped = this.firstPopped;
			}

			final int begin = findBeginPos(this.lastPopped, node);
			int end = findEndPos(this.firstPopped);
			if (end == -1) end = begin;
			final SourcecodeRange range = new SourcecodeRange(begin, end);

			this.getMapping().put(node, range);

			node.setStartPos(createBeginPos(begin));
			node.setEndPos(createEndPos(end));
		}
	}
	
	 
	private int findBeginPos(final ArrayList list,
			PositionedNode n) {
		Object first = list.get(0);
		if (!(first instanceof PositionedNode) && !(first instanceof IToken)) {
			List list2 = (List) first;

			if (list2.size() > 0) {
				first = list2.get(0);
			} else {
				/*
				 * Sometimes (haven't found out why) we get empty list here. In
				 * the only observed cases we were looking for the source range
				 * of the whole parse unit. Then the index is 0.
				 */
				return 0;
			}
		}

		if (first instanceof IToken) {
			return findIndex((IToken) first);
		}

		final PositionedNode node = (PositionedNode) first;
		final SourcecodeRange item = this.getMapping().get(node);
		if (item == null){
			System.err.println(n.getClass().getSimpleName() + " / " + node.getClass().getSimpleName() + ": " + node);
		}
		return item.getBeginIndex();
	}

	 
	private int findEndPos(final ArrayList list) {
		Object last = list.get(list.size() - 1);
		if (!(last instanceof PositionedNode) && !(last instanceof IToken)) {
			final List list2 = (List) last;
			last = list2.get(list2.size() - 1);
		}

		if (last instanceof IToken) {
			return findIndex((IToken) last);
		}

		final PositionedNode node = (PositionedNode) last;
		final SourcecodeRange item = this.getMapping().get(node);
		if (item == null)
			return -1;
		return item.getEndIndex();
	}

	private int findIndex(final IToken token) {
		final List<IToken> list = this.lex.getTokenList();

		for (int i = list.size() - 1; i >= 0; i--) {
			if (list.get(i) == token) {
				return i;
			}
		}

		return -1;
	}

	private SourcePosition createBeginPos(final int index) {
		final List<IToken> list = this.lex.getTokenList();
		final IToken token = list.get(index);
		return new SourcePosition(token.getLine(), token.getPos());
	}

	private SourcePosition createEndPos(final int index) {
		final List<IToken> list = this.lex.getTokenList();
		final IToken token = list.get(index);
		return new SourcePosition(token.getLine(), token.getPos()
				+ token.getText().length());
	}
	
$

Macro:ParserInliningPushHeader
     
    private void push(int numstate, ArrayList 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 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;

            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 pop()
    {
    	ArrayList list = ((State) this.stack.previous()).nodes; 
		if (this.firstPopped == null) {
			this.firstPopped = list;
		} else {
			this.lastPopped = list;
		}
        return list;
    }

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

     
    public Start parse() throws ParserException, LexerException, IOException
    {
    	this.getMapping().clear();
    
        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 list = new ArrayList();
		        list.add(this.lexer.next());
                        push(this.action[1], list$1$);
                    }
		    break;
                case REDUCE:
                    switch(this.action[1])
                    {

$

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

$

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

$

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:ParserNewHeader


     
    ArrayList new$0$() /* reduce $1$ */
    {
        this.firstPopped = null;
        this.lastPopped = null;
          ArrayList nodeList = new ArrayList();


$

Macro:ParserNewBodyDecl
          ArrayList nodeArrayList$0$ = pop();

$

Macro:ParserNewBodyDeclNull
        ArrayList nodeArrayList$0$ = null;

$

Macro:ParserBraceOpening
        {
            // Block

$

Macro:ParserBraceClosing
        }

$

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

$

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

$

Macro:ParserNullVariableDeclaration
          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) //Macro:ParserTypedLinkedListAddAll
	{
      $0$Node$1$.addAll($2$Node$3$);
  	  //$0$Node$1$ = $2$Node$3$;
	}

$

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

$

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

$

Macro:ParserNewTail
        // return nodeList;
        final ArrayList containerList = nodeList;
        Object elementToCheck = containerList.get(0);
        checkResult(elementToCheck);
        
        return containerList;
    }

$

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$(  $0$ node)
    {
        this.index = $1$;
    }

$

Macro:TokenIndexTail

    @Override
    public void caseEOF(  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
{
    Token token;
    String realMsg;

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

    public ParserException(  Token token, String prefix, String  message)
    {
        super(prefix+message);
        this.realMsg = message;
        this.token = token;
    }

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

    public String getRealMsg()
    {
        return this.realMsg;
    }
}

$

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

package $0$;

import java.util.ArrayList;

@SuppressWarnings("rawtypes")
final class State
{
    int state;
    ArrayList nodes;

    State(  int state,   ArrayList nodes)
    {
        this.state = state;
        this.nodes = nodes;
    }
}

$
