#pragma once
#include <string>
#include <iostream>
#include <fstream> 

using namespace std;

/** CmdType
The 9 different command types available in the VM language 
*/
enum CmdType {C_ARITHMETIC, C_PUSH, C_POP, C_LABEL, C_GOTO, C_IF, C_FUNCTION, C_RETURN, C_CALL};

/** CmdMapEntry
Structure used to facilitate the mapping from VM command mnemonic to command type 
*/
struct CmdMapEntry{
	CmdType type;
	const char* cmd;
};

/** cmdMapSize
The number of different VM command mnemonics
*/
const int cmdMapSize = 17;

/** cmdArray
An arrays that holds all VM command mnemonics and the corresponding cmd type. It is used in 'parse'to identify the type of the command based on the mnemonic.
*/
static const CmdMapEntry cmdArray[cmdMapSize] = {{C_ARITHMETIC, "add"}, {C_ARITHMETIC, "sub"},{C_ARITHMETIC, "neg"},{C_ARITHMETIC, "and"},{C_ARITHMETIC, "not"},{C_ARITHMETIC, "eq"}, {C_ARITHMETIC, "gt"}, {C_ARITHMETIC, "lt"}, {C_ARITHMETIC, "or"},  {C_PUSH, "push"}, {C_POP, "pop"}, {C_LABEL, "label"}, {C_GOTO, "goto"}, {C_IF, "if-goto"}, {C_FUNCTION, "function"}, {C_RETURN, "return"}, {C_CALL, "call"}};
static const char* cmdTypeStringArray[9] = {"C_Arithmetic", "C_Push", "C_Pop", "C_Label", "C_Goto", "C_If", "C_Function", "C_Return", "C_Call"};
/** VMParser
The VM source file parser class.
*/
class VMParser
{
protected:
	int lineNumber; /** the line number of the line currently being parsed */
	string currentLine; /** the string contained in the current line */
	fstream inFile; /** the fstream object used to read data from the input file */
	
	string arg1value; /** The first argument of the parsed command. If the command type is C_ARITHMETIC then it contains the VM command mnemonic. Not all command types have an argument. */
	int arg2value; /** The second argument of the parsed command. Not all command types have 2 arguments */

	void parse(); 
public:
	VMParser(const char* filename);
	~VMParser(void);

	bool hasMoreCommands();
    int advance();
    CmdType commandType();
    
	void dump();

	string arg1() {return arg1value;} /** returns the value of the first argument of the current command */
	int arg2() {return arg2value;} /** returns the value of the second argument of the current command */
};

     

