--
--
-- In a parser using this template, the following macro may be redefined:
--
--     $additional_interfaces
--     $ast_class
--
-- B E G I N N I N G   O F   T E M P L A T E   btVTCLParserTemplateD
--
%Options programming_language=java,margin=4,backtrack
%Options table,error_maps,scopes
%options prefix=TK_,
%options action=("*.java", "/.", "./")
%options ParseTable=lpg.lpgjavaruntime.ParseTable

--
-- This template requires that the name of the EOF token be set
-- to EOF_TOKEN to be consistent with LexerTemplateD and LexerTemplateE
--
$EOF
    EOF_TOKEN
$End

$ERROR
    ERROR_TOKEN
$End

$Define

    $Header
    /.
                //
                // Rule $rule_number:  $rule_text
                //./

    $BeginAction
    /. $Header
                case $rule_number: {./

    $EndAction
    /.          break;
                }./

    $BeginJava
    /.$BeginAction
                    $symbol_declarations./

    $EndJava /.$EndAction./

    $NoAction
    /. $Header
                case $rule_number:
                    break;./

    $BadAction
    /. $Header
                case $rule_number:
                    throw new Error("No action specified for rule " + $rule_number);./

    $NullAction
    /. $Header
                case $rule_number:
                    setResult(null);
                    break;./

    $BeginActions
    /.
        public void ruleAction(int ruleNumber)
        {
            switch (ruleNumber)
            {./

    $SplitActions
    /.
	            default:
	                ruleAction$rule_number(ruleNumber);
	                break;
	        }
	        return;
	    }
	
	    public void ruleAction$rule_number(int ruleNumber)
	    {
	        switch (ruleNumber)
	        {./

    $EndActions
    /.
                default:
                    break;
            }
            return;
        }./

    --
    -- Macros that may be needed in a parser using this template
    --
    $additional_interfaces /../
    $ast_class /.$ast_type./

    --
    -- Old deprecated macros that should NEVER be used.
    --
    $setSym1 /. // macro setSym1 is deprecated. Use function setResult
                getParser().setSym1./
    $setResult /. // macro setResult is deprecated. Use function setResult
                 getParser().setSym1./
    $getSym /. // macro getSym is deprecated. Use function getRhsSym
              getParser().getSym./
    $getToken /. // macro getToken is deprecated. Use function getRhsTokenIndex
                getParser().getToken./
    $getIToken /. // macro getIToken is deprecated. Use function getRhsIToken
                 super.getIToken./
    $getLeftSpan /. // macro getLeftSpan is deprecated. Use function getLeftSpan
                   getParser().getFirstToken./
    $getRightSpan /. // macro getRightSpan is deprecated. Use function getRightSpan
                    getParser().getLastToken./
$End

$Globals
    /.import lpg.lpgjavaruntime.*;
    ./
$End

$Headers
    /.
import org.eclipse.viatra2.errors.info.ErrorInformation;
import org.eclipse.viatra2.errors.info.Location;
import org.eclipse.viatra2.lpgparser.loader.VTCLMessages;
import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorKind;
import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorSeverity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.viatra2.lpgparser.loader.ExplanationGenerator;
	  
    public class $action_type extends PrsStream implements RuleAction$additional_interfaces {
        final String PARSER_MARKER = "org.eclipse.viatra2.loaders.vtclparsermarker";

        ExplanationGenerator generator = new ExplanationGenerator(this);

        private java.util.List<ErrorInformation> allErrorInfos = new java.util.ArrayList<ErrorInformation>();
	    public java.util.List<ErrorInformation> getAllErrorInfos() {
            return allErrorInfos;
        }
        
        public void clearParseErrorList() {
	    if (allErrorInfos == null)
		    allErrorInfos = new java.util.ArrayList<ErrorInformation>();
	    else
		    allErrorInfos.clear();
    }
    
        private static ParseTable prs = new $prs_type();
        private BacktrackingParser btParser;

        public BacktrackingParser getParser() { return btParser; }
        private void setResult(Object object) { btParser.setSym1(object); }
        public Object getRhsSym(int i) { return btParser.getSym(i); }

        public int getRhsTokenIndex(int i) { return btParser.getToken(i); }
        public IToken getRhsIToken(int i) { return super.getIToken(getRhsTokenIndex(i)); }
        
        public int getRhsFirstTokenIndex(int i) { return btParser.getFirstToken(i); }
        public IToken getRhsFirstIToken(int i) { return super.getIToken(getRhsFirstTokenIndex(i)); }

        public int getRhsLastTokenIndex(int i) { return btParser.getLastToken(i); }
        public IToken getRhsLastIToken(int i) { return super.getIToken(getRhsLastTokenIndex(i)); }

        public int getLeftSpan() { return btParser.getFirstToken(); }
        public IToken getLeftIToken()  { return super.getIToken(getLeftSpan()); }

        public int getRightSpan() { return btParser.getLastToken(); }
        public IToken getRightIToken() { return super.getIToken(getRightSpan()); }

        public int getRhsErrorTokenIndex(int i) {
            int index = btParser.getToken(i);
            IToken err = super.getIToken(index);
            return (err instanceof ErrorToken ? index : 0);
        }
        public ErrorToken getRhsErrorIToken(int i) {
            int index = btParser.getToken(i);
            IToken err = super.getIToken(index);
            return (ErrorToken) (err instanceof ErrorToken ? err : null);
        }

        public $action_type(LexStream lexStream) {
            super(lexStream);

            try {
                super.remapTerminalSymbols(orderedTerminalSymbols(), $prs_type.EOFT_SYMBOL);
            } catch(NullExportedSymbolsException e) {
            } catch(NullTerminalSymbolsException e) {
            } catch(UnimplementedTerminalsException e) {
                java.util.ArrayList unimplemented_symbols = e.getSymbols();
                System.out.println("The Lexer will not scan the following token(s):");
                for (int i = 0; i < unimplemented_symbols.size(); i++) {
                    Integer id = (Integer) unimplemented_symbols.get(i);
                    System.out.println("    " + $sym_type.orderedTerminalSymbols[id.intValue()]);               
                }
                System.out.println();                        
            }
            catch(UndefinedEofSymbolException e) {
                throw new Error(new UndefinedEofSymbolException
                                    ("The Lexer does not implement the Eof symbol " +
                                     $sym_type.orderedTerminalSymbols[$prs_type.EOFT_SYMBOL]));
            } 
        }

        public String[] orderedTerminalSymbols() { return $sym_type.orderedTerminalSymbols; }
        public String getTokenKindName(int kind) { return $sym_type.orderedTerminalSymbols[kind]; }
        public int getEOFTokenKind() { return $prs_type.EOFT_SYMBOL; }
        public PrsStream getParseStream() { return this; }
        
    
	/**
	 * Called when encountering a single bad character. Do not report
	 * this error at this point.
	 */
	public void reportError(int left_char, int right_char) {
//		System.out.println("reportError(int, int)");	    
	}

	/**
	 * Reports the parse error by setting the error to <code>errorString</code>
	 * 
	 * @param errorCode the error code
	 * @param locationInfo
	 * @param leftToken the token to the left of the error
	 * @param rightToken the token to the right of the error
	 * @param tokenText the text of the bad token
	 */
	public void reportError(int errorCode, String locationInfo, int leftToken, int rightToken, String tokenText) {
	
	    int leftTokenLoc = (leftToken > rightToken ? rightToken : leftToken);
	    int rightTokenLoc = rightToken;
	    String errorString;
	
	    if (getLine(leftTokenLoc)  <= 0) {
	 	    errorString =  VTCLMessages.InvalidVTCL_ERROR_;
	        allErrorInfos.add(new ErrorInformation(errorString, PARSER_MARKER, ErrorKind.PARSE_ERROR)); 
	    } 
	    else {
      Location location = new Location(
    		getLine(leftTokenLoc),
    		getColumn(leftTokenLoc), 
		getEndLine(rightTokenLoc),
		getEndColumn(rightTokenLoc) + 1,
		getStartOffset(leftTokenLoc),
		getEndOffset(rightTokenLoc));
		
		switch (errorCode) {
		case EOF_CODE:
		case MISPLACED_CODE:
	        case DELETION_CODE:
	            errorString = " Syntax error: " + errorMsgText[errorCode] + " " +    
	    		      	'"' + computeInputString(
	    				getIToken(leftToken).getStartOffset(),
	    				getIToken(rightToken).getEndOffset()) + '"';
	            break;
	        case INVALID_TOKEN_CODE:
	             errorString = " Syntax error: Token" +  " " +    
	    		          '"' + computeInputString(
	    				getIToken(leftToken).getStartOffset(),
	    				getIToken(rightToken).getEndOffset()) + '"'
                              + " " + errorMsgText[errorCode] + ".";
	             String explanation = generator.calculateErrorExplanation(tokenText, leftToken, rightToken);
	             if (explanation != "") {
	    	     errorString = errorString + " Cause: " + explanation + ".";
	            }
	        break;
	
		case MERGE_CODE:
		case BEFORE_CODE:
		case INSERTION_CODE:
		case SCOPE_CODE:
		case SUBSTITUTION_CODE: // includes SECONDARY_CODE
		    errorString = " Syntax error: " + tokenText + " " + errorMsgText[errorCode] + " " + 
			'"' + computeInputString(
				getIToken(leftToken).getStartOffset(),
				getIToken(rightToken).getEndOffset()) + '"';
		    break;
	
		default:
		    errorString = " Syntax error: " + errorMsgText[errorCode] + " at token " + tokenText;
		break;
		}
		allErrorInfos.add(new 
			ErrorInformation(errorString,
				PARSER_MARKER,
				ErrorKind.PARSE_ERROR,
				location,
				ErrorSeverity.ERROR));
	 }
	    
	}
	 

	/**
	 * Returns a single line string representation of the input chars
	 * for the given range.
	 * 
	 * @param left left most char index
	 * @param right right most char index
	 * @return a single line string representation of the input chars
	 */
	private String computeInputString(int left, int right) {
		StringBuffer result = new StringBuffer(right - left + 1);
		char[] chars = getInputChars();

		for (int i = left; i <= right; i++) {
			if (chars[i] == '\t') {
				result.append(' ');
			} else if (chars[i] == '\n' || chars[i] == '\r' || chars[i] == '\f') {
				if (i > 0) {
					if (!Character.isWhitespace(chars[i-1])) {
						result.append(' ');
					}
				}
			} else {
				result.append(chars[i]);
			}
				
		}
		return result.toString();
	}
	

        
    /**
     * Report error message for given error_token by calling 
     * method <code>reportError/5</code> is called finally
     * @param error_token 
     * @param msg 
     */
    public final void reportErrorTokenMessage(int error_token, String msg)
    {
        allErrorInfos.add(new 
		ErrorInformation(msg, 
				PARSER_MARKER,
			    ErrorKind.PARSE_ERROR,
				getLine(error_token),  
				getColumn(error_token),
				getEndLine(error_token),
				getEndColumn(error_token)));
    }

    /** 
     * This SymbolTable class is from the IMP project
     */
    public static class SymbolTable {
        private Map<String,ASTNode> table = new HashMap<String,ASTNode>();

        public void addDefinition(String name, ASTNode def) { table.put(name, def); }
        public ASTNode lookup(String name) { return table.get(name); }
        public List<String> allSymbolsOfType(Class type) {
            List<String> result= new ArrayList<String>();

            for(String sym: table.keySet()) {
                ASTNode def= table.get(sym);

                if (type.isInstance(def))
                    result.add(sym);
            }
            return result;
        }
        public <T> List<T> allDefsOfType(Class<T> type) {
            List<T> result = new ArrayList<T>();
            
            for(String sym: table.keySet()) {
                ASTNode def= table.get(sym);

                if (type.isInstance(def))
                    result.add((T) def);
            }
            return result;
        }
        public Set<String> allSymbols() { return table.keySet(); }
    }
//    protected static SymbolTable symtab;
//    { symtab = new SymbolTable(); }

        public $ast_class parser()
        {
            return parser(null, 0);
        }
        
        public $ast_class parser(Monitor monitor)
        {
            return parser(monitor, 0);
        }
        
        public $ast_class parser(int error_repair_count)
        {
            return parser(null, error_repair_count);
        }

        public $ast_class parser(Monitor monitor, int error_repair_count)
        {
            try
            {
                btParser = new BacktrackingParser(monitor, this, prs, this);
            }
            catch (NotBacktrackParseTableException e)
            {
                throw new Error(new NotBacktrackParseTableException
                                    ("Regenerate $prs_type.java with -BACKTRACK option"));
            }
            catch (BadParseSymFileException e)
            {
                throw new Error(new BadParseSymFileException("Bad Parser Symbol File -- $sym_type.java"));
            }

            try
            {
                return ($ast_class) btParser.parse(error_repair_count);
            }
            catch (BadParseException e)
            {
                reset(e.error_token); // point to error token
                DiagnoseParser diagnoseParser = new DiagnoseParser(this, prs);
                diagnoseParser.diagnose(e.error_token);
            }

            return null;
        }

    ./

$End

$Rules
    /.$BeginActions./
$End

$Trailers
    /.
        $EndActions
    }
    ./
$End

--
-- E N D   O F   T E M P L A T E
--
