git @ Cat's Eye Technologies Thue / master src / thue.c
master

Tree @master (Download .tar.gz)

thue.c @masterraw · history · blame

/* $Header: C:\\UTILS\\CVS\\ROOT/programs\\lang\\thue/thue.c,v 1.4 2000/09/02 16:46:29 John Colagioia Exp $
 *
 * Recent Changes:
 *
 * $Log: thue.c,v $
 * Revision 1.5  2010/12/18           Chris Pressey
 * Fix off-by-one error in sort routine, reported by
 * Nathan Thern.  Fix another off-by-one error in
 * random number generation.  Modernize: use rand()
 * and rename getline() to avoid name conflict.
 *
 * Revision 1.4  2000/09/02 16:46:29  John Colagioia
 * Trivial bugfix.
 *
 * Revision 1.2  2000/02/29 21:51:24  John Colagioia
 *
 * Just added some basic header info in the comments.
 *
 *
 */

/* For want of a nail,
    the shoe was lost.
   For want of a shoe,
    the horse was lost.
   For want of a horse,
    the knight was lost.
   For want of a knight,
    the battle was lost.
   So it was a kingdom was lost,
    all for the want of a nail.
	-- George Herbert, Jacula Prudentum
	   (Colloqual Adaptation)
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

#define	SEP	"::="

	char	* get_line	(FILE * infile);

struct rule
	{
	 char	lhs[64];
	 char	rhs[64];
	} rulebase[128];

int	ruleidx = 0,
	debug = 0;
char	*dataspace,
	*tempspace;

int main (int argc, char *argv[])
{
 char	*line,
	*c,
	*tmp,
	*target[64],
	 tempstr[64];
 int	 state,
	 flagstate,
	 i, j, k,
	 order,
	 temp,
	 rnum[64];
 FILE	*infile;

 srand(time(0));
 dataspace = malloc(16384);
 tempspace = malloc(16384);
 if (dataspace == NULL || tempspace == NULL) {
	fprintf (stderr, "Could not allocate sufficient working memory\n");
	exit(1);
 }
 target[0] = dataspace;
 memset (rulebase, 0, sizeof (rulebase));
 memset (dataspace, 0, sizeof (dataspace));
 if (argc > 1)
	infile = fopen (argv[1], "r");
 else
	infile = stdin;
 if (infile == NULL)
	return (-1);

 order = 0;
 if (argc > 2)
    switch (argv[2][0])
	{
	 case 'r':	/* Right-to-Left Processing */
		order = 2;
		break;
	 case 'l':	/* Left-to-Right */
		order = 1;
		break;
	 case 'd':
		debug = 1;
		break;
	}

 /* Get input file */
 state = 0;
 while (!feof (infile))
	{
	 line = get_line (infile);
	 if (state == 0)
		{
		 if (line != NULL && !strlen (line))
			continue;
		 c = strstr (line, SEP);
		 if (c == NULL)
			fprintf (stderr, "Malformed production: \"%s\"!\n", line);
		 else if (c == line)
			state = 1;
		 else	{
			 flagstate = 0;
			 for (tmp=line;tmp!=c;tmp++)
				if (!isspace (*tmp))
					 flagstate = 1;
			 if (flagstate)
				{
				 *c = '\000';
				 c += strlen (SEP);
				 strcpy (rulebase[ruleidx].lhs, line);
				 strcpy (rulebase[ruleidx].rhs, c);
				 ++ruleidx;
				}
			 else	state = 1;
			}
		}
	 else if (line != NULL)
			strcat (dataspace, line);
	}

 if (debug)
	printf ("Initial:  \"%s\"\n", dataspace);

 /* Apply rules */
 state = 1;
 while (state)
	{
	 /* Get all valid LHSs */
	 j = 1;
	 k = 0;
	 c = dataspace;
	 for (i=0;i<ruleidx;i++)
	    do
		{
		 k = j;
		 target[k] = strstr (c, rulebase[i].lhs);
		 rnum[k] = i;
		 if (target[k] != NULL)
			{
			 ++j;
			 c = target[k] + 1;
			}
		 else
			c = dataspace;
		}
	    while (target[k]);

	 if (j == 1)
		{
		 state = 0;
		 continue;
		}

	 /* Sort the LHS list - Just a bubble sort */
	 for (i=1;i<j;i++)
	    for (k=1;k<i;k++)
		if (target[i] < target[k])
			{
			 c = target[i];		temp = rnum[i];
			 target[i] = target[k];	rnum[i] = rnum[k];
			 target[k] = c;		rnum[k] = temp;
			}

	 /* Choose rule to apply */
	 switch (order)
		{
		 case 2:
			i = j - 1;
			break;
		 case 1:
			i = 1;
			break;
		 default:
			i = rand() % (j - 1) + 1;
			break;
		}
	 line = target[i];
	 temp = rnum[i];
	 c = line + strlen (rulebase[temp].lhs);
	 *line = '\000';

	 /* Check for I/O */
	 i = rulebase[temp].rhs[0] == '~';
	 if (i)
		{
		 puts (&rulebase[temp].rhs[1]);
		 memset (tempstr, 0, sizeof (tempstr));
		}
	 else
		{
 		 i = !strcmp (rulebase[temp].rhs, ":::");
		 if (i)
                     {
			fgets (tempstr, sizeof (tempstr), stdin);
                        tempstr[strlen (tempstr) - 1] = '\0';
                     }
		}

	 /* Apply the rule */
	 sprintf (tempspace, "%s%s%s", dataspace, i?tempstr:rulebase[temp].rhs, c);
	 strcpy (dataspace, tempspace);
	 if (debug)
		puts (dataspace);
	}

 if (debug)
	printf ("Final:  \"%s\"\n", dataspace);
 return (0);
}

char * get_line (FILE * infile)
{
 static	char	 buffer[256];
	char	*s;

 memset (buffer, 0, sizeof (buffer));
 /* Get next line from file */
 s = fgets (buffer, sizeof (buffer), infile);
 if (s == NULL)
	return (NULL);
 buffer[strlen (buffer) - 1] = '\0';
 /* Return pointer to string */
 return (buffer);
}