#ifndef _NBASIC_H_
#define _NBASIC_H_

#include <stdio.h>
#include "RegEx.h"
#define MAX_REGEXES 100

enum
{
	//recognized nbasic tokens
	NULL_START_TOKEN = 0,
	X, Y, A, ARRAY, ZEROPAGE, ABSOLUTE, //1-6
	GOTO, GOSUB, BRANCHTO, RETURN, RESUME, //7-11
	SET, BRACKETOPEN, BRACKETCLOSE, INC, DEC, //12-16
	PLUS, MINUS, SHIFTLEFT, SHIFTRIGHT, BITAND, //17-21
	BITOR, BITEOR, ISEQUAL, NOTEQUAL, ISLESS, ISGREATER, LESSEQ, GREATEREQ,
	IF, THEN, ENDIF,
	TO, NEXT, FOR,
	ASM, ENDASM, DATA, PUSH, POP,
	ENDPROG,PAST_END_FILE,
	LABEL, NUMBER, VAR, NEWLINE, COMMENT, WHITESPACE, INCBIN,

	//6502 assembly commands
	ASMTEXT,
	ASMLABEL,
	ASMACCEPTABLE,
	//math
	//ADC->   A + M + C -> A
	//ASL->   C <- |7|6|5|4|3|2|1|0| <- 0
	//LSR->   0 -> |7|6|5|4|3|2|1|0| -> C
	//SBC->   A - M - ~C -> A
	ADCi, ADCp, ADCpx, CLC,
	ASLa, ASLp, ASLpx,
	LSRa, LSRp, LSRpx,
	SBCi, SBCp, SBCpx, SEC, //SBC has more modes. check these
	
	//ADC, SBC, CLC, SEC, ASL, LSR,
	//AND, EOR, ORA, /*CLV, ROL, ROR,*/
	ANDi, ANDp, ANDpx,
	ORi,  ORp,  ORpx,
  EORi, EORp, EORpx,
	//conditionals
	BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRA, BVC, BVS,
	CMPi, CMPp, CPXi, CPXp, CPYi, CPYp,
	//dec, inc, lda, sta
	DECp, DECpx, DEX, DEY,
	INCp, INCpx, INX, INY,
	LDAi, LDAp, LDApx, LDApy, //other store modes
	LDXi, LDXp, LDXpy, LDYi, LDYp, LDYpx,
	PHA, PLA,
	STAp, STApx, STApy, //other store modes
	STXp, STXpy, STYp, STYpx,
	TAX, TAY, TXA, TYA, /*TXS, TSX,*/
	//jumps
	JMP, JSR, RTS, RTI,
	
	NULL_END_TOKEN
};


extern void Exit(const char*);

class Token
{
	friend class TokenList;
	public:
		Token(int num_, int type_, int line_, const char* val_, int location_=-1);
		~Token();
		int index, type, line, valuelen, location;
		char* value;
		Token *next, *prev;
};

class TokenList
{
	public:
		TokenList();
		~TokenList();
		int NumTokens() const;
		void AddToken(int type, const char* val, int len, int linenum, int loc=-1);
		bool Match(int start, int type);
		bool Match(int start, int type0, int type1);
		bool Match(int start, int type0, int type1, int type2);
		bool Match(int start, int type0, int type1, int type2, int type3);
		const Token* GetToken(int n);
		Token* GetTokenPointer(int n);
		bool HasToken(const char* value);
		void SetTokenLocation(int i, int loc);
		void RemoveToken(int n);
	private:
		int num_tokens;
		Token *first, *last, *marker;
};

class NBasic
{
	public:
		NBasic();
		~NBasic();
		void SetVerbosity(bool);
		void AddRegEx(const char *exp, int result, bool require_whitespace=true);
		void SetMaxFiles(int n);
		void AddFile(const char* filename);
		void SetWhitespaceRegEx(int n){whitespace_regex=n;}
		void SetNewlineRegEx(int n){newline_regex=n;}
		int NumRegExes() const {return num_regexes;}
		void Compile();
		bool Output(const char*);
		void Output(FILE*);
		bool TokenizeLine(const char*, int linenum); //returns true if successful, else false
	private:
		int numfiles;
		int *filelines;
		const char **filenames;
		int numlines;
		bool verbose;

		int Compile(int token_index);
		void CreateAutoVariables();
		void VarError(const char* name);
		void VarAllocError(const char* name);
		void AddVariable(const char* name, int length=-1, int vartype=0, int loc=-1);
		bool VariableExists(const char* name);
		void OutputVariables(FILE*);
		int next_autolabel;
		
		int TokenType(int);
		const char* TokenValue(int);
		char* MakeNumber(const char*,int line);
		int NumberValue(const char*, int line);
		int ConditionalOpposite(int cond);
		bool IsConditional(int token_index);
		bool IsMath(int token_index);
		int MathLength(int token_index, int line);
		void CompileError(const char*, int);
		void TrimWhitespace(); //remove needless whitespace (except in asm blocks)
		void CompactMath(); //compact number/number math ops
		RegEx regexes[MAX_REGEXES];
		int regex_returns[MAX_REGEXES];
		bool regex_requirewhite[MAX_REGEXES];
		int num_regexes;
		int whitespace_regex, newline_regex;
		TokenList tokens;
		TokenList asmlist;
		TokenList variables;

		//compile functions
		int CompileAsm(int,int,int);
		int CompileConditional(int,int,int);
		int CompileIdentifiers(int,int,int);
		int CompileIncrement(int,int,int);
		int CompileJump(int,int,int);
		int CompileSet(int,int,int);
		int CompileMath(int,int,int);
		int CompileData(int,int,int);
		int CompilePush(int,int,int);
};

#endif


syntax highlighted by Code2HTML, v. 0.9.1