<commit_before>/*
 Copyright (c) 2012 Sweetdumplings <linmx0130@163.com>
 All rights reserved.
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

#include <QtGui>
#include "pQDoubleListChooser.h"
pQDoubleListChooser::pQDoubleListChooser(QWidget *parent)
	:QWidget(parent)
{
	toLeft=new QPushButton("<-");
	toRight=new QPushButton("->");
	LeftList=new QListWidget;
	RightList=new QListWidget;
	//build the ui
	QHBoxLayout *mainlayout=new QHBoxLayout;
	QVBoxLayout *buttonlayout=new QVBoxLayout;
	buttonlayout->addWidget(toLeft);
	buttonlayout->addWidget(toRight);
	mainlayout->addWidget(LeftList);
	mainlayout->addLayout(buttonlayout);
	mainlayout->addWidget(RightList);
	//connect slots and signals
	connect(toLeft,SIGNAL(clicked()),this,SLOT(toLeftClicked()));
	connect(toRight,SIGNAL(clicked()),this,SLOT(toRightClicked()));
	connect(LeftList,SIGNAL(itemDoubleClicked(QListWidgetItem *)),
			this,SLOT(LeftListDoubleClicked()));
	connect(RightList,SIGNAL(itemDoubleClicked(QListWidgetItem *)),
			this,SLOT(RightListDoubleClicked()));

	setLayout(mainlayout);
}

/*
 * movetoSide functions
 * These functions will help users to move the items.
 * They show the way to use addItem and removeItemWidget
 */

void pQDoubleListChooser::movetoRight(){
	QList<QListWidgetItem *> need_to_move=LeftList->selectedItems();
	QList<QListWidgetItem *>::iterator i=need_to_move.begin();
	for (;i!=need_to_move.end();++i){
		QListWidgetItem *newitem=new QListWidgetItem(*(*i));
		RightList->addItem(newitem);
	}
	for (i=need_to_move.begin();i!=need_to_move.end();++i){
		LeftList->removeItemWidget((*i));
		delete (*i);
		//Important: the delete sentence is necessary.
		//After "delete", the useless memory will be return to the system
		//and the item on UI will disappear.
	}
}
void pQDoubleListChooser::movetoLeft(){
	QList<QListWidgetItem *> need_to_move=RightList->selectedItems();
	QList<QListWidgetItem *>::const_iterator i=need_to_move.begin();
	for (;i!=need_to_move.end();++i){
		QListWidgetItem *newitem=new QListWidgetItem(*(*i));
		LeftList->addItem(newitem);
	}
	for (i=need_to_move.begin();i!=need_to_move.end();++i){
		RightList->removeItemWidget((*i));
		delete (*i);
	}
}

//Slots
void pQDoubleListChooser::toLeftClicked(){
	this->movetoLeft();
}
void pQDoubleListChooser::toRightClicked(){
	this->movetoRight();
}
void pQDoubleListChooser::LeftListDoubleClicked(){
	this->movetoRight();
}
void pQDoubleListChooser::RightListDoubleClicked(){
	this->movetoLeft();
}
<commit_msg>add size policy(Preferred) to DoubleListChooser<commit_after>/*
 Copyright (c) 2012 Sweetdumplings <linmx0130@163.com>
 All rights reserved.
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

#include <QtGui>
#include "pQDoubleListChooser.h"
pQDoubleListChooser::pQDoubleListChooser(QWidget *parent)
	:QWidget(parent)
{
	toLeft=new QPushButton("<-");
	toRight=new QPushButton("->");
	LeftList=new QListWidget;
	RightList=new QListWidget;
	//build the ui
	QHBoxLayout *mainlayout=new QHBoxLayout;
	QVBoxLayout *buttonlayout=new QVBoxLayout;

	QSizePolicy listsizepolicy(QSizePolicy::Preferred
					,QSizePolicy::Preferred);
	listsizepolicy.setHorizontalStretch(3);
	LeftList->setSizePolicy(listsizepolicy);
	RightList->setSizePolicy(listsizepolicy);

	buttonlayout->addWidget(toLeft);
	buttonlayout->addWidget(toRight);
	mainlayout->addWidget(LeftList);
	mainlayout->addLayout(buttonlayout);
	mainlayout->addWidget(RightList);
	//connect slots and signals
	connect(toLeft,SIGNAL(clicked()),this,SLOT(toLeftClicked()));
	connect(toRight,SIGNAL(clicked()),this,SLOT(toRightClicked()));
	connect(LeftList,SIGNAL(itemDoubleClicked(QListWidgetItem *)),
			this,SLOT(LeftListDoubleClicked()));
	connect(RightList,SIGNAL(itemDoubleClicked(QListWidgetItem *)),
			this,SLOT(RightListDoubleClicked()));

	setLayout(mainlayout);
}

/*
 * movetoSide functions
 * These functions will help users to move the items.
 * They show the way to use addItem and removeItemWidget
 */

void pQDoubleListChooser::movetoRight(){
	QList<QListWidgetItem *> need_to_move=LeftList->selectedItems();
	QList<QListWidgetItem *>::iterator i=need_to_move.begin();
	for (;i!=need_to_move.end();++i){
		QListWidgetItem *newitem=new QListWidgetItem(*(*i));
		RightList->addItem(newitem);
	}
	for (i=need_to_move.begin();i!=need_to_move.end();++i){
		LeftList->removeItemWidget((*i));
		delete (*i);
		//Important: the delete sentence is necessary.
		//After "delete", the useless memory will be return to the system
		//and the item on UI will disappear.
	}
}
void pQDoubleListChooser::movetoLeft(){
	QList<QListWidgetItem *> need_to_move=RightList->selectedItems();
	QList<QListWidgetItem *>::const_iterator i=need_to_move.begin();
	for (;i!=need_to_move.end();++i){
		QListWidgetItem *newitem=new QListWidgetItem(*(*i));
		LeftList->addItem(newitem);
	}
	for (i=need_to_move.begin();i!=need_to_move.end();++i){
		RightList->removeItemWidget((*i));
		delete (*i);
	}
}

//Slots
void pQDoubleListChooser::toLeftClicked(){
	this->movetoLeft();
}
void pQDoubleListChooser::toRightClicked(){
	this->movetoRight();
}
void pQDoubleListChooser::LeftListDoubleClicked(){
	this->movetoRight();
}
void pQDoubleListChooser::RightListDoubleClicked(){
	this->movetoLeft();
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Exception.h"
#include "FastSpinlock.h"
#include "DummyClients.h"
#include "PlayerSession.h"
#include "GameSession.h"
#include "IocpManager.h"
#include "GameLiftManager.h"
#include "PacketType.h"
#include "DummyClients.h"
#include "Log.h"

#include <Rpc.h>
#include <aws/core/utils/Outcome.h>
#include <aws/gamelift/model/CreateGameSessionRequest.h>
#include <aws/gamelift/model/CreatePlayerSessionsRequest.h>
#include <aws/gamelift/model/StartGameSessionPlacementRequest.h>
#include <aws/gamelift/model/DescribeGameSessionPlacementRequest.h>
#include <aws/gamelift/model/DescribeGameSessionDetailsRequest.h>

GameSession::~GameSession()
{
	for (auto it : mReadySessionList)
	{
		delete it;
	}
}

bool GameSession::PreparePlayerSessions()
{
	CRASH_ASSERT(LThreadType == THREAD_MAIN);

	for (int i = 0; i < mMaxPlayerCount - TEST_PLAYER_SESSION_EXCEPT; ++i)
	{
		PlayerSession* client = new PlayerSession(this);

		if (false == client->PrepareSession())
			return false;

		mReadySessionList.push_back(client);
	}

	return true;
}

bool GameSession::CreateGameSession()
{
	FastSpinlockGuard guard(mLock);

	Aws::GameLift::Model::CreateGameSessionRequest req;

	auto aliasId = GGameLiftManager->GetAliasId();
	if (aliasId == "TEST_LOCAL")
	{
		req.SetFleetId(std::string("fleet-") + mGameSessionName);
	}
	else
	{
		req.SetAliasId(aliasId);
	}

	req.SetName(mGameSessionName);
	req.SetMaximumPlayerSessionCount(mMaxPlayerCount);
	auto outcome = GGameLiftManager->GetAwsClient()->CreateGameSession(req);
	if (outcome.IsSuccess())
	{
		auto gs = outcome.GetResult().GetGameSession();
		mPort = gs.GetPort();
		mIpAddress = gs.GetIpAddress();
		mGameSessionId = gs.GetGameSessionId();
		return true;
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());

	return false;
}

bool GameSession::CreatePlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	Aws::GameLift::Model::CreatePlayerSessionsRequest req;
	req.SetGameSessionId(mGameSessionId);
	std::vector<std::string> playerIds;

	for (int i = 0; i < mMaxPlayerCount - TEST_PLAYER_SESSION_EXCEPT; ++i) ///< must be less than 25
	{
		std::string pid = "DummyPlayer" + std::to_string(mStartPlayerId + i);
		playerIds.push_back(pid);
	}
	req.SetPlayerIds(playerIds);

	auto outcome = GGameLiftManager->GetAwsClient()->CreatePlayerSessions(req);
	if (outcome.IsSuccess())
	{
		mPlayerSessionList = outcome.GetResult().GetPlayerSessions();
		return true;
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());
	return false;
}

bool GameSession::ConnectPlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	auto it = mReadySessionList.begin();
	int idx = mStartPlayerId;
	for (auto& playerSessionItem : mPlayerSessionList)
	{
		(*it)->AddRef();
		if (false == (*it)->ConnectRequest(playerSessionItem.GetPlayerSessionId(), idx++))
			return false;

		Sleep(10);

		++it;
	}

	return true;
}

void GameSession::DisconnectPlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	for (auto session : mReadySessionList)
	{
		if (session->IsConnected())
			session->DisconnectRequest(DR_ACTIVE);
	}
}

bool GameSession::StartGameSessionPlacement()
{
	FastSpinlockGuard guard(mLock);

	/// region reset for a match queue...
	GGameLiftManager->SetUpAwsClient(GGameLiftManager->GetRegion());

	GeneratePlacementId();

	Aws::GameLift::Model::StartGameSessionPlacementRequest req;
	req.SetGameSessionQueueName(GGameLiftManager->GetMatchQueue());
	req.SetMaximumPlayerSessionCount(MAX_PLAYER_PER_GAME);
	req.SetPlacementId(mPlacementId);

	auto outcome = GGameLiftManager->GetAwsClient()->StartGameSessionPlacement(req);
	if (outcome.IsSuccess())
	{
		auto status = outcome.GetResult().GetGameSessionPlacement().GetStatus();

		if (status == Aws::GameLift::Model::GameSessionPlacementState::PENDING)
		{
			return CheckGameSessionPlacement();
		}

		if (status == Aws::GameLift::Model::GameSessionPlacementState::FULFILLED)
		{
			auto gs = outcome.GetResult().GetGameSessionPlacement();

			mGameSessionId = gs.GetGameSessionArn();
			mIpAddress = gs.GetIpAddress();
			mPort = gs.GetPort();

			/// change region...
			GGameLiftManager->SetUpAwsClient(gs.GetGameSessionRegion());

			return true;
		}
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());

	return false;
}

bool GameSession::CheckGameSessionPlacement()
{
	while (true)
	{
		Aws::GameLift::Model::DescribeGameSessionPlacementRequest req;
		req.SetPlacementId(mPlacementId);
		auto outcome = GGameLiftManager->GetAwsClient()->DescribeGameSessionPlacement(req);
		if (outcome.IsSuccess())
		{
			auto gs = outcome.GetResult().GetGameSessionPlacement();

			if (gs.GetStatus() == Aws::GameLift::Model::GameSessionPlacementState::FULFILLED)
			{
				mGameSessionId = gs.GetGameSessionArn();
				mIpAddress = gs.GetIpAddress();
				mPort = gs.GetPort();

				/// change region...
				auto region = gs.GetGameSessionRegion();
				GGameLiftManager->SetUpAwsClient(region);

				return true;
			}
		}
		else
		{
			break;
		}

		Sleep(500);
	}

	return false;

}

void GameSession::GeneratePlacementId()
{
	UUID uuid;
	UuidCreate(&uuid);

	unsigned char* str = nullptr;
	UuidToStringA(&uuid, &str);

	mPlacementId.clear();
	mPlacementId = std::string((char*)str);

	RpcStringFreeA(&str);
}<commit_msg>*fixed: simplifying to get a game session info<commit_after>#include "stdafx.h"
#include "Exception.h"
#include "FastSpinlock.h"
#include "DummyClients.h"
#include "PlayerSession.h"
#include "GameSession.h"
#include "IocpManager.h"
#include "GameLiftManager.h"
#include "PacketType.h"
#include "DummyClients.h"
#include "Log.h"

#include <Rpc.h>
#include <aws/core/utils/Outcome.h>
#include <aws/gamelift/model/CreateGameSessionRequest.h>
#include <aws/gamelift/model/CreatePlayerSessionsRequest.h>
#include <aws/gamelift/model/StartGameSessionPlacementRequest.h>
#include <aws/gamelift/model/DescribeGameSessionPlacementRequest.h>
#include <aws/gamelift/model/DescribeGameSessionDetailsRequest.h>

GameSession::~GameSession()
{
	for (auto it : mReadySessionList)
	{
		delete it;
	}
}

bool GameSession::PreparePlayerSessions()
{
	CRASH_ASSERT(LThreadType == THREAD_MAIN);

	for (int i = 0; i < mMaxPlayerCount - TEST_PLAYER_SESSION_EXCEPT; ++i)
	{
		PlayerSession* client = new PlayerSession(this);

		if (false == client->PrepareSession())
			return false;

		mReadySessionList.push_back(client);
	}

	return true;
}

bool GameSession::CreateGameSession()
{
	FastSpinlockGuard guard(mLock);

	Aws::GameLift::Model::CreateGameSessionRequest req;

	auto aliasId = GGameLiftManager->GetAliasId();
	if (aliasId == "TEST_LOCAL")
	{
		req.SetFleetId(std::string("fleet-") + mGameSessionName);
	}
	else
	{
		req.SetAliasId(aliasId);
	}

	req.SetName(mGameSessionName);
	req.SetMaximumPlayerSessionCount(mMaxPlayerCount);
	auto outcome = GGameLiftManager->GetAwsClient()->CreateGameSession(req);
	if (outcome.IsSuccess())
	{
		auto gs = outcome.GetResult().GetGameSession();
		mPort = gs.GetPort();
		mIpAddress = gs.GetIpAddress();
		mGameSessionId = gs.GetGameSessionId();
		return true;
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());

	return false;
}

bool GameSession::CreatePlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	Aws::GameLift::Model::CreatePlayerSessionsRequest req;
	req.SetGameSessionId(mGameSessionId);
	std::vector<std::string> playerIds;

	for (int i = 0; i < mMaxPlayerCount - TEST_PLAYER_SESSION_EXCEPT; ++i) ///< must be less than 25
	{
		std::string pid = "DummyPlayer" + std::to_string(mStartPlayerId + i);
		playerIds.push_back(pid);
	}
	req.SetPlayerIds(playerIds);

	auto outcome = GGameLiftManager->GetAwsClient()->CreatePlayerSessions(req);
	if (outcome.IsSuccess())
	{
		mPlayerSessionList = outcome.GetResult().GetPlayerSessions();
		return true;
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());
	return false;
}

bool GameSession::ConnectPlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	auto it = mReadySessionList.begin();
	int idx = mStartPlayerId;
	for (auto& playerSessionItem : mPlayerSessionList)
	{
		(*it)->AddRef();
		if (false == (*it)->ConnectRequest(playerSessionItem.GetPlayerSessionId(), idx++))
			return false;

		Sleep(10);

		++it;
	}

	return true;
}

void GameSession::DisconnectPlayerSessions()
{
	FastSpinlockGuard guard(mLock);

	for (auto session : mReadySessionList)
	{
		if (session->IsConnected())
			session->DisconnectRequest(DR_ACTIVE);
	}
}

bool GameSession::StartGameSessionPlacement()
{
	FastSpinlockGuard guard(mLock);

	/// region reset for a match queue...
	GGameLiftManager->SetUpAwsClient(GGameLiftManager->GetRegion());

	GeneratePlacementId();

	Aws::GameLift::Model::StartGameSessionPlacementRequest req;
	req.SetGameSessionQueueName(GGameLiftManager->GetMatchQueue());
	req.SetMaximumPlayerSessionCount(MAX_PLAYER_PER_GAME);
	req.SetPlacementId(mPlacementId);

	auto outcome = GGameLiftManager->GetAwsClient()->StartGameSessionPlacement(req);
	if (outcome.IsSuccess())
	{
		auto status = outcome.GetResult().GetGameSessionPlacement().GetStatus();

		if (status == Aws::GameLift::Model::GameSessionPlacementState::PENDING)
		{
			return CheckGameSessionPlacement();
		}

		if (status == Aws::GameLift::Model::GameSessionPlacementState::FULFILLED)
		{
			auto gs = outcome.GetResult().GetGameSessionPlacement();

			mGameSessionId = gs.GetGameSessionArn();
			mIpAddress = gs.GetIpAddress();
			mPort = gs.GetPort();

			/// change region...
			GGameLiftManager->SetUpAwsClient(gs.GetGameSessionRegion());

			return true;
		}
	}

	GConsoleLog->PrintOut(true, "%s\n", outcome.GetError().GetMessageA().c_str());

	return false;
}

bool GameSession::CheckGameSessionPlacement()
{
	while (true)
	{
		Aws::GameLift::Model::DescribeGameSessionPlacementRequest req;
		req.SetPlacementId(mPlacementId);
		auto outcome = GGameLiftManager->GetAwsClient()->DescribeGameSessionPlacement(req);
		if (outcome.IsSuccess())
		{
			auto gs = outcome.GetResult().GetGameSessionPlacement();

			if (gs.GetStatus() == Aws::GameLift::Model::GameSessionPlacementState::FULFILLED)
			{
				mGameSessionId = gs.GetGameSessionArn();
				mIpAddress = gs.GetIpAddress();
				mPort = gs.GetPort();

				/// change region...
				GGameLiftManager->SetUpAwsClient(gs.GetGameSessionRegion());

				return true;
			}
		}
		else
		{
			break;
		}

		Sleep(500);
	}

	return false;

}

void GameSession::GeneratePlacementId()
{
	UUID uuid;
	UuidCreate(&uuid);

	unsigned char* str = nullptr;
	UuidToStringA(&uuid, &str);

	mPlacementId.clear();
	mPlacementId = std::string((char*)str);

	RpcStringFreeA(&str);
}<|endoftext|>


<commit_before>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

/* don't be a boring tuna */
#warning you are ugly

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "configuration.h"
#include "script/script.h"
#include "music.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

/* game counter, controls FPS */
void inc_speed_counter(){
    /* probably put input polling here, InputManager::poll() */
    Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

/* if you need to count seconds for some reason.. */
void inc_second_counter() {
    Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigSegV(int i, siginfo_t * sig, void * data){
    const char * message = "Bug! Caught a memory violation. Shutting down..\n";
    int dont_care = write(1, message, 48);
    dont_care = dont_care;
    // Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
    Bitmap::setGfxModeText();
    allegro_exit();
    /* write to a log file or something because sigsegv shouldn't
     * normally happen.
     */
    exit(1);
}
#else
#endif

/* catch a socket being closed prematurely on unix */
#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );

	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigSegV;
	sigaction( SIGSEGV, &action, NULL );

	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

/* should probably call the janitor here or something */
static void close_paintown(){
    Music::pause();
    Bitmap::setGfxModeText();
    allegro_exit();
    exit(0);
}
END_OF_FUNCTION(close_paintown)

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
        out << "Data path is " << Util::getDataPath() << endl;
        out << "Paintown version " << Global::getVersionString() << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

        /* png */
	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        Configuration::loadConfigurations();

        const int sx = Configuration::getScreenWidth();
        const int sy = Configuration::getScreenHeight();

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
        /* 16 bit color depth */
	set_color_depth( 16 );

        /* set up the screen */
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
        /* set up the timers */
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	out << "Initialize random number generator" << endl;
        /* initialize random number generator */
	srand( time( NULL ) );

        /* keep running in the background */
	set_display_switch_mode(SWITCH_BACKGROUND);

        /* close window when the X is pressed */
        LOCK_FUNCTION(close_paintown);
        set_close_button_callback(close_paintown);

        /* music */
	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	out << "Initialize network" << endl;
	Network::init();

        /* this mutex is used to show the loading screen while the game loads */
	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	return true;
}
<commit_msg>print build time<commit_after>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

/* don't be a boring tuna */
#warning you are ugly

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "configuration.h"
#include "script/script.h"
#include "music.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

/* game counter, controls FPS */
void inc_speed_counter(){
    /* probably put input polling here, InputManager::poll() */
    Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

/* if you need to count seconds for some reason.. */
void inc_second_counter() {
    Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigSegV(int i, siginfo_t * sig, void * data){
    const char * message = "Bug! Caught a memory violation. Shutting down..\n";
    int dont_care = write(1, message, 48);
    dont_care = dont_care;
    // Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
    Bitmap::setGfxModeText();
    allegro_exit();
    /* write to a log file or something because sigsegv shouldn't
     * normally happen.
     */
    exit(1);
}
#else
#endif

/* catch a socket being closed prematurely on unix */
#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );

	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigSegV;
	sigaction( SIGSEGV, &action, NULL );

	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

/* should probably call the janitor here or something */
static void close_paintown(){
    Music::pause();
    Bitmap::setGfxModeText();
    allegro_exit();
    exit(0);
}
END_OF_FUNCTION(close_paintown)

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
        out << "Data path is " << Util::getDataPath() << endl;
        out << "Paintown version " << Global::getVersionString() << endl;
        out << "Build date " << __DATE__ << " " << __TIME__ << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

        /* png */
	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        Configuration::loadConfigurations();

        const int sx = Configuration::getScreenWidth();
        const int sy = Configuration::getScreenHeight();

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
        /* 16 bit color depth */
	set_color_depth( 16 );

        /* set up the screen */
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
        /* set up the timers */
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	out << "Initialize random number generator" << endl;
        /* initialize random number generator */
	srand( time( NULL ) );

        /* keep running in the background */
	set_display_switch_mode(SWITCH_BACKGROUND);

        /* close window when the X is pressed */
        LOCK_FUNCTION(close_paintown);
        set_close_button_callback(close_paintown);

        /* music */
	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	out << "Initialize network" << endl;
	Network::init();

        /* this mutex is used to show the loading screen while the game loads */
	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	return true;
}
<|endoftext|>


<commit_before>#include <functional>
#include <initializer_list>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>

#include <iostream>

#include <memory>

namespace parser{

	using namespace std;

 	struct Sign{

        std::string name;
        bool isTerm;

        Sign(std::string n, bool t):
	        name(move(n)),
	        isTerm(move(t))
        {}

		Sign(std::string n):
			name(move(n)),
		    isTerm(true)
	    {}

		Sign():
			name(""),
			isTerm(true)
		{}

		operator std::string() const{
    		return name;
		}

		bool operator==(const Sign& rhs) const{
			return name == rhs.name;
		};

		inline bool operator!=(const Sign& rhs) const{
			return !(*this == rhs);
		}
	};

    class HashSign {
		public:
	    size_t operator()(const Sign& s) const {
	        const int C =  9873967;
	        size_t t = 0;
	        for(int i = 0; i != s.name.size(); ++i) {
	            t = t * C + (char)s.name[i];
	        }
	        return t;
	    }
	};

	struct Item{
        Sign left;
        std::vector<Sign> rights;
        int pos;

        Item(Sign l, vector<Sign> r):
        pos(0),
        left(move(l)),
        rights(move(r))
        {}

        Sign nextSign(){
        	if(isLast())
        		return Sign();
        	return rights.at(pos);
        }

        void next(){
        	pos++;
        }

		bool isLast(){
			return pos == rights.size();
		}

		int posOf(Sign s){
			int i = 0;
			for(auto v : rights){
				if(v == s)
					return i;
				i++;
			}
			return -1;
		}

		friend std::ostream& operator<<(std::ostream &out, const Item &i){
			out << std::string(i.left) <<" => ";

			if(i.pos == 0){
				out<< " . ";
			}
			for(int j=0;j<i.rights.size();j++){
				out << std::string(i.rights.at(j));
				if(i.pos == j+1){
					out<< " . ";
				}else{
					out<<"   ";
				}
			}
			out << "\n";
			return out;
		}
	};

	struct State{
		int id;
		vector<Item> items;
		vector<Item> expands;

		State():
			id(-1)
		{}

		State(int id):
			id(id)
		{}

		void append(vector<Item> newItems){
			this->items.insert(items.end(), move(newItems).begin(), move(newItems).end());
		}

		void expand(vector<Item> newItems){
			this->expands.insert(expands.end(), move(newItems).begin(), move(newItems).end());
		}

		void merge(){
			this->items.insert(items.end(), expands.begin(), expands.end());
		}

		friend std::ostream& operator<<(std::ostream &out, const State &s){
			out <<"- Q"<< std::to_string(s.id) <<" -\n";
			for(auto item : s.items){
				cout <<" "<< item;
			}
			for(auto item : s.expands){
				cout <<"  "<< item;
			}
			out << "\n";
			return out;
		}
	};

	Sign mS(std::string name){
		return Sign(name,false);
	}
	Sign mtS(std::string name){
		return Sign(name);
	}

    auto  E = mS("E");
    auto Eq = mS("Eq");
    auto  T = mS("T");
    auto Tq = mS("Tq");
    auto  F = mS("F");

	auto  S = mS("S");

	auto Eps = mtS("Epsilon");
	auto Fin = mtS("Fin");

	std::vector<Item> grammar;

	std::vector<Item> getItems(Sign s){
		std::vector<Item> res;
		for(auto& i : grammar){
			if(i.left.name == s.name){
				res.push_back(i);
			}
		}
		return res;
	}

    std::vector<Sign> first(Sign sign){
        if(sign.isTerm){
            return {sign};
        }
        std::vector<Sign> res;
		auto items = getItems( sign );
		if(items.size() == 0)
			return res;

        for(auto& i : items){
        	auto ext = first(i.rights[0]);
            if(find(ext.begin(), ext.end(), Eps) != ext.end()){
				ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
               	res.insert(res.end(), ext.begin(), ext.end());
                    if(i.rights.size() >= 2){
                        auto nxt = first(i.rights[1]);
                        res.insert(res.end(), nxt.begin(), nxt.end());
                    }else{
                        res.push_back( Eps);
                    }
            }else{
            	res.insert(res.end(), ext.begin(), ext.end());
			}
		}
        return res;
    }

    std::vector<Sign> first(vector<Sign>& l){
        if(l.size() == 0)
            return {Eps};

        std::vector<Sign> res;

        auto it = l.begin();
        if(*it == Eps) return {Eps};
        if((*it).isTerm) return {*it};

        auto ext = first(*it);
        if(find(ext.begin(), ext.end(), Eps) != ext.end()){
            ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
            res.insert(res.end(), ext.begin(), ext.end());
            if(l.size() >= 2 ){
                it++;
                auto next = first(*it);
                res.insert(res.end(), next.begin(), next.end());
            }else{
				res.push_back(Eps);
			}
        }
        return ext;
    }

    std::vector<Sign> follow(Sign s){
        std::vector<Sign> res;

        if(s == E){
            res.push_back(Fin);
        }

        for(auto rit = grammar.cbegin(); rit != grammar.cend(); ++rit){
            auto ls = (*rit).left;
            if(ls == s) continue;

			auto rs = (*rit).rights;
            for(size_t i = 1; i < rs.size(); i++){
            	if(rs[i] == s){
                	if(i + 1 < rs.size()){
                    	auto ext = first(rs[i+1]);
                        if(find(ext.begin(), ext.end(), Eps) != ext.end()){
               	        	auto left = follow(ls);
                            res.insert(res.end(), left.begin(), left.end());
                        }
                        ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
                       	res.insert(res.end(), ext.begin(), ext.end());
                    }else{
                        auto left = follow(ls);
                        res.insert(res.end(), left.begin(), left.end());
                    }
                }
            }
        }
        return res;
    }

/*

    std::vector<Sign> follow(Sign s){
    	if(s == E)
    		return { Eps };

    	cout << string(s) << endl;
        std::vector<Sign> res;
	    for(auto item : grammar){
        	if(item.posOf(s) == -1)
        		continue;

            if(item.posOf(s) == item.rights.size()-1){
            	if(s != item.left){
	            	auto newFollow = follow(item.left);
	                res.insert(res.end(), newFollow.begin(), newFollow.end());
	            }
            }else{
                res.push_back(item.rights.at(item.posOf(s)+1));
            }
	    }
	    return res;
	}
*/
    unordered_map<Sign, vector<Sign>, HashSign> follows;
	vector<shared_ptr<State>> DFAutomaton;
	unordered_map<string, int> transitions;

	int cnt = 0;
	void generateDFAutomaton(int st){
		/*
		cout<< "generateDFAutomaton("<<st<<") \n";
		for(auto i : (*DFAutomaton[st]).items)
			cout << i;
		cout << "============\n";
		cnt++;
		if(cnt > 100) return;
		*/
		vector<int> newStateNumbers;
		auto state = DFAutomaton.at(st);

		for(auto item : state->items){
			//cout <<" size is "<< state->items.size() << endl;
			Sign first = item.nextSign();
			if(first.name=="")
				continue;

			//cout << string(first) << endl;
			if(!first.isTerm){
				state->expand(getItems(first));
			}

			if(!item.isLast()){
				if(transitions.find(first.name) == transitions.end()){
					DFAutomaton.push_back(make_shared<State>(DFAutomaton.size() - 1));
					transitions[first] = DFAutomaton.size() - 1;
					newStateNumbers.push_back(DFAutomaton.size() - 1);

				//cout<<"** \n"<< item <<" added "<< DFAutomaton.size() - 1 << endl;
				item.next();
				DFAutomaton.at(DFAutomaton.size() - 1)->append({item});

				}
			}
		}
		//cout << "extends\n";
		for(auto item : state->expands){
			Sign first = item.nextSign();
			if(first.name=="")
				continue;
			//cout << string(first) << endl;

			if(!item.isLast()){
				if(transitions.find(first.name) == transitions.end()){
					DFAutomaton.push_back(make_shared<State>(DFAutomaton.size() - 1));
					transitions[first] = DFAutomaton.size() - 1;
					newStateNumbers.push_back(DFAutomaton.size() - 1);
				}
				//cout<<"** \n"<< item <<" added "<< DFAutomaton.size() - 1 << endl;
				item.next();
				DFAutomaton.at(DFAutomaton.size() - 1)->append({item});

			}
		}

		for(auto itr = transitions.begin(); itr != transitions.end(); ++itr) {
        	std::cout << "key = " << itr->first
	        << ", val = " << itr->second << "\n";
    	}

		for(auto s : newStateNumbers){
			//cout<< st <<"'s sub generateDFAutomaton("<<s<<") "<<(*DFAutomaton[s]).items.size()<<"\n";
       		generateDFAutomaton(s);
       	}
	}

	void setup(){

        grammar.push_back(Item( E,
            { T, Eq }
        ));

        grammar.push_back(Item( Eq,
            {mtS("+"), T,  Eq }
        ));
        grammar.push_back(Item( Eq,
            { Eps }
        ));

		grammar.push_back(Item( T,
            { F, Tq}
        ));

		grammar.push_back(Item( Tq,
            { mtS("*"), F, Tq }
        ));
        grammar.push_back(Item( Tq,
            { Eps }
        ));

        grammar.push_back(Item( F,
            { mtS("("), E, mtS(")")}
        ));
        grammar.push_back(Item( F,
            { mtS("i")}
		));

        grammar.push_back(Item( S,
            { E, Fin}
		));

		for(auto I : grammar){
			follows.emplace( I.left, follow(I.left));
		}

		auto Q0 = make_shared<State>(0);
		Q0->append(getItems(S));
		DFAutomaton.push_back(Q0);

		generateDFAutomaton(0);
		cout << "=======\n";
		for(int i=0;i<DFAutomaton.size();i++){
			cout << *DFAutomaton[i] << endl;
		}
    }

	using namespace std;

    void test(Sign S){
        std::cout << "==== First is ==="<<std::string(S)<< " ===\n";
        for(auto& s: first(S)){
            std::cout << std::string(s) << std::endl;
        }
        std::cout<<"===== Follow is ===\n";
        for(auto& r: follow(S)){
            std::cout << std::string(r) << std::endl;
        }
	}

    void parser(){
        setup();

/*
		test(E);

        test(Eq);

        test(T);

        test(Tq);

        test(F);

        std::cout<<"===\n";
		std::vector<Item> items = { Item( mS("S"), { E, Fin}) };
        closure(items);
		std::cout<<"~~~~~~~~~~~~~~~\n";
        for(auto i : items)
			std::cout << i;

        //delete items;

        //create_dfa();
        //for(auto rit = rule_table.begin(); rit != rule_table.end(); ++rit){
        //    if(rit.second)
        //        rit.second.reset();
        //}
*/
    }
}

int main(){
    parser::parser();
    return 0;
}
/*
 * ==== T ===
 * (
 * i
 * ===
 * FIN
 * )
 * +
 * ==== Tq ===
 * *
 * Epsilon
 * ===
 * FIN
 * )
 * +
 * ==== F ===
 * (
 * i
 * ===
 * FIN
 * )
 * +
 * *
 * ===
 */

<commit_msg>[Add] LR parse table<commit_after>#include <functional>
#include <initializer_list>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>

#include <iomanip>

#include <iostream>

#include <memory>

namespace parser{

	using namespace std;

 	struct Sign{

        std::string name;
        bool isTerm;

        Sign(std::string n, bool t):
	        name(move(n)),
	        isTerm(move(t))
        {}

		Sign(std::string n):
			name(move(n)),
		    isTerm(true)
	    {}

		Sign():
			name(""),
			isTerm(true)
		{}

		operator std::string() const{
    		return name;
		}

		bool operator==(const Sign& rhs) const{
			return name == rhs.name;
		};

		inline bool operator!=(const Sign& rhs) const{
			return !(*this == rhs);
		}
	};

    class HashSign {
		public:
	    size_t operator()(const Sign& s) const {
	        const int C =  9873967;
	        size_t t = 0;
	        for(int i = 0; i != s.name.size(); ++i) {
	            t = t * C + (char)s.name[i];
	        }
	        return t;
	    }
	};

	struct Item{
        Sign left;
        std::vector<Sign> rights;
        int pos;

        Item(Sign l, vector<Sign> r):
        pos(0),
        left(move(l)),
        rights(move(r))
        {}

        Sign nextSign(){
        	if(isLast())
        		return Sign();
        	return rights.at(pos);
        }

        void next(){
        	pos++;
        }

		bool isLast(){
			return pos == rights.size();
		}

		int posOf(Sign s){
			int i = 0;
			for(auto v : rights){
				if(v == s)
					return i;
				i++;
			}
			return -1;
		}

		friend std::ostream& operator<<(std::ostream &out, const Item &i){
			out << std::string(i.left) <<" => ";

			if(i.pos == 0){
				out<< " . ";
			}
			for(int j=0;j<i.rights.size();j++){
				out << std::string(i.rights.at(j));
				if(i.pos == j+1){
					out<< " . ";
				}else{
					out<<"   ";
				}
			}
			out << "\n";
			return out;
		}
	};

	struct State{
		int id;
		vector<Item> items;
		vector<Item> expands;

		State():
			id(-1)
		{}

		State(int id):
			id(id)
		{}

		void append(vector<Item> newItems){
			this->items.insert(items.end(), move(newItems).begin(), move(newItems).end());
		}

		void expand(vector<Item> newItems){
			this->expands.insert(expands.end(), move(newItems).begin(), move(newItems).end());
		}

		void merge(){
			this->items.insert(items.end(), expands.begin(), expands.end());
		}

		friend std::ostream& operator<<(std::ostream &out, const State &s){
			out <<"- Q"<< std::to_string(s.id) <<" -\n";
			for(auto item : s.items){
				cout <<" "<< item;
			}
			for(auto item : s.expands){
				cout <<"  "<< item;
			}
			out << "\n";
			return out;
		}
	};

	struct Action{
		int id;
		enum A{
			SHIFT,
			GOTO,
			REDUCE,
			ACCEPT
		} action;

		Action(int id,A action):
			id(move(id)),
			action(move(action))
		{}
	};

	Sign mS(std::string name){
		return Sign(name,false);
	}
	Sign mtS(std::string name){
		return Sign(name);
	}

    auto  E = mS("E");
    auto Eq = mS("Eq");
    auto  T = mS("T");
    auto Tq = mS("Tq");
    auto  F = mS("F");

	auto  S = mS("S");

	auto Eps = mtS("Epsilon");
	auto Fin = mtS("Fin");

	std::vector<Item> grammar;

	std::vector<Item> getItems(Sign s){
		std::vector<Item> res;
		for(auto& i : grammar){
			if(i.left.name == s.name){
				res.push_back(i);
			}
		}
		return res;
	}

    std::vector<Sign> first(Sign sign){
        if(sign.isTerm){
            return {sign};
        }
        std::vector<Sign> res;
		auto items = getItems( sign );
		if(items.size() == 0)
			return res;

        for(auto& i : items){
        	auto ext = first(i.rights[0]);
            if(find(ext.begin(), ext.end(), Eps) != ext.end()){
				ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
               	res.insert(res.end(), ext.begin(), ext.end());
                    if(i.rights.size() >= 2){
                        auto nxt = first(i.rights[1]);
                        res.insert(res.end(), nxt.begin(), nxt.end());
                    }else{
                        res.push_back( Eps);
                    }
            }else{
            	res.insert(res.end(), ext.begin(), ext.end());
			}
		}
        return res;
    }

    std::vector<Sign> first(vector<Sign>& l){
        if(l.size() == 0)
            return {Eps};

        std::vector<Sign> res;

        auto it = l.begin();
        if(*it == Eps) return {Eps};
        if((*it).isTerm) return {*it};

        auto ext = first(*it);
        if(find(ext.begin(), ext.end(), Eps) != ext.end()){
            ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
            res.insert(res.end(), ext.begin(), ext.end());
            if(l.size() >= 2 ){
                it++;
                auto next = first(*it);
                res.insert(res.end(), next.begin(), next.end());
            }else{
				res.push_back(Eps);
			}
        }
        return ext;
    }

    std::vector<Sign> follow(Sign s){
        std::vector<Sign> res;

        if(s == E){
            res.push_back(Fin);
        }

        for(auto rit = grammar.cbegin(); rit != grammar.cend(); ++rit){
            auto ls = (*rit).left;
            if(ls == s) continue;

			auto rs = (*rit).rights;
            for(size_t i = 1; i < rs.size(); i++){
            	if(rs[i] == s){
                	if(i + 1 < rs.size()){
                    	auto ext = first(rs[i+1]);
                        if(find(ext.begin(), ext.end(), Eps) != ext.end()){
               	        	auto left = follow(ls);
                            res.insert(res.end(), left.begin(), left.end());
                        }
                        ext.erase(remove(ext.begin(), ext.end(), Eps), ext.end());
                       	res.insert(res.end(), ext.begin(), ext.end());
                    }else{
                        auto left = follow(ls);
                        res.insert(res.end(), left.begin(), left.end());
                    }
                }
            }
        }
        return res;
    }

/*

    std::vector<Sign> follow(Sign s){
    	if(s == E)
    		return { Eps };

    	cout << string(s) << endl;
        std::vector<Sign> res;
	    for(auto item : grammar){
        	if(item.posOf(s) == -1)
        		continue;

            if(item.posOf(s) == item.rights.size()-1){
            	if(s != item.left){
	            	auto newFollow = follow(item.left);
	                res.insert(res.end(), newFollow.begin(), newFollow.end());
	            }
            }else{
                res.push_back(item.rights.at(item.posOf(s)+1));
            }
	    }
	    return res;
	}
*/
    unordered_map<Sign, vector<Sign>, HashSign> follows;
	vector<shared_ptr<State>> DFAutomaton;
	unordered_multimap<Sign, pair<int,int>, HashSign> transitions;

	int cnt = 0;
	void generateDFAutomaton(int st){
		/*
		cout<< "generateDFAutomaton("<<st<<") \n";
		for(auto i : (*DFAutomaton[st]).items)
			cout << i;
		cout << "============\n";
		cnt++;
		if(cnt > 100) return;
		*/
		vector<int> newStateNumbers;
		auto state = DFAutomaton.at(st);

		for(auto item : state->items){
			//cout <<" size is "<< state->items.size() << endl;
			Sign first = item.nextSign();
			if(first.name=="")
				continue;

			//cout << string(first) << endl;
			if(!first.isTerm){
				state->expand(getItems(first));
			}

			if(!item.isLast()){
				if(transitions.find(first.name) == transitions.end()){
					DFAutomaton.push_back(make_shared<State>(DFAutomaton.size()));
					transitions.emplace(first, make_pair( DFAutomaton.size()-1, st));
					newStateNumbers.push_back(DFAutomaton.size() - 1);

				//cout<<"** \n"<< item <<" added "<< DFAutomaton.size() - 1 << endl;
				item.next();
				DFAutomaton.at(DFAutomaton.size() - 1)->append({item});

				}
			}
		}
		//cout << "extends\n";
		for(auto item : state->expands){
			Sign first = item.nextSign();
			if(first.name=="")
				continue;
			//cout << string(first) << endl;

			if(!item.isLast()){
				if(transitions.find(first.name) == transitions.end()){
					DFAutomaton.push_back(make_shared<State>(DFAutomaton.size()));
					transitions.emplace(first, make_pair( DFAutomaton.size()-1, st));
					newStateNumbers.push_back(DFAutomaton.size() - 1);
				}
				//cout<<"** \n"<< item <<" added "<< DFAutomaton.size() - 1 << endl;
				item.next();
				DFAutomaton.at(DFAutomaton.size() - 1)->append({item});

			}
		}

		for(auto s : newStateNumbers){
			//cout<< st <<"'s sub generateDFAutomaton("<<s<<") "<<(*DFAutomaton[s]).items.size()<<"\n";
       		generateDFAutomaton(s);
       	}
	}

	void setup(){

        grammar.push_back(Item( E,
            { T, Eq }
        ));

        grammar.push_back(Item( Eq,
            {mtS("+"), T,  Eq }
        ));
        grammar.push_back(Item( Eq,
            { Eps }
        ));

		grammar.push_back(Item( T,
            { F, Tq}
        ));

		grammar.push_back(Item( Tq,
            { mtS("*"), F, Tq }
        ));
        grammar.push_back(Item( Tq,
            { Eps }
        ));

        grammar.push_back(Item( F,
            { mtS("("), E, mtS(")")}
        ));
        grammar.push_back(Item( F,
            { mtS("i")}
		));

        grammar.push_back(Item( S,
            { E, Fin}
		));

		for(auto I : grammar){
			follows.emplace( I.left, follow(I.left));
		}

		auto Q0 = make_shared<State>(0);
		Q0->append(getItems(S));
		DFAutomaton.push_back(Q0);

		generateDFAutomaton(0);
		cout << "=======\n";
		for(int i=0;i<DFAutomaton.size();i++){
			cout << *DFAutomaton[i] << endl;
		}

		for(auto itr = transitions.begin(); itr != transitions.end(); ++itr) {
        	std::cout << "key = " << itr->first.name
	        << ": from:"<< itr->second.second<< " to:" << itr->second.first << "\n";
    	}

    	vector<unordered_map<Sign, shared_ptr<Action>, HashSign>> parserTable(DFAutomaton.size());

		for(auto it = transitions.begin(); it != transitions.end(); ++it){
			if(it->first.isTerm){
				parserTable.at(it->second.second).emplace( it->first, make_shared<Action>(it->second.first, Action::SHIFT));
				cout <<"shift("<< it->second.second <<","<< it->second.first <<")\n";
			}else{
				parserTable.at(it->second.second).emplace( it->first, make_shared<Action>(it->second.first, Action::GOTO));
				cout <<"goto("<< it->second.second <<","<< it->second.first <<")\n";
			}
		}

		vector<Sign> signs{mtS("i"), mtS("*"), mtS("+"), mtS("("), mtS(")"), E, Eq, T, Tq, F};
		cout<<"  |";
		for(auto s : signs){
			cout <<setw(2)<< string(s) <<"|  ";
		}
		cout << endl;
		for(int i=0;i< parserTable.size();i++){
			cout <<setw(2)<< i << "|";
			for(auto s : signs){
				if(parserTable.at(i).find(s) != parserTable.at(i).end()){
					auto ac = parserTable.at(i).find(s)->second;
					if(ac->action == Action::SHIFT){
						cout << "s"<<setw(2)<< ac->id <<"|";
					}else{
						cout << "g"<<setw(2)<< ac->id <<"|";
					}
				}else{
					cout << "   |";
				}
			}
			cout << endl;
		}
//    	parserTableparserTable.
    }

	using namespace std;

    void test(Sign S){
        std::cout << "==== First is ==="<<std::string(S)<< " ===\n";
        for(auto& s: first(S)){
            std::cout << std::string(s) << std::endl;
        }
        std::cout<<"===== Follow is ===\n";
        for(auto& r: follow(S)){
            std::cout << std::string(r) << std::endl;
        }
	}

    void parser(){
        setup();

/*
		test(E);

        test(Eq);

        test(T);

        test(Tq);

        test(F);

        std::cout<<"===\n";
		std::vector<Item> items = { Item( mS("S"), { E, Fin}) };
        closure(items);
		std::cout<<"~~~~~~~~~~~~~~~\n";
        for(auto i : items)
			std::cout << i;

        //delete items;

        //create_dfa();
        //for(auto rit = rule_table.begin(); rit != rule_table.end(); ++rit){
        //    if(rit.second)
        //        rit.second.reset();
        //}
*/
    }
}

int main(){
    parser::parser();
    return 0;
}
/*
 * ==== T ===
 * (
 * i
 * ===
 * FIN
 * )
 * +
 * ==== Tq ===
 * *
 * Epsilon
 * ===
 * FIN
 * )
 * +
 * ==== F ===
 * (
 * i
 * ===
 * FIN
 * )
 * +
 * *
 * ===
 */

<|endoftext|>


<commit_before>#include "parser.hpp"

#include <iostream>
#include <sstream>

#include <tuple>
#include <map>

#include "error.hpp"

std::tuple<int64_t, bool> get_int(std::stringstream &ss, const std::string &sn, const int &ln) {
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid integer literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

std::tuple<int64_t, bool> get_reg(std::stringstream &ss, const std::string &sn, const int &ln) {
	// @TODO Check if integer value is actually valid
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid register literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

bool check_empty(std::stringstream &ss, const std::string &sn, const int &ln)
{
	std::string token;
	if (ss >> token) {
		std::cerr << Error() << "Expected newline but found '" << token << "' in " <<
			sn << '.' << ln << std::endl;
		return true;
	}
	return false;
}

Code parse(std::ifstream& src, std::string& src_name)
{
	// Rely that src is opened and at the proper point

	Code code;
	int line_num = 0;
	std::string line;

	std::map<std::string, int64_t> label_dict;
	std::map<int64_t, std::string> label_refs;

	while (std::getline(src, line)) {
		line_num++;

		if (line.empty())
			continue;

		std::stringstream line_stream(line);

		std::string token;
		line_stream >> token;

		// Check if line is a comment
		if (token[0] == ';')
			continue;

		// Check if line is a label
		if (token[0] == '@') {
			// @TODO Check if label is already defined and don't allow
			// substitutions.
			label_dict[token] = code.curr_index;
			continue;
		}

		if (token == "halt") {
			code.push_op(op::halt);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "noop") {
			code.push_op(op::noop);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "add") {
			code.push_op(op::add);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "cil") {
			code.push_op(op::cil);

			auto tmp1 = get_int(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "ofv") {
			code.push_op(op::ofv);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "onl") {
			code.push_op(op::onl);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jmp") {
			code.push_op(op::jmp);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jgt") {
			code.push_op(op::jgt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jeq") {
			code.push_op(op::jeq);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jlt") {
			code.push_op(op::jlt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else {
			std::cerr << Error() << "Unkown instruction '" << token << "' in " <<
				src_name << '.' << line_num << std::endl;
			return Code();
		}
	}

	// Push a halt at the end
	code.push_op(op::halt);

	for (auto &ref : label_refs) {
		const auto index_to_change = ref.first;
		const auto referenced_label = ref.second;
		const auto find_result = label_dict.find(referenced_label);
		if (find_result == label_dict.end()) {
			// @TODO Add information about where this label was used
			std::cerr << Error() << "Unknown label " << referenced_label << std::endl;
			return Code();
		}
		const auto referenced_index = find_result->second;
		code.change(index_to_change, var(referenced_index));
	}

	return code;
}
<commit_msg>Allow comment after instructions<commit_after>#include "parser.hpp"

#include <iostream>
#include <sstream>

#include <tuple>
#include <map>

#include "error.hpp"

std::tuple<int64_t, bool> get_int(std::stringstream &ss, const std::string &sn, const int &ln) {
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid integer literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

std::tuple<int64_t, bool> get_reg(std::stringstream &ss, const std::string &sn, const int &ln) {
	// @TODO Check if integer value is actually valid
	int64_t integer_token;
	ss >> integer_token;
	if (ss.fail()) {
		std::cerr << Error() << "Invalid register literal in " << sn << '.' << ln << std::endl;
		return std::make_tuple(0, true);
	}
	return std::make_tuple(integer_token, false);
}

bool check_empty(std::stringstream &ss, const std::string &sn, const int &ln)
{
	std::string token;
	if (ss >> token) {
		// Allow comments
		if (token[0] == ';')
			return false;

		std::cerr << Error() << "Expected newline but found '" << token << "' in " <<
			sn << '.' << ln << std::endl;
		return true;
	}
	return false;
}

Code parse(std::ifstream& src, std::string& src_name)
{
	// Rely that src is opened and at the proper point

	Code code;
	int line_num = 0;
	std::string line;

	std::map<std::string, int64_t> label_dict;
	std::map<int64_t, std::string> label_refs;

	while (std::getline(src, line)) {
		line_num++;

		if (line.empty())
			continue;

		std::stringstream line_stream(line);

		std::string token;
		line_stream >> token;

		// Check if line is a comment
		if (token[0] == ';')
			continue;

		// Check if line is a label
		if (token[0] == '@') {
			// @TODO Check if label is already defined and don't allow
			// substitutions.
			label_dict[token] = code.curr_index;
			continue;
		}

		if (token == "halt") {
			code.push_op(op::halt);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "noop") {
			code.push_op(op::noop);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "add") {
			code.push_op(op::add);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "cil") {
			code.push_op(op::cil);

			auto tmp1 = get_int(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			auto tmp2 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp2))
				return Code();
			code.push_int(std::get<0>(tmp2));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "ofv") {
			code.push_op(op::ofv);

			auto tmp1 = get_reg(line_stream, src_name, line_num);
			if (std::get<1>(tmp1))
				return Code();
			code.push_int(std::get<0>(tmp1));

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "onl") {
			code.push_op(op::onl);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jmp") {
			code.push_op(op::jmp);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jgt") {
			code.push_op(op::jgt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jeq") {
			code.push_op(op::jeq);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else if (token == "jlt") {
			code.push_op(op::jlt);

			line_stream >> token;
			label_refs[code.curr_index] = token;

			code.push_int(-1);

			if (check_empty(line_stream, src_name, line_num))
				return Code();

		} else {
			std::cerr << Error() << "Unkown instruction '" << token << "' in " <<
				src_name << '.' << line_num << std::endl;
			return Code();
		}
	}

	// Push a halt at the end
	code.push_op(op::halt);

	for (auto &ref : label_refs) {
		const auto index_to_change = ref.first;
		const auto referenced_label = ref.second;
		const auto find_result = label_dict.find(referenced_label);
		if (find_result == label_dict.end()) {
			// @TODO Add information about where this label was used
			std::cerr << Error() << "Unknown label " << referenced_label << std::endl;
			return Code();
		}
		const auto referenced_index = find_result->second;
		code.change(index_to_change, var(referenced_index));
	}

	return code;
}
<|endoftext|>


<commit_before>#ifndef ATL_PARSER_HPP
#define ATL_PARSER_HPP
/**
 * @file /home/ryan/programming/atl/parser.hpp
 * @author Ryan Domigan <ryan_domigan@sutdents@uml.edu>
 * Created on Jun 29, 2013
 */

#include <iterator>
#include <sstream>

#include <string>
#include <vector>
#include <iostream>
#include <functional>

#include <iterator>

#include "./exception.hpp"
#include "./type.hpp"
#include "./conversion.hpp"
#include "./type_testing.hpp"
#include "./helpers.hpp"
#include "./print.hpp"

namespace atl
{
	// A simple minded parser, this just transforms a string into an
	// Ast.  There are a couple of reserved symbols:
	//
	//   '(' ')'         : Open and close an Ast branch
	//
	//   DELIM '\'' : 'n expands to (quote n) (should probably be a
	//                 macro).  Can still be used as part of a
	//                 variable name (ie x and x' are both valid
	//                 symbols).
	//
	//   '\"' : starts and ends a string literal
	//
	//   DELIM 0..9 DELIM: a number (a number must be all digits ie
	//                     124567, possibly with a decimal point.  If
	//                     there is a non-digit ie 12345a, it is a
	//                     symbol.  hex/octal/binary representations
	//                     are not a thing ATM).
	//  ';' : comments out to the end of line
	class ParseString
	{
	private:
		template<class Itr>
		void skip_ws_and_comments(Itr &itr, Itr const& end)
		{
			for(; itr != end; ++itr)
				{
					if(*itr == ';')
						for(; (itr != end) && (*itr != '\n'); ++itr);
					else if(!std::isspace(*itr))
						return;

					if(*itr == '\n')
						++_line;
				}
		}

		GC &_gc;
		unsigned long _line;

		static const string delim;	/* symbol deliminator */
		static const string _ws; 	/* white space */
		string scratch;

		inline bool digit(char c) { return ((c >= '0') && (c <= '9')); }
		bool string_is_number(const string& str) {
			return (digit(str[0]) || ((str[0] == '-') && (str.length() > 1) && digit(str[1])));
		}

		template<class Itr>
		void parse(AstSubstrate &vec, Itr &&itr, Itr &&end) {
			for(; itr != end; ++itr) {
				switch(*itr)
					{
					case '\n':
						++_line;
					case ' ':		/* whitespace */
					case '\t':
						continue;

					case ';': 		/* comment */
						for(; itr != end && *itr != '\n'; ++itr);
						if(*itr == '\n') ++_line;
						continue;

					case '\'':
						{		/* quote */
							auto quote = push_nested_ast(vec);
							vec.push_back(wrap<Quote>());

							++itr;
							parse(vec, itr, end);
							quote.end_ast();
							return;
						}

					case '(':
						{		/* sub expression */
							++itr;
							if(*itr == ')') {
								push_nested_ast(vec);
								return;
							}

							auto ast = push_nested_ast(vec);
							while(*itr != ')')
								{
									if(itr == end)
										throw UnbalancedParens
											(to_string(_line)
											 .append(": error: unbalanced parens"));
									parse(vec, itr, end);
								}

							++itr;
							ast.end_ast();
							return;
						}

					case ')': return;

					case '"':
						{		/* string */
							std::string *str = reinterpret_cast<std::string*>(_gc.make<String>());

							for(++itr; *itr != '"'; ++itr)
								{
									if(itr == end) throw to_string(_line)
										               .append("string not terminated.");
									if(*itr == '\n') ++_line;

									str->push_back(*itr);
								}

							++itr;
							vec.emplace_back(tag<String>::value, str);
							return;
						}

					default:
						{
							scratch.clear();

							for(; (itr != end) && (delim.find(*itr) == string::npos); ++itr)
								scratch.push_back(*itr);

							if((itr != end) && (*itr == '\n')) ++_line;

							if(string_is_number(scratch))
								{
									vec.push_back(wrap(atoi(scratch.c_str())));
								}
							else
								{
									vec.push_back(_gc.amake<Symbol>(scratch));
								}

							return;
						}
					}
			}
			return;
		}

	public:
		ParseString(GC &gc) : _gc(gc) {
			_line = 1;
			//_gc.mark_callback( [this](GC &gc) { _gc.mark(_mark); });
		}

		/* parse one S-expression from a string into an ast */
		PassByValue string_(const std::string& input)
		{
			auto& vec = _gc.sequence();

			auto itr = input.begin(),
				end = input.end();
			parse(vec, itr, end);

			// Check that there was just one expression in our string
			while(itr != input.end() && std::isspace(*itr)) ++itr;
			if(itr != input.end())
				throw MultiExpressionString(std::string("More than one expression in `")
				                            .append(input)
				                            .append("`"));

			return PassByValue(*vec.begin());
		}

		/* parse one S-expression from a stream into an ast */
		PassByValue stream(istream &stream)
		s{
			auto initial_flags = stream.flags();
			noskipws(stream);

			auto& vec = _gc.sequence();

			auto itr = istreambuf_iterator<char>(stream),
				end = istreambuf_iterator<char>();
			parse(vec, itr, end);

			// Swallow any following whitepace or comments so the caller
			// of the parser doesn't have to check.
			skip_ws_and_comments(itr, end);

			stream.flags(initial_flags);
			return PassByValue(*vec.begin());
		}

		void reset_line_number() { _line = 1; }
	};
	const std::string ParseString::_ws = " \n\t";
	const std::string ParseString::delim = "()\" \n\t";
}
#endif
<commit_msg>Fix typo in parser<commit_after>#ifndef ATL_PARSER_HPP
#define ATL_PARSER_HPP
/**
 * @file /home/ryan/programming/atl/parser.hpp
 * @author Ryan Domigan <ryan_domigan@sutdents@uml.edu>
 * Created on Jun 29, 2013
 */

#include <iterator>
#include <sstream>

#include <string>
#include <vector>
#include <iostream>
#include <functional>

#include <iterator>

#include "./exception.hpp"
#include "./type.hpp"
#include "./conversion.hpp"
#include "./type_testing.hpp"
#include "./helpers.hpp"
#include "./print.hpp"

namespace atl
{
	// A simple minded parser, this just transforms a string into an
	// Ast.  There are a couple of reserved symbols:
	//
	//   '(' ')'         : Open and close an Ast branch
	//
	//   DELIM '\'' : 'n expands to (quote n) (should probably be a
	//                 macro).  Can still be used as part of a
	//                 variable name (ie x and x' are both valid
	//                 symbols).
	//
	//   '\"' : starts and ends a string literal
	//
	//   DELIM 0..9 DELIM: a number (a number must be all digits ie
	//                     124567, possibly with a decimal point.  If
	//                     there is a non-digit ie 12345a, it is a
	//                     symbol.  hex/octal/binary representations
	//                     are not a thing ATM).
	//  ';' : comments out to the end of line
	class ParseString
	{
	private:
		template<class Itr>
		void skip_ws_and_comments(Itr &itr, Itr const& end)
		{
			for(; itr != end; ++itr)
				{
					if(*itr == ';')
						for(; (itr != end) && (*itr != '\n'); ++itr);
					else if(!std::isspace(*itr))
						return;

					if(*itr == '\n')
						++_line;
				}
		}

		GC &_gc;
		unsigned long _line;

		static const string delim;	/* symbol deliminator */
		static const string _ws; 	/* white space */
		string scratch;

		inline bool digit(char c) { return ((c >= '0') && (c <= '9')); }
		bool string_is_number(const string& str) {
			return (digit(str[0]) || ((str[0] == '-') && (str.length() > 1) && digit(str[1])));
		}

		template<class Itr>
		void parse(AstSubstrate &vec, Itr &&itr, Itr &&end) {
			for(; itr != end; ++itr) {
				switch(*itr)
					{
					case '\n':
						++_line;
					case ' ':		/* whitespace */
					case '\t':
						continue;

					case ';': 		/* comment */
						for(; itr != end && *itr != '\n'; ++itr);
						if(*itr == '\n') ++_line;
						continue;

					case '\'':
						{		/* quote */
							auto quote = push_nested_ast(vec);
							vec.push_back(wrap<Quote>());

							++itr;
							parse(vec, itr, end);
							quote.end_ast();
							return;
						}

					case '(':
						{		/* sub expression */
							++itr;
							if(*itr == ')') {
								push_nested_ast(vec);
								return;
							}

							auto ast = push_nested_ast(vec);
							while(*itr != ')')
								{
									if(itr == end)
										throw UnbalancedParens
											(to_string(_line)
											 .append(": error: unbalanced parens"));
									parse(vec, itr, end);
								}

							++itr;
							ast.end_ast();
							return;
						}

					case ')': return;

					case '"':
						{		/* string */
							std::string *str = reinterpret_cast<std::string*>(_gc.make<String>());

							for(++itr; *itr != '"'; ++itr)
								{
									if(itr == end) throw to_string(_line)
										               .append("string not terminated.");
									if(*itr == '\n') ++_line;

									str->push_back(*itr);
								}

							++itr;
							vec.emplace_back(tag<String>::value, str);
							return;
						}

					default:
						{
							scratch.clear();

							for(; (itr != end) && (delim.find(*itr) == string::npos); ++itr)
								scratch.push_back(*itr);

							if((itr != end) && (*itr == '\n')) ++_line;

							if(string_is_number(scratch))
								{
									vec.push_back(wrap(atoi(scratch.c_str())));
								}
							else
								{
									vec.push_back(_gc.amake<Symbol>(scratch));
								}

							return;
						}
					}
			}
			return;
		}

	public:
		ParseString(GC &gc) : _gc(gc) {
			_line = 1;
			//_gc.mark_callback( [this](GC &gc) { _gc.mark(_mark); });
		}

		/* parse one S-expression from a string into an ast */
		PassByValue string_(const std::string& input)
		{
			auto& vec = _gc.sequence();

			auto itr = input.begin(),
				end = input.end();
			parse(vec, itr, end);

			// Check that there was just one expression in our string
			while(itr != input.end() && std::isspace(*itr)) ++itr;
			if(itr != input.end())
				throw MultiExpressionString(std::string("More than one expression in `")
				                            .append(input)
				                            .append("`"));

			return PassByValue(*vec.begin());
		}

		/* parse one S-expression from a stream into an ast */
		PassByValue stream(istream &stream)
		{
			auto initial_flags = stream.flags();
			noskipws(stream);

			auto& vec = _gc.sequence();

			auto itr = istreambuf_iterator<char>(stream),
				end = istreambuf_iterator<char>();
			parse(vec, itr, end);

			// Swallow any following whitepace or comments so the caller
			// of the parser doesn't have to check.
			skip_ws_and_comments(itr, end);

			stream.flags(initial_flags);
			return PassByValue(*vec.begin());
		}

		void reset_line_number() { _line = 1; }
	};
	const std::string ParseString::_ws = " \n\t";
	const std::string ParseString::delim = "()\" \n\t";
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/timer.hpp>
#include <stdio.h>

int main( int argc, char **argv )
{
    boost::timer t;
    std::cout << "max timespan: "
              << t.elapsed_max() / 3600 << "h" << std::endl;
    std::cout << "min timespan: "
              << t.elapsed_min() << "s" << std::endl;
    std::cout << "now times elapsed: "
              << t.elapsed() << "s" << std::endl;

    getchar();
    return 0;
}
<commit_msg>a more meaningful example for boost.<commit_after>#include <cstdio>
#include <boost/date_time/posix_time/posix_time.hpp>

int main( void  )
{
    namespace pt = boost::posix_time;
    pt::ptime now = pt::second_clock::local_time();

    printf( "%s\t->\t%04d-%02d-%02d %02d:%02d:%02d\n"
          , "date '+%Y-%m-%d %H:%M:%S'"
          , now.date().year()
          , now.date().month()
          , now.date().day()
          , now.time_of_day().hours()
          , now.time_of_day().minutes()
          , now.time_of_day().seconds() );

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of TeapotNet.                                     *
 *                                                                       *
 *   TeapotNet is free software: you can redistribute it and/or modify   *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   TeapotNet 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 Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with TeapotNet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "tpn/mutex.h"
#include "tpn/exception.h"

namespace tpn
{

Mutex::Mutex(void) :
	mLockCount(0),
	mRelockCount(0)
{

	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
	//pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);

	 if(pthread_mutex_init(&mMutex, &attr) != 0)
		 throw Exception("Unable to create mutex");
}

Mutex::~Mutex(void)
{
	pthread_mutex_destroy(&mMutex);
}

void Mutex::lock(int count)
{
	if(count <= 0) return;

	int ret = pthread_mutex_lock(&mMutex);
	if(ret != 0 && ret != EDEADLK)
		throw Exception("Unable to lock mutex");

	if(ret == 0) Assert(mLockCount == 0);
	mLockedBy = pthread_self();
	mLockCount+= count;
}

bool Mutex::tryLock(void)
{
	int ret = pthread_mutex_trylock(&mMutex);
        if(ret == EBUSY) return false;

        if(ret != 0 && ret != EDEADLK)
                throw Exception("Unable to lock mutex");

	if(ret == 0) Assert(mLockCount == 0);
	mLockedBy = pthread_self();
        mLockCount++;
	return true;
}

void Mutex::unlock(void)
{
	if(!mLockCount)
		throw Exception("Mutex is not locked");

	if(!pthread_equal(mLockedBy, pthread_self()))
		throw Exception("Mutex is locked by another thread");

	mLockCount--;
	if(mLockCount == 0)
	{
		int ret = pthread_mutex_unlock(&mMutex);
		if(ret != 0) throw Exception("Unable to unlock mutex");
	}
}

int Mutex::unlockAll(void)
{
	if(!mLockCount)
		throw Exception("Mutex is not locked");

	if(!pthread_equal(mLockedBy, pthread_self()))
		throw Exception("Mutex is locked by another thread");

 	mRelockCount = mLockCount;
	mLockCount = 0;

	int ret = pthread_mutex_unlock(&mMutex);
	if(ret != 0) throw Exception("Unable to unlock mutex");

	return mRelockCount;
}

void Mutex::relockAll(void)
{
	lock(mRelockCount);
	mRelockCount = 0;
}

int Mutex::lockCount(void) const
{
	return mLockCount;
}

}
<commit_msg>Fixed random issues with mutexes<commit_after>/*************************************************************************
 *   Copyright (C) 2011-2012 by Paul-Louis Ageneau                       *
 *   paul-louis (at) ageneau (dot) org                                   *
 *                                                                       *
 *   This file is part of TeapotNet.                                     *
 *                                                                       *
 *   TeapotNet is free software: you can redistribute it and/or modify   *
 *   it under the terms of the GNU Affero General Public License as      *
 *   published by the Free Software Foundation, either version 3 of      *
 *   the License, or (at your option) any later version.                 *
 *                                                                       *
 *   TeapotNet 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 Affero General Public License for more details.                 *
 *                                                                       *
 *   You should have received a copy of the GNU Affero General Public    *
 *   License along with TeapotNet.                                       *
 *   If not, see <http://www.gnu.org/licenses/>.                         *
 *************************************************************************/

#include "tpn/mutex.h"
#include "tpn/exception.h"

namespace tpn
{

Mutex::Mutex(void) :
	mLockCount(0),
	mRelockCount(0)
{

	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
	//pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);

	 if(pthread_mutex_init(&mMutex, &attr) != 0)
		 throw Exception("Unable to create mutex");
}

Mutex::~Mutex(void)
{
	pthread_mutex_destroy(&mMutex);
}

void Mutex::lock(int count)
{
	if(count <= 0) return;

	int ret = pthread_mutex_lock(&mMutex);
	if(ret != 0 && ret != EDEADLK)
		throw Exception("Unable to lock mutex");

	if(ret == 0) Assert(mLockCount == 0);
	mLockedBy = pthread_self();
	mLockCount+= count;
}

bool Mutex::tryLock(void)
{
	int ret = pthread_mutex_trylock(&mMutex);
        if(ret == EBUSY) return false;

        if(ret != 0 && ret != EDEADLK)
                throw Exception("Unable to lock mutex");

	if(ret == 0) Assert(mLockCount == 0);
	mLockedBy = pthread_self();
        mLockCount++;
	return true;
}

void Mutex::unlock(void)
{
	if(!mLockCount)
		throw Exception("Mutex is not locked");

	//if(!pthread_equal(mLockedBy, pthread_self()))
	//	throw Exception("Mutex is locked by another thread");

	mLockCount--;
	if(mLockCount == 0)
	{
		int ret = pthread_mutex_unlock(&mMutex);
		if(ret != 0) throw Exception("Unable to unlock mutex");
	}
}

int Mutex::unlockAll(void)
{
	if(!mLockCount)
		throw Exception("Mutex is not locked");

	//if(!pthread_equal(mLockedBy, pthread_self()))
	//	throw Exception("Mutex is locked by another thread");

 	mRelockCount = mLockCount;
	mLockCount = 0;

	int ret = pthread_mutex_unlock(&mMutex);
	if(ret != 0) throw Exception("Unable to unlock mutex");

	return mRelockCount;
}

void Mutex::relockAll(void)
{
	lock(mRelockCount);
	mRelockCount = 0;
}

int Mutex::lockCount(void) const
{
	return mLockCount;
}

}
<|endoftext|>