// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: parser.cpp 844 2011-10-13 22:05:28Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#include "parser.h"
#include "graph.h"
#include <cstdio>
#include <cassert>
#include <cstdlib>

static inline 
void parse_state(FILE* file, Graph* graph) {
    char label[1000];
    int node;
    int res = fscanf(file, "%d ", &node);
    assert(res == 1);
    for (int cnt = 0; ; ++cnt) {
	char c = fgetc(file);
	if (c == '\n' || feof(file)) {
	    label[cnt] = 0;
	    break;
	}
	label[cnt] = c;
    }
    graph->labelNode(node, label);
} 

static inline 
void parse_trans(FILE* file, Graph* graph) {
    int from, to;
    int res = fscanf(file, "%d %d\n", &from, &to);
    assert(res == 2);
    graph->addEdge(from, to);
} 

static inline 
void parse_init(FILE* file, Graph* graph) {
    int init;
    int res = fscanf(file, "%d\n", &init);
    assert(res == 1);
    graph->setInitial(init);
} 

static inline 
void parse_dead(FILE* file, Graph* graph) {
    int dead;
    int res = fscanf(file, "%d\n", &dead);
    assert(res == 1);
    // FIXME: this info is not yet used
} 

static inline 
void parse_goal(FILE* file, Graph* graph) {
    int goal;
    int res = fscanf(file, "%d\n", &goal);
    assert(res == 1);
    graph->setTarget(goal);
}

Graph* Parser::parse(const char* filename) const {
    Graph* graph = new Graph;
    
    FILE* file = fopen(filename, "r");
    while (!feof(file)) {
	char c;
	int res = fscanf(file, "%c ", &c);
	assert(res == 1);
	switch (c) {
	case 'T': parse_trans(file, graph); break;
	case 'S': parse_state(file, graph); break;
	case 'G': parse_goal(file, graph); break;
	case 'I': parse_init(file, graph); break;
	case 'D': parse_dead(file, graph); break;
	default:  assert(false);
	}
    }
    fclose(file);
    
    return graph;
}
