/*	Copyright  (c)	Günter Woigk 2010 - 2020
					mailto:kio@little-bat.de

	This file is free software.

	Permission to use, copy, modify, distribute, and sell this software
	and its documentation for any purpose is hereby granted without fee,
	provided that the above copyright notice appears in all copies and
	that both that copyright notice, this permission notice and the
	following disclaimer appear in supporting documentation.

	THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY,
	NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
	A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE COPYRIGHT HOLDER
	BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE,
	TO THE EXTENT PERMITTED BY APPLICABLE LAW.
*/


#pragma once
#include "kio/kio.h"
#include "Templates/HashMap.h"
#include "NameID.h"
#include "Word.h"
#include "Templates/StrArray.h"
//#include "Compiler.h"
//#include "FileInfo.h"
#include "Tokenizer.h"
#include "types.h"

namespace vpp
{

/**	preprocess source file
	- read file
	- tokenize file
	- preprocess file
	- output:
		names[]			 nameIDs used so far
		errors[]
		source[]		 single char[]		with all #include'd files inserted
		words[]			 tokenized source	with all #include'd files and #define'd macros processed
		included_files[] list of #include'd files	((inserted in source and words))
		required_files[] list of #require'd files	((to be compiled and linked separately))

	@param sourcefile  absolute path of source file
	@param listdir     absolute path of list dir or NULL
*/

class Preprocessor
{
public:
	Names&		names;
	Words		words;
	Array<char>& source;
	FileInfos&	included_files;
	StrArray&	required_files;
	Errors		errors;
	Tokenizer	tokenizer;

	Preprocessor (Names&, Array<char>& source, FileInfos& incl_files, StrArray& req_files);
	void preprocess (cstr filename, cstr listdir) throws;

private:
	HashMap<NameID,Words> macros;
	Array<Words>undefed_macros;

	void add_macro(NameID idf);
	void add_macro(NameID idf, cstr value);
	void add_macro(NameID idf, int value);
	void add_macro(NameID idf, uint value);
	void init_macros();
	uint expand_macro (Words& words, uint wpos0);

	bool test (Words& words, uint& wpos, NameID idf);
	void expect (Words& words, uint& wpos, NameID idf);
	bool test (uint& wpos, NameID idf);
	void expect (uint& wpos, NameID idf);
	void expect_eol (uint wpos);
	Word& get_idf (uint& wpos);

	void skip_value (uint& wpos, int prio);
	Ival text_value (uint& wpos) throws;
	Ival value(uint& widx, int prio=0/*pAny*/);
	Ival numeric_value(uint& widx, int prio=0/*pAny*/);

	uint skip (uint wpos);
	void include (cstr filename, uint wpos, uint wend);
	uint parse (uint wpos0);
	uint skip_block (uint wpos);
	void preprocess_file (cstr sourcefile) throws;

	cstr listfile_errors;
	cstr listfile_macros;
	cstr listfile_words;
	cstr listfile_included_files;
	cstr listfile_required_files;
	void eraselistfiles(cstr sourcefile, cstr listdir);
	void writelistfiles ();
	cstr tostr (cWord&);
	void write_macro(FD&, Words&);
};


extern void preprocess (cstr sourcefile, cstr listdir) throws;


} // namespace






















