Alien-LibJIT

 view release on metacpan or  search on metacpan

libjit/dpas/dpas-parser.y  view on Meta::CPAN

 *
 * The libjit library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the libjit library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include "dpas-internal.h"
#include <jit/jit-dump.h>
#include <config.h>
#ifdef HAVE_STDLIB_H
	#include <stdlib.h>
#endif
#ifdef HAVE_STDARG_H
	#include <stdarg.h>
#elif HAVE_VARARGS_H
	#include <varargs.h>
#endif

/*
 * Imports from the lexical analyser.
 */
extern int yylex(void);
#ifdef YYTEXT_POINTER
extern char *yytext;
#else
extern char yytext[];
#endif

/*
 * Error reporting flag.
 */
int dpas_error_reported = 0;

/*
 * Function dumping flag.
 */
int dpas_dump_functions = 0;

/*
 * Report error messages from the parser.
 */
static void yyerror(char *msg)
{
	char *text = yytext;
	char *newmsg;
	int posn, outposn;
	dpas_error_reported = 1;
	if(!jit_strcmp(msg, "parse error") || !jit_strcmp(msg, "syntax error"))
	{
		/* This error is pretty much useless at telling the user
		   what is happening.  Try to print a better message
		   based on the current input token */
	simpleError:
		if(text && *text != '\0')
		{
			fprintf(stderr, "%s:%ld: parse error at or near `%s'\n",
					dpas_filename, dpas_linenum, text);
		}
		else
		{
			fprintf(stderr, "%s:%ld: parse error\n",
					dpas_filename, dpas_linenum);
		}
	}
	else if(!jit_strncmp(msg, "parse error, expecting `", 24))
	{
		/* We have to quote the token names in the "%token" declarations
		   within yacc grammars so that byacc doesn't mess up the output.
		   But the quoting causes Bison to output quote characters in
		   error messages which look awful.  This code attempts to fix
		   things up */
		newmsg = jit_strdup(msg);
	expectingError:
		if(newmsg)
		{
			posn = 0;
			outposn = 0;
			while(newmsg[posn] != '\0')
			{
				if(newmsg[posn] == '`')
				{
					if(newmsg[posn + 1] == '"' && newmsg[posn + 2] == '`')
					{
						/* Convert <`"`> into <`> */
						posn += 2;
						newmsg[outposn++] = '`';
					}
					else if(newmsg[posn + 1] == '"')
					{
						/* Convert <`"> into <> */
						++posn;
					}
					else if(newmsg[posn + 1] == '`' ||
					        newmsg[posn + 1] == '\'')
					{
						/* Convert <``> or <`'> into <`> */
						++posn;
						newmsg[outposn++] = '`';
					}
					else
					{
						/* Ordinary <`> on its own */
						newmsg[outposn++] = '`';
					}
				}
				else if(newmsg[posn] == '\\')
				{
					/* Ignore backslashes in the input */
				}
				else if(newmsg[posn] == '"' && newmsg[posn + 1] == '\'')
				{
					/* Convert <"'> into <> */
					++posn;
				}
				else if(newmsg[posn] == '\'' && newmsg[posn + 1] == '"' &&
				        newmsg[posn + 2] == '\'')
				{
					/* Convert <'"'> into <'> */
					posn += 2;
					newmsg[outposn++] = '\'';
				}
				else if(newmsg[posn] == '\'' && newmsg[posn + 1] == '\'')
				{
					/* Convert <''> into <'> */
					++posn;
					newmsg[outposn++] = '\'';
				}
				else if(newmsg[posn] == ' ' && newmsg[posn + 1] == '\'')
				{
					/*  bison 1.75 - <'> following a space becomes <`> */
					++posn;
					newmsg[outposn++] = ' ';
					newmsg[outposn++] = '`';
				}
				else if(newmsg[posn] == '"')
				{
					/* Ignore quotes - bison 1.75 */
				}
				else
				{
					/* Ordinary character */
					newmsg[outposn++] = newmsg[posn];
				}
				++posn;
			}
			newmsg[outposn] = '\0';
			if(text && *text != '\0')
			{
				fprintf(stderr, "%s:%ld: %s, at or near `%s'\n",
						dpas_filename, dpas_linenum, newmsg, text);
			}
			else
			{
				fprintf(stderr, "%s:%ld: %s\n",
						dpas_filename, dpas_linenum, newmsg);
			}
			jit_free(newmsg);
		}
		else
		{
			if(text && *text != '\0')
			{
				fprintf(stderr, "%s:%ld: %s at or near `%s'\n",
						dpas_filename, dpas_linenum, msg, text);
			}
			else
			{
				fprintf(stderr, "%s:%ld: %s\n",
						dpas_filename, dpas_linenum, msg);
			}
		}
	}
	else if(!jit_strncmp(msg, "parse error, unexpected ", 24))
	{
		/* The error probably has the form "parse error, unexpected ...,
		   expecting ..." - strip out the "unexpected" part */
		posn = 24;
		while(msg[posn] != '\0' &&
			  jit_strncmp(msg + posn, ", expecting ", 12) != 0)
		{
			++posn;
		}
		if(msg[posn] == '\0')
		{
			goto simpleError;
		}
		newmsg = (char *)jit_malloc(jit_strlen(msg) + 1);
		if(!newmsg)
		{
			goto defaultError;
		}
		jit_strcpy(newmsg, "parse error, expecting ");
		jit_strcat(newmsg, msg + posn + 12);
		goto expectingError;
	}
	else
	{
		/* The parser has probably included information as to what
		   is expected in this context, so report that */
	defaultError:
		if(text && *text != '\0')
		{
			fprintf(stderr, "%s:%ld: %s at or near `%s'\n",
					dpas_filename, dpas_linenum, msg, text);
		}
		else
		{
			fprintf(stderr, "%s:%ld: %s\n",
					dpas_filename, dpas_linenum, msg);
		}
	}
}

void dpas_error(const char *format, ...)
{
	va_list va;
#ifdef HAVE_STDARG_H
	va_start(va, format);
#else
	va_start(va);
#endif
	fprintf(stderr, "%s:%ld: ", dpas_filename, dpas_linenum);
	vfprintf(stderr, format, va);
	putc('\n', stderr);
	va_end(va);
	dpas_error_reported = 1;
}

void dpas_warning(const char *format, ...)
{
	va_list va;
#ifdef HAVE_STDARG_H
	va_start(va, format);
#else
	va_start(va);
#endif
	fprintf(stderr, "%s:%ld: warning: ", dpas_filename, dpas_linenum);
	vfprintf(stderr, format, va);
	putc('\n', stderr);
	va_end(va);
}

void dpas_error_on_line(const char *filename, long linenum,
                        const char *format, ...)
{
	va_list va;
#ifdef HAVE_STDARG_H
	va_start(va, format);
#else
	va_start(va);
#endif
	fprintf(stderr, "%s:%ld: ", filename, linenum);
	vfprintf(stderr, format, va);
	putc('\n', stderr);
	va_end(va);
	dpas_error_reported = 1;
}

static void dpas_undeclared(const char *name)
{
	dpas_error("`%s' is not declared in the current scope", name);
}

static void dpas_redeclared(const char *name, dpas_scope_item_t item)
{
	dpas_error("`%s' is already declared in the current scope", name);
	dpas_error_on_line(dpas_scope_item_filename(item),
					   dpas_scope_item_linenum(item),
					   "previous declaration of `%s' here", name);
}

/*
 * Add an item to a list of identifiers.
 */
static void identifier_list_add(char ***list, int *len, char *name)
{
	char **new_list = (char **)jit_realloc(*list, sizeof(char *) * (*len + 1));
	if(!new_list)
	{
		dpas_out_of_memory();
	}
	new_list[*len] = name;
	++(*len);
	*list = new_list;
}

/*
 * Free the contents of an identifier list.
 */
static void identifier_list_free(char **list, int len)
{
	int posn;
	for(posn = 0; posn < len; ++posn)
	{
		jit_free(list[posn]);
	}
	jit_free(list);
}

/*
 * Determine if an identifier list contains a specific item.
 */
static int identifier_list_contains(char **list, int len, const char *name)
{
	int posn;
	for(posn = 0; posn < len; ++posn)
	{
		if(list[posn] && !jit_stricmp(list[posn], name))
		{
			return 1;
		}
	}
	return 0;
}



( run in 1.163 second using v1.01-cache-2.11-cpan-d59ab9ce9b0 )