/*	$Id: parser.c,v 1.2 2002/04/19 04:12:40 riq Exp $	*/
/* 
	IN:  PARSER_PTR  (->sig tiene la cadena a parsear )
	OUT: TRUE si hay mas para leer.
		FALSE si no hay mas.
		PARSER_PTR->token = 1er token
		PARSER_PTR->valor = su valor
		PARSER_PTR->sig = Puntero al siguiente token
		PARSER_PTR->status= TRUE si estaba bien escrito

	Separadores:  son pasados por DELIM_PTR a 
	Igualadores:  son pasados por DELIM_PTR b
	Fin / EOF: asciiz
 Ejemplos validos:
 	"Quiero un nuevo mundo=TRUE;Me gusta Linux=Si"
	"Hola;Como;Te;Va"
 Ejemplos no validos:
 	"Hola=343=534"
*/

#include <ctype.h>
#include <string.h>
#include "parser.h"

/* Que tipo de char es? */
static int que_es( char a, DELIM_PTR igualador, DELIM_PTR separador )
{
	if( a==0 || a=='\n' || a=='\r' )
		return PARSER_FIN;
	if( a==igualador->a || a==igualador->b || a==igualador->c )
		return PARSER_IGUAL;
	if( a==separador->a || a==separador->b || a==separador->c )
		return PARSER_SEPARADOR;

	return PARSER_DATA;
}


static int			/* True or False */
analiza( int *corto_pos,	/* En que pos corto la cadena */
	int *corto_valor,	/* Con que valor corto la cadena */
	char *in,		/* Cadena de entrada */ 
	char *out,		/* Cadena de salida */
	int max,		/* Max valor que puede tener la cadena */
	DELIM_PTR igualador,	/* IGUALADORES */
	DELIM_PTR separador	/* SEPARADORES */
	)
{
	int i;
	int k;
	
	out[0]=0;

	for(i=0;i<max;i++) {
		if( (k=que_es(in[i],igualador,separador))!=PARSER_DATA ) break;
		out[i]=tolower(in[i]);
		out[i+1]=0;
	}	

	*corto_pos=i;
	if(i==max) {
		*corto_valor = PARSER_ERROR;
		return FALSE;
	}
	*corto_valor=k;
	return TRUE;
}

/* Unica funcion exportable */
int		/* True hay mas datos
		False, no hay mas para leer*/
parser_init( PARSER_PTR p_in )
{
	int j,k,k2;

	if(!analiza( &k, &j, p_in->sig, p_in->token,  PARSER_TOKEN_MAX, p_in->igualador, p_in->separador ) )
		return FALSE;
	
	p_in->value[0]=0;
	p_in->status=FALSE;

	switch(j) {
	case PARSER_FIN:
		p_in->sig[0]=0;
		p_in->status=TRUE;
		return FALSE;
	case PARSER_SEPARADOR:
		strncpy(p_in->sig, &p_in->sig[k+1], sizeof(p_in->sig) );
		p_in->status=TRUE;
		return TRUE;
	case PARSER_IGUAL:
		if(!analiza( &k2, &j, &p_in->sig[k+1], p_in->value, PARSER_VALUE_MAX, p_in->igualador, p_in->separador ))
			return FALSE;
		if(j==PARSER_IGUAL || j==PARSER_SEPARADOR )
			k++;
		strncpy(p_in->sig, &p_in->sig[k2+k+1],sizeof(p_in->sig) );
		if( j==PARSER_ERROR || j==PARSER_IGUAL )
			return FALSE;
		p_in->status=TRUE;	/* hasta aca todo fue bien leido */
		if( j==PARSER_FIN )	/* No hay mas para leer */
			return FALSE;
		return TRUE;
	case PARSER_ERROR:
	default:
		return FALSE;
	}	
}
