/**
 * AM1 Simulator - simulating am1 code in an abstract machine based on the
 * definitions of the lectures 'Programmierung' at TU Dresden.
 * Copyright (C) 2010 Max Leuthäuser
 * Contact: s7060241@mail.zih.tu-dresden.de
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* WARNING: This is generated code. DO *NOT* MODIFY IT! */

package org.jalgo.module.am1simulator.parser.am1;

import org.jalgo.module.am1simulator.parser.ParserUtils;
import org.jalgo.module.am1simulator.parser.ErrorEvents;
import org.jalgo.module.am1simulator.model.am1.*;
import org.jalgo.module.am1simulator.model.AddressException;
import org.jalgo.module.am1simulator.model.LineAddress;
import beaver.*;
import org.jalgo.module.am1simulator.model.am1.AbstractStatementFactory.Statement;

/**
 * This class is a LALR parser generated by <a
 * href="http://beaver.sourceforge.net">Beaver</a> v0.9.6.1 from the grammar
 * specification "am1-parser.g".
 */
public class GeneratedAM1Parser extends Parser {
	static public class Terminals {
		static public final short EOF = 0;
		static public final short SEMICOLON = 1;
		static public final short NUMBER = 2;
		static public final short MINUS = 3;
		static public final short LBRAKET = 4;
		static public final short RBRAKET = 5;
		static public final short COMMA = 6;
		static public final short LOCAL = 7;
		static public final short GLOBAL = 8;
		static public final short LOAD = 9;
		static public final short LOADA = 10;
		static public final short STORE = 11;
		static public final short WRITE = 12;
		static public final short READ = 13;
		static public final short LOADI = 14;
		static public final short STOREI = 15;
		static public final short WRITEI = 16;
		static public final short READI = 17;
		static public final short ADD = 18;
		static public final short MUL = 19;
		static public final short SUB = 20;
		static public final short DIV = 21;
		static public final short MOD = 22;
		static public final short EQ = 23;
		static public final short NE = 24;
		static public final short LT = 25;
		static public final short GT = 26;
		static public final short LE = 27;
		static public final short GE = 28;
		static public final short JMP = 29;
		static public final short JMC = 30;
		static public final short PUSH = 31;
		static public final short CALL = 32;
		static public final short INIT = 33;
		static public final short RET = 34;
		static public final short LIT = 35;
		static public final short EOL = 36;
	}

	static final ParsingTables PARSING_TABLES = new ParsingTables(
			"U9ojrETF544O1l1dpxkpeuA89o3YUGKGss4vK50FHL6mOGAVnCGFVh1tOiDEWht7NZweqMZ"
					+ "K#D$OU##A$VNPlJcoZdSc4EVocsVctTdDxcnk0Tn03sGZ3qDHWW06emZZu4PRj4DxT417T4"
					+ "9d9A4Bkg8RkcCYoZ4PbPZQohEcmo4tHP25FaX19ZBGoqfpdW6VgkNOZWzK6RBLmbOwqORZK"
					+ "RPwH6MPocbmoG$vBj$agtoH9laid#IZV93tI4QAl4Cg#xVeYJJc6$I61#dm8b$koXtqHJ$u"
					+ "vJM2yWgvw8$XyX93C023v0KAC0mZv3aACLAUOGoAKOhHyXJZCHOJv8aynYHUyH4gs3$45FO"
					+ "Fv3vcnDaRtWVt9vMxcSRxy70tqddVcRmNywcoUHVULfuLv2xc0jOxSN2dVF1RQSvZOpFru$"
					+ "5gGUv5ehMnD1ByV5mHwmDyPz6P6oxE0amtQ#RCO1fC9wj6SyrbZQ9fdkzIezZnFwyVxSqVK"
					+ "5NFJaIQ665AflbcZMq1BQH5j9YMq59QHijf1QsaLLH7gzLvQsWThQKGhQT2sa0RrPfwbPje"
					+ "CssZ8jfAnTH0EwYHIcaxxQAT5A7TL4vxQH$jeKhQJuVe85NG0VCPwJ0TfIDKJSVe19sa6Zf"
					+ "5jNISpj9fcaDdw1oTfmjqaIxHPRf2LsakNQFhvZEfvqfIMH2hjGJRJDkusZQkKUdHri#ASu"
					+ "rQbLbQtQlDPwlCqUhvsdoUof1M3slpEfKbMZsYpRUeR53PgB9CMrU5vYO$aR39lRygj#bMu"
					+ "ZF#RvDVxBpycXZyfZZ8oI#2qG8EnQqu$v7szL4#wvyVvRSuaFSR#VQ$gm==");

	private ArithmeticStatementFactory arithmetic = new ArithmeticStatementFactory();
	private CompareStatementFactory compare = new CompareStatementFactory();
	private IOStatementFactory io = new IOStatementFactory();
	private JumpStatementFactory jump = new JumpStatementFactory();
	private MemoryStatementFactory memory = new MemoryStatementFactory();
	private ProceduralStatementFactory procedural = new ProceduralStatementFactory();

	private LineAddress address(Symbol symbol) {
		try {
			return new LineAddress(Symbol.getLine(symbol.getStart()));
		} catch (AddressException e) {
			return null;
		}
	}

	public ErrorEvents getErrorEvents() {
		return (ErrorEvents) report;
	}

	private final Action[] actions;

	public GeneratedAM1Parser() {
		super(PARSING_TABLES);
		actions = new Action[] { Action.RETURN, // [0] Program = CommandList
				new Action() { // [1] CommandList = Command.a SEMICOLON
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol _symbol_a = _symbols[offset + 1];
						final SimulationStatement a = (SimulationStatement) _symbol_a.value;
						AM1Program program = new AM1Program();
						program.add(a);
						return new Symbol(program);
					}
				}, new Action() { // [2] CommandList = CommandList.a EOL
									// Command.b SEMICOLON
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol _symbol_a = _symbols[offset + 1];
						final AM1Program a = (AM1Program) _symbol_a.value;
						final Symbol _symbol_b = _symbols[offset + 3];
						final SimulationStatement b = (SimulationStatement) _symbol_b.value;
						a.add(b);
						return new Symbol(a);
					}
				}, new Action() { // [3] Command = ADD.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(arithmetic.newStatement(
								Statement.ADD, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [4] Command = MUL.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(arithmetic.newStatement(
								Statement.MUL, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [5] Command = SUB.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(arithmetic.newStatement(
								Statement.SUB, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [6] Command = DIV.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(arithmetic.newStatement(
								Statement.DIV, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [7] Command = MOD.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(arithmetic.newStatement(
								Statement.MOD, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [8] Command = EQ.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(Statement.EQUAL,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [9] Command = NE.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(
								Statement.NOTEQUAL,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [10] Command = LT.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(
								Statement.LESSERTHEN,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [11] Command = GT.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(
								Statement.GREATERTHEN,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [12] Command = LE.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(
								Statement.LESSEREQUAL,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [13] Command = GE.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(compare.newStatement(
								Statement.GREATEREQUAL,
								new StatementResource.Builder(address(a))
										.build()));
					}
				}, new Action() { // [14] Command = JMP.a UnsignedNumber.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(jump.newStatement(Statement.JMP,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [15] Command = JMC.a UnsignedNumber.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(jump.newStatement(Statement.JMC,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [16] Command = LOAD.a LBRAKET Location.b
									// COMMA Number.c RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final String b = (String) _symbol_b.value;
						final Symbol _symbol_c = _symbols[offset + 5];
						final Integer c = (Integer) _symbol_c.value;
						return new Symbol(memory.newStatement(Statement.LOAD,
								new StatementResource.Builder(address(a))
										.location(b).value(c).build()));
					}
				}, new Action() { // [17] Command = LOADA.a LBRAKET Location.b
									// COMMA Number.c RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final String b = (String) _symbol_b.value;
						final Symbol _symbol_c = _symbols[offset + 5];
						final Integer c = (Integer) _symbol_c.value;
						return new Symbol(memory.newStatement(Statement.LOADA,
								new StatementResource.Builder(address(a))
										.location(b).value(c).build()));
					}
				}, new Action() { // [18] Command = LOADI.a LBRAKET Number.b
									// RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(memory.newStatement(Statement.LOADI,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [19] Command = STORE.a LBRAKET Location.b
									// COMMA Number.c RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final String b = (String) _symbol_b.value;
						final Symbol _symbol_c = _symbols[offset + 5];
						final Integer c = (Integer) _symbol_c.value;
						return new Symbol(memory.newStatement(Statement.STORE,
								new StatementResource.Builder(address(a))
										.location(b).value(c).build()));
					}
				}, new Action() { // [20] Command = STOREI.a LBRAKET Number.b
									// RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(memory.newStatement(Statement.STOREI,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [21] Command = WRITE.a LBRAKET Location.b
									// COMMA Number.c RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final String b = (String) _symbol_b.value;
						final Symbol _symbol_c = _symbols[offset + 5];
						final Integer c = (Integer) _symbol_c.value;
						return new Symbol(io.newStatement(Statement.WRITE,
								new StatementResource.Builder(address(a))
										.location(b).value(c).build()));
					}
				}, new Action() { // [22] Command = WRITEI.a LBRAKET Number.b
									// RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(io.newStatement(Statement.WRITEI,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [23] Command = READ.a LBRAKET Location.b
									// COMMA Number.c RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final String b = (String) _symbol_b.value;
						final Symbol _symbol_c = _symbols[offset + 5];
						final Integer c = (Integer) _symbol_c.value;
						return new Symbol(io.newStatement(Statement.READ,
								new StatementResource.Builder(address(a))
										.location(b).value(c).build()));
					}
				}, new Action() { // [24] Command = READI.a LBRAKET Number.b
									// RBRAKET
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 3];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(io.newStatement(Statement.READI,
								new StatementResource.Builder(address(a))
										.value(b).build()));
					}
				}, new Action() { // [25] Command = PUSH.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(procedural.newStatement(
								Statement.PUSH, new StatementResource.Builder(
										address(a)).build()));
					}
				}, new Action() { // [26] Command = CALL.a UnsignedNumber.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(procedural.newStatement(
								Statement.CALL, new StatementResource.Builder(
										address(a)).value(b).build()));
					}
				}, new Action() { // [27] Command = INIT.a UnsignedNumber.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(procedural.newStatement(
								Statement.INIT, new StatementResource.Builder(
										address(a)).value(b).build()));
					}
				}, new Action() { // [28] Command = RET.a UnsignedNumber.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(procedural.newStatement(
								Statement.RET, new StatementResource.Builder(
										address(a)).value(b).build()));
					}
				}, new Action() { // [29] Command = LIT.a Number.b
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						final Symbol _symbol_b = _symbols[offset + 2];
						final Integer b = (Integer) _symbol_b.value;
						return new Symbol(procedural.newStatement(
								Statement.LIT, new StatementResource.Builder(
										address(a)).value(b).build()));
					}
				}, new Action() { // [30] UnsignedNumber = NUMBER.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol a = _symbols[offset + 1];
						return new Symbol(ParserUtils.safeSymbolToInt(a,
								(ErrorEvents) report));
					}
				}, new Action() { // [31] Location = LOCAL
					public Symbol reduce(Symbol[] _symbols, int offset) {
						return new Symbol("lokal");
					}
				}, new Action() { // [32] Location = GLOBAL
					public Symbol reduce(Symbol[] _symbols, int offset) {
						return new Symbol("global");
					}
				}, new Action() { // [33] Number = UnsignedNumber.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol _symbol_a = _symbols[offset + 1];
						final Integer a = (Integer) _symbol_a.value;
						return new Symbol(a);
					}
				}, new Action() { // [34] Number = MINUS UnsignedNumber.a
					public Symbol reduce(Symbol[] _symbols, int offset) {
						final Symbol _symbol_a = _symbols[offset + 2];
						final Integer a = (Integer) _symbol_a.value;
						return new Symbol(-a);
					}
				} };

		this.report = ErrorEvents.forAm1();
	}

	protected Symbol invokeReduceAction(int rule_num, int offset) {
		return actions[rule_num].reduce(_symbols, offset);
	}
}
