started adding new error infrastructure
This commit is contained in:
parent
508194029a
commit
5e8d706cf0
|
@ -27,6 +27,7 @@ SET(HDRS
|
|||
parser.h
|
||||
tokenizer.h
|
||||
unicode.h
|
||||
error.h
|
||||
)
|
||||
|
||||
SET(SRCS
|
||||
|
@ -36,6 +37,7 @@ SET(SRCS
|
|||
parser.c
|
||||
tokenizer.c
|
||||
unicode.c
|
||||
error.c
|
||||
)
|
||||
|
||||
add_executable(lci ${SRCS} ${HDRS})
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#include "error.h"
|
||||
|
||||
static const char *err_msgs[] = {
|
||||
/* MN_ERROR_OPENING_FILE */
|
||||
"Error opening file '%s'.\n",
|
||||
/* MN_ERROR_CLOSING_FILE */
|
||||
"Error closing file '%s'.\n",
|
||||
|
||||
/* LX_LINE_CONTINUATION */
|
||||
"%s:%d: a line with continuation may not be followed by an empty line\n",
|
||||
/* LX_MULTIPLE_LINE_COMMENT */
|
||||
"%s:%d: multiple line comment may not appear on the same line as code\n",
|
||||
/* LX_EXPECTED_TOKEN_DELIMITER */
|
||||
"%s:%d: expected token delimiter after string literal\n",
|
||||
|
||||
/* TK_EXPECTED_FLOATING_POINT */
|
||||
"%s:%u: expected floating point decimal value\n",
|
||||
/* TK_EXPECTED_INTEGER */
|
||||
"%s:%u: expected integer value\n",
|
||||
/* TK_UNKNOWN_TOKEN */
|
||||
"%s:%u: unknown token at: %s\n",
|
||||
|
||||
/* PR_UNKNOWN_IDENTIFIER_TYPE */
|
||||
"%s:%u: unable to delete unknown identifier type\n",
|
||||
/* PR_UNKNOWN_STATEMENT_TYPE */
|
||||
"unable to delete unknown statement type\n",
|
||||
/* PR_UNKNOWN_EXPRESSION_TYPE */
|
||||
"unable to delete unknown expression type\n",
|
||||
/* PR_EXPECTED_BOOLEAN */
|
||||
"%s:%u: expected integer at: %s\n",
|
||||
/* PR_EXPECTED_INTEGER */
|
||||
"%s:%u: expected integer at: %s\n",
|
||||
/* PR_EXPECTED_FLOAT */
|
||||
"%s:%u: expected float at: %s\n",
|
||||
/* PR_EXPECTED_STRING */
|
||||
"%s:%u: expected string at: %s\n",
|
||||
/* PR_EXPECTED_CONSTANT */
|
||||
"%s:%u: expected constant value at: %s\n",
|
||||
/* PR_EXPECTED_TYPE */
|
||||
"%s:%u: expected type at: %s\n",
|
||||
/* PR_EXPECTED_IDENTIFIER */
|
||||
"%s:%u: expected identifier at: %s\n",
|
||||
/* PR_EXPECTED_TOKEN */
|
||||
"%s:%u: expected %s at: %s\n",
|
||||
/* PR_INVALID_OPERATOR */
|
||||
"%s:%u: invalid operator at: %s\n",
|
||||
/* PR_EXPECTED_EXPRESSION */
|
||||
"%s:%u: expected expression at: %s\n",
|
||||
/* PR_EXPECTED_END_OF_EXPRESSION */
|
||||
"%s:%u: expected end of expression at: %s\n",
|
||||
/* PR_EXPECTED_END_OF_STATEMENT */
|
||||
"%s:%u: expected end of statement at: %s\n",
|
||||
/* PR_CANNOT_USE_STR_AS_LITERAL */
|
||||
"%s:%u: cannot use an interpolated string as an OMG literal at: %s\n",
|
||||
/* PR_LITERAL_MUST_BE_UNIQUE */
|
||||
"%s:%u: OMG literal must be unique at: %s\n",
|
||||
/* PR_EXPECTED_LOOP_NAME */
|
||||
"%s:%u: expected loop name at: %s\n",
|
||||
/* PR_EXPECTED_EITHER_TOKEN */
|
||||
"%s:%u: expected %s or %s at: %s\n",
|
||||
/* PR_EXPECTED_UNARY_FUNCTION */
|
||||
"%s:%u: expected unary function at: %s\n",
|
||||
/* PR_EXPECTED_MATCHING_LOOP_NAME */
|
||||
"%s:%u: expected matching loop name at: %s\n",
|
||||
/* PR_EXPECTED_STATEMENT */
|
||||
"%s:%u: expected statement at: %s\n",
|
||||
};
|
||||
|
||||
static const int err_codes[] = {
|
||||
/* The 100 block is for the main body */
|
||||
100, /* MN_ERROR_OPENING_FILE */
|
||||
101, /* MN_ERROR_CLOSING_FILE */
|
||||
|
||||
/* The 200 block is for the lexer */
|
||||
200, /* LX_LINE_CONTINUATION */
|
||||
201, /* LX_MULTIPLE_LINE_COMMENT */
|
||||
202, /* LX_EXPECTED_TOKEN_DELIMITER */
|
||||
|
||||
/* The 300 block is for the tokenizer */
|
||||
300, /* TK_EXPECTED_FLOATING_POINT */
|
||||
301, /* TK_EXPECTED_INTEGER */
|
||||
302, /* TK_UNKNOWN_TOKEN */
|
||||
|
||||
/* The 400 block is for the parser */
|
||||
400, /* PR_UNKNOWN_IDENTIFIER_TYPE */
|
||||
401, /* PR_UNKNOWN_STATEMENT_TYPE */
|
||||
402, /* PR_UNKNOWN_EXPRESSION_TYPE */
|
||||
403, /* PR_EXPECTED_BOOLEAN */
|
||||
404, /* PR_EXPECTED_INTEGER */
|
||||
405, /* PR_EXPECTED_FLOAT */
|
||||
406, /* PR_EXPECTED_STRING */
|
||||
407, /* PR_EXPECTED_CONSTANT */
|
||||
408, /* PR_EXPECTED_TYPE */
|
||||
409, /* PR_EXPECTED_IDENTIFIER */
|
||||
410, /* PR_EXPECTED_TOKEN */
|
||||
411, /* PR_INVALID_OPERATOR */
|
||||
412, /* PR_EXPECTED_EXPRESSION */
|
||||
413, /* PR_EXPECTED_END_OF_EXPRESSION */
|
||||
414, /* PR_EXPECTED_END_OF_STATEMENT */
|
||||
415, /* PR_CANNOT_USE_STR_AS_LITERAL */
|
||||
416, /* PR_LITERAL_MUST_BE_UNIQUE */
|
||||
417, /* PR_EXPECTED_LOOP_NAME */
|
||||
418, /* PR_EXPECTED_ONE_OF */
|
||||
419, /* PR_EXPECTED_UNARY_FUNCTION */
|
||||
420, /* PR_EXPECTED_MATCHING_LOOP_NAME */
|
||||
421, /* PR_EXPECTED_STATEMENT */
|
||||
|
||||
/* The 500 block is for the interpreter */
|
||||
};
|
||||
|
||||
void error2(ErrorType e, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, e);
|
||||
vfprintf(stderr, err_msgs[e], args);
|
||||
va_end(args);
|
||||
|
||||
exit(err_codes[e]);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Error type definitions.
|
||||
*
|
||||
* \file error.h
|
||||
*
|
||||
* \author Justin J. Meza
|
||||
*
|
||||
* \date 2012
|
||||
*/
|
||||
|
||||
#ifndef __ERROR_H__
|
||||
#define __ERROR_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* Represents an error type. The error types are organized based on which
|
||||
* module they occur in:
|
||||
*
|
||||
* - MN_* for the main body,
|
||||
* - LX_* for the lexer,
|
||||
* - TK_* for the tokenizer,
|
||||
* - PR_* for the parser,
|
||||
* - IN_* for the interpreter
|
||||
*
|
||||
* \note Remember to update the error message and error code arrays (in the
|
||||
* error C file) with the appropriate error message and code.
|
||||
*/
|
||||
typedef enum {
|
||||
MN_ERROR_OPENING_FILE,
|
||||
MN_ERROR_CLOSING_FILE,
|
||||
|
||||
LX_LINE_CONTINUATION,
|
||||
LX_MULTIPLE_LINE_COMMENT,
|
||||
LX_EXPECTED_TOKEN_DELIMITER,
|
||||
|
||||
TK_EXPECTED_FLOATING_POINT,
|
||||
TK_EXPECTED_INTEGER,
|
||||
TK_UNKNOWN_TOKEN,
|
||||
|
||||
PR_UNKNOWN_IDENTIFIER_TYPE,
|
||||
PR_UNKNOWN_STATEMENT_TYPE,
|
||||
PR_UNKNOWN_EXPRESSION_TYPE,
|
||||
PR_EXPECTED_BOOLEAN,
|
||||
PR_EXPECTED_INTEGER,
|
||||
PR_EXPECTED_FLOAT,
|
||||
PR_EXPECTED_STRING,
|
||||
PR_EXPECTED_CONSTANT,
|
||||
PR_EXPECTED_TYPE,
|
||||
PR_EXPECTED_IDENTIFIER,
|
||||
PR_EXPECTED_TOKEN,
|
||||
PR_INVALID_OPERATOR,
|
||||
PR_EXPECTED_EXPRESSION,
|
||||
PR_EXPECTED_END_OF_EXPRESSION,
|
||||
PR_EXPECTED_END_OF_STATEMENT,
|
||||
PR_CANNOT_USE_STR_AS_LITERAL,
|
||||
PR_LITERAL_MUST_BE_UNIQUE,
|
||||
PR_EXPECTED_LOOP_NAME,
|
||||
PR_EXPECTED_EITHER_TOKEN,
|
||||
PR_EXPECTED_UNARY_FUNCTION,
|
||||
PR_EXPECTED_MATCHING_LOOP_NAME,
|
||||
PR_EXPECTED_STATEMENT,
|
||||
} ErrorType;
|
||||
|
||||
void error2(ErrorType, ...);
|
||||
|
||||
#endif /* __ERROR_H__ */
|
6
lexer.c
6
lexer.c
|
@ -236,7 +236,7 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
/* Make sure next line is not empty */
|
||||
while (*test && isspace(*test)) {
|
||||
if (*test == '\r' || *test == '\n') {
|
||||
fprintf(stderr, "%s:%d: a line with continuation may not be followed by an empty line\n", fname, line);
|
||||
error2(LX_LINE_CONTINUATION, fname, line);
|
||||
deleteLexemeList(list);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
start++;
|
||||
if (start == buffer || *start == ',' || *start == '\r' || *start == '\n')
|
||||
continue;
|
||||
fprintf(stderr, "%s:%d: multiple line comment may not appear on the same line as code\n", fname, line);
|
||||
error2(LX_MULTIPLE_LINE_COMMENT, fname, line);
|
||||
deleteLexemeList(list);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname)
|
|||
&& strncmp(start + len, "'Z", 2)
|
||||
&& strncmp(start + len, "...", 3)
|
||||
&& strncmp(start + len, "\xE2\x80\xA6", 3)) {
|
||||
fprintf(stderr, "%s:%d: expected token delimiter after string literal\n", fname, line);
|
||||
error2(LX_EXPECTED_TOKEN_DELIMITER, fname, line);
|
||||
deleteLexemeList(list);
|
||||
return NULL;
|
||||
}
|
||||
|
|
2
lexer.h
2
lexer.h
|
@ -20,6 +20,8 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
/**
|
||||
|
|
8
main.c
8
main.c
|
@ -114,6 +114,7 @@
|
|||
#include "tokenizer.h"
|
||||
#include "parser.h"
|
||||
#include "interpreter.h"
|
||||
#include "error.h"
|
||||
|
||||
#define READSIZE 512
|
||||
|
||||
|
@ -156,7 +157,6 @@ int main(int argc, char **argv)
|
|||
while ((ch = getopt_long(argc, argv, shortopt, longopt, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
default:
|
||||
fprintf (stderr, "Incorrect option '%c'\n", ch);
|
||||
help();
|
||||
exit(EXIT_FAILURE);
|
||||
case 'h':
|
||||
|
@ -176,7 +176,7 @@ int main(int argc, char **argv)
|
|||
node = NULL;
|
||||
file = NULL;
|
||||
|
||||
if (!strncmp (argv[optind],"-\0",2)) {
|
||||
if (!strncmp(argv[optind],"-\0",2)) {
|
||||
file = stdin;
|
||||
fname = "stdin";
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (!file) {
|
||||
fprintf(stderr, "File does not exist.\n");
|
||||
error2(MN_ERROR_OPENING_FILE, argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (fclose(file) != 0) {
|
||||
fprintf(stderr, "Error closing file.\n");
|
||||
error2(MN_ERROR_CLOSING_FILE, argv[optind]);
|
||||
if (buffer) free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
|
203
parser.c
203
parser.c
|
@ -306,7 +306,7 @@ void deleteIdentifierNode(IdentifierNode *node)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unable to delete unknown identifier type\n");
|
||||
error2(PR_UNKNOWN_IDENTIFIER_TYPE, node->fname, node->line);
|
||||
break;
|
||||
}
|
||||
if (node->slot) deleteIdentifierNode(node->slot);
|
||||
|
@ -515,7 +515,7 @@ void deleteStmtNode(StmtNode *node)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unable to delete unknown statement type\n");
|
||||
error2(PR_UNKNOWN_STATEMENT_TYPE);
|
||||
break;
|
||||
}
|
||||
free(node);
|
||||
|
@ -1158,7 +1158,7 @@ void deleteExprNode(ExprNode *node)
|
|||
case ET_IMPVAR:
|
||||
break; /* This expression type does not have any content */
|
||||
default:
|
||||
fprintf(stderr, "Unable to delete unknown expression type\n");
|
||||
error2(PR_UNKNOWN_EXPRESSION_TYPE);
|
||||
break;
|
||||
}
|
||||
free(node);
|
||||
|
@ -1417,21 +1417,56 @@ int nextToken(Token ***tokenp,
|
|||
}
|
||||
|
||||
/**
|
||||
* Prints an error message of the form "FILE:LINE: INFO before: NEXT.\n", where
|
||||
* LINE is the line the head of \a tokens appears on, INFO is \a info, and NEXT
|
||||
* is the image of the head of \a tokens.
|
||||
* A simple wrapper around the global error printing function tailored to
|
||||
* general parser errors.
|
||||
*
|
||||
* \param [in] info The information to print.
|
||||
* \param [in] type The type of error.
|
||||
*
|
||||
* \param [in] tokens The tokens being parsed when the error occurred.
|
||||
*/
|
||||
void error(const char *info,
|
||||
Token **tokens)
|
||||
void parser_error(ErrorType type,
|
||||
Token **tokens)
|
||||
{
|
||||
fprintf(stderr, "%s:%u: %s at: %s\n",
|
||||
error2(type, (*tokens)->fname, (*tokens)->line, (*tokens)->image);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapper around the global error printing function tailored to
|
||||
* expected token parser errors.
|
||||
*
|
||||
* \param [in] token The expected token's image.
|
||||
*
|
||||
* \param [in] tokens The tokens being parsed when the error occurred.
|
||||
*/
|
||||
void parser_error_expected_token(TokenType token,
|
||||
Token **tokens)
|
||||
{
|
||||
error2(PR_EXPECTED_TOKEN,
|
||||
(*tokens)->fname,
|
||||
(*tokens)->line,
|
||||
info,
|
||||
keywords[token],
|
||||
(*tokens)->image);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapper around the global error printing function tailored to
|
||||
* expected two token parser errors.
|
||||
*
|
||||
* \param [in] token1 The first expected token's image.
|
||||
*
|
||||
* \param [in] token2 The second expected token's image.
|
||||
*
|
||||
* \param [in] tokens The tokens being parsed when the error occurred.
|
||||
*/
|
||||
void parser_error_expected_either_token(TokenType token1,
|
||||
TokenType token2,
|
||||
Token **tokens)
|
||||
{
|
||||
error2(PR_EXPECTED_TOKEN,
|
||||
(*tokens)->fname,
|
||||
(*tokens)->line,
|
||||
keywords[token1],
|
||||
keywords[token2],
|
||||
(*tokens)->image);
|
||||
}
|
||||
|
||||
|
@ -1471,7 +1506,7 @@ ConstantNode *parseConstantNode(Token ***tokenp)
|
|||
/* This should succeed; it was checked for above */
|
||||
status = acceptToken(&tokens, TT_BOOLEAN);
|
||||
if (!status) {
|
||||
error("expected boolean", tokens);
|
||||
parser_error(PR_EXPECTED_BOOLEAN, tokens);
|
||||
goto parseConstantNodeAbort;
|
||||
}
|
||||
}
|
||||
|
@ -1487,7 +1522,7 @@ ConstantNode *parseConstantNode(Token ***tokenp)
|
|||
/* This should succeed; it was checked for above */
|
||||
status = acceptToken(&tokens, TT_INTEGER);
|
||||
if (!status) {
|
||||
error("expected integer", tokens);
|
||||
parser_error(PR_EXPECTED_INTEGER, tokens);
|
||||
goto parseConstantNodeAbort;
|
||||
}
|
||||
}
|
||||
|
@ -1503,7 +1538,7 @@ ConstantNode *parseConstantNode(Token ***tokenp)
|
|||
/* This should succeed; it was checked for above */
|
||||
status = acceptToken(&tokens, TT_FLOAT);
|
||||
if (!status) {
|
||||
error("expected float", tokens);
|
||||
parser_error(PR_EXPECTED_FLOAT, tokens);
|
||||
goto parseConstantNodeAbort;
|
||||
}
|
||||
}
|
||||
|
@ -1528,12 +1563,12 @@ ConstantNode *parseConstantNode(Token ***tokenp)
|
|||
/* This should succeed; it was checked for above */
|
||||
status = acceptToken(&tokens, TT_STRING);
|
||||
if (!status) {
|
||||
error("expected string", tokens);
|
||||
parser_error(PR_EXPECTED_STRING, tokens);
|
||||
goto parseConstantNodeAbort;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error("expected constant value", tokens);
|
||||
parser_error(PR_EXPECTED_CONSTANT, tokens);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -1625,7 +1660,7 @@ TypeNode *parseTypeNode(Token ***tokenp)
|
|||
if (!ret) goto parseTypeNodeAbort;
|
||||
}
|
||||
else {
|
||||
error("expected type", tokens);
|
||||
parser_error(PR_EXPECTED_TYPE, tokens);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -1698,7 +1733,7 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp)
|
|||
/* This should succeed; it was checked for above */
|
||||
status = acceptToken(&tokens, TT_IDENTIFIER);
|
||||
if (!status) {
|
||||
error("expected identifier", tokens);
|
||||
parser_error(PR_EXPECTED_IDENTIFIER, tokens);
|
||||
goto parseIdentifierNodeAbort;
|
||||
}
|
||||
}
|
||||
|
@ -1713,7 +1748,7 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp)
|
|||
data = expr;
|
||||
}
|
||||
else {
|
||||
error("expected identifier", tokens);
|
||||
parser_error(PR_EXPECTED_IDENTIFIER, tokens);
|
||||
}
|
||||
|
||||
/* Check if there is a slot access */
|
||||
|
@ -1781,7 +1816,7 @@ ExprNode *parseCastExprNode(Token ***tokenp)
|
|||
/* Parse the cast token */
|
||||
status = acceptToken(&tokens, TT_MAEK);
|
||||
if (!status) {
|
||||
error("expected MAEK", tokens);
|
||||
parser_error_expected_token(TT_MAEK, tokens);
|
||||
goto parseCastExprNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -1951,7 +1986,7 @@ ExprNode *parseFuncCallExprNode(Token ***tokenp)
|
|||
/* Parse the function call token */
|
||||
status = acceptToken(&tokens, TT_IZ);
|
||||
if (!status) {
|
||||
error("expected IZ", tokens);
|
||||
parser_error_expected_token(TT_IZ, tokens);
|
||||
goto parseFuncCallExprNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -1990,7 +2025,7 @@ ExprNode *parseFuncCallExprNode(Token ***tokenp)
|
|||
/* Parse the end-of-argument token */
|
||||
status = acceptToken(&tokens, TT_MKAY);
|
||||
if (!status) {
|
||||
error("expected MKAY", tokens);
|
||||
parser_error_expected_token(TT_MKAY, tokens);
|
||||
goto parseFuncCallExprNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2167,7 +2202,7 @@ ExprNode *parseOpExprNode(Token ***tokenp)
|
|||
#endif
|
||||
}
|
||||
else {
|
||||
error("invalid operator", tokens);
|
||||
parser_error(PR_INVALID_OPERATOR, tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2338,7 +2373,7 @@ ExprNode *parseExprNode(Token ***tokenp)
|
|||
*tokenp = tokens;
|
||||
}
|
||||
else {
|
||||
error("expected expression", tokens);
|
||||
parser_error(PR_EXPECTED_EXPRESSION, tokens);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -2381,7 +2416,7 @@ StmtNode *parseCastStmtNode(Token ***tokenp)
|
|||
/* Remove the cast keywords from the token stream */
|
||||
status = acceptToken(&tokens, TT_ISNOWA);
|
||||
if (!status) {
|
||||
error("expected IS NOW A", tokens);
|
||||
parser_error_expected_token(TT_ISNOWA, tokens);
|
||||
goto parseCastStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2392,7 +2427,7 @@ StmtNode *parseCastStmtNode(Token ***tokenp)
|
|||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseCastStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2452,7 +2487,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
/* Remove the print keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_VISIBLE);
|
||||
if (!status) {
|
||||
error("expected VISIBLE", tokens);
|
||||
parser_error_expected_token(TT_VISIBLE, tokens);
|
||||
goto parsePrintStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2480,7 +2515,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parsePrintStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2538,7 +2573,7 @@ StmtNode *parseInputStmtNode(Token ***tokenp)
|
|||
/* Remove the input keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_GIMMEH);
|
||||
if (!status) {
|
||||
error("expected GIMMEH", tokens);
|
||||
parser_error_expected_token(TT_GIMMEH, tokens);
|
||||
goto parseInputStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2549,7 +2584,7 @@ StmtNode *parseInputStmtNode(Token ***tokenp)
|
|||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseInputStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2610,7 +2645,7 @@ StmtNode *parseAssignmentStmtNode(Token ***tokenp)
|
|||
|
||||
/* Remove the assignment keyword from the token stream */
|
||||
if (!acceptToken(&tokens, TT_R)) {
|
||||
error("expected R", tokens);
|
||||
parser_error_expected_token(TT_R, tokens);
|
||||
goto parseAssignmentStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2621,7 +2656,7 @@ StmtNode *parseAssignmentStmtNode(Token ***tokenp)
|
|||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseAssignmentStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2686,7 +2721,7 @@ StmtNode *parseDeclarationStmtNode(Token ***tokenp)
|
|||
|
||||
/* Remove the declaration keywords from the token stream */
|
||||
if (!acceptToken(&tokens, TT_HASA)) {
|
||||
error("expected HAS A", tokens);
|
||||
parser_error_expected_token(TT_HASA, tokens);
|
||||
goto parseDeclarationStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2716,7 +2751,7 @@ StmtNode *parseDeclarationStmtNode(Token ***tokenp)
|
|||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseDeclarationStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2781,27 +2816,27 @@ StmtNode *parseIfThenElseStmtNode(Token ***tokenp)
|
|||
/* Remove the if keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_ORLY);
|
||||
if (!status) {
|
||||
error("expected O RLY?", tokens);
|
||||
parser_error_expected_token(TT_ORLY, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The if keyword must appear on its own line */
|
||||
if (!acceptToken(&tokens, TT_NEWLINE)) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Parse the true branch keyword */
|
||||
status = acceptToken(&tokens, TT_YARLY);
|
||||
if (!status) {
|
||||
error("expected YA RLY", tokens);
|
||||
parser_error_expected_token(TT_YARLY, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The true branch keyword must appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2829,7 +2864,7 @@ StmtNode *parseIfThenElseStmtNode(Token ***tokenp)
|
|||
/* The else-if keyword and guard must be on their own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2848,7 +2883,7 @@ StmtNode *parseIfThenElseStmtNode(Token ***tokenp)
|
|||
/* The else keyword must appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2860,14 +2895,14 @@ StmtNode *parseIfThenElseStmtNode(Token ***tokenp)
|
|||
/* Parse the end-if-block keyword */
|
||||
status = acceptToken(&tokens, TT_OIC);
|
||||
if (!status) {
|
||||
error("expected OIC", tokens);
|
||||
parser_error_expected_token(TT_OIC, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The end-if-block keyword must appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseIfThenElseStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2934,14 +2969,14 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
/* Remove the switch keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_WTF);
|
||||
if (!status) {
|
||||
error("expected WTF?", tokens);
|
||||
parser_error_expected_token(TT_WTF, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The switch keyword must appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2958,7 +2993,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
/* Parse the case keyword */
|
||||
status = acceptToken(&tokens, TT_OMG);
|
||||
if (!status) {
|
||||
error("expected OMG", tokens);
|
||||
parser_error_expected_token(TT_OMG, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2971,7 +3006,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
|
||||
/* String interpolation is not allowed */
|
||||
if (c->type == CT_STRING && strstr(c->data.s, ":{")) {
|
||||
error("cannot use an interpolated string as an OMG literal", tokens);
|
||||
parser_error(PR_CANNOT_USE_STR_AS_LITERAL, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -2986,7 +3021,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
&& fabs(c->data.f - test->data.f) < FLT_EPSILON)
|
||||
|| (c->type == CT_STRING
|
||||
&& !strcmp(c->data.s, test->data.s))) {
|
||||
error("OMG literal must be unique", tokens);
|
||||
parser_error(PR_LITERAL_MUST_BE_UNIQUE, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
}
|
||||
|
@ -3003,7 +3038,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
/* Make sure the guard appears on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3022,7 +3057,7 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
/* Make sure the default case keyword appears on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3034,14 +3069,14 @@ StmtNode *parseSwitchStmtNode(Token ***tokenp)
|
|||
/* Parse the end-switch keyword */
|
||||
status = acceptToken(&tokens, TT_OIC);
|
||||
if (!status) {
|
||||
error("expected OIC", tokens);
|
||||
parser_error_expected_token(TT_OIC, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Make sure the end-switch keyword appears on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseSwitchStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3101,14 +3136,14 @@ StmtNode *parseBreakStmtNode(Token ***tokenp)
|
|||
/* Remove the break keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_GTFO);
|
||||
if (!status) {
|
||||
error("expected GTFO", tokens);
|
||||
parser_error_expected_token(TT_GTFO, tokens);
|
||||
goto parseBreakStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The break keyword must appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseBreakStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3156,7 +3191,7 @@ StmtNode *parseReturnStmtNode(Token ***tokenp)
|
|||
/* Remove the return keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_FOUNDYR);
|
||||
if (!status) {
|
||||
error("expected FOUND YR", tokens);
|
||||
parser_error_expected_token(TT_FOUNDYR, tokens);
|
||||
goto parseReturnStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3167,7 +3202,7 @@ StmtNode *parseReturnStmtNode(Token ***tokenp)
|
|||
/* The return statement must reside on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseReturnStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3250,7 +3285,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* Remove the loop-start keyword from the token stream */
|
||||
status = acceptToken(&tokens, TT_IMINYR);
|
||||
if (!status) {
|
||||
error("expected IM IN YR", tokens);
|
||||
parser_error_expected_token(TT_IMINYR, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3258,7 +3293,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
name1 = parseIdentifierNode(&tokens);
|
||||
if (!name1) goto parseLoopStmtNodeAbort;
|
||||
else if (name1->type != IT_DIRECT) {
|
||||
error("expected loop name", tokens);
|
||||
parser_error(PR_EXPECTED_LOOP_NAME, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3282,13 +3317,13 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
#endif
|
||||
}
|
||||
else {
|
||||
error("expected UPPIN or NERFIN", tokens);
|
||||
parser_error_expected_either_token(TT_UPPIN, TT_NERFIN, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Parse the required syntax */
|
||||
if (!acceptToken(&tokens, TT_YR)) {
|
||||
error("expected YR", tokens);
|
||||
parser_error_expected_token(TT_YR, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3354,7 +3389,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* Parse the function indicator */
|
||||
status = acceptToken(&tokens, TT_IZ);
|
||||
if (!status) {
|
||||
error("expected IZ", tokens);
|
||||
parser_error_expected_token(TT_IZ, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3369,7 +3404,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* Check for unary function */
|
||||
status = acceptToken(&tokens, TT_YR);
|
||||
if (!status) {
|
||||
error("expected unary function", tokens);
|
||||
parser_error(PR_EXPECTED_UNARY_FUNCTION, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3379,7 +3414,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
|
||||
/* Make sure the argument is an identifier */
|
||||
if (arg->type != ET_IDENTIFIER) {
|
||||
error("expected identifier", tokens);
|
||||
parser_error(PR_EXPECTED_IDENTIFIER, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3401,7 +3436,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* Check for unary function */
|
||||
status = acceptToken(&tokens, TT_MKAY);
|
||||
if (!status) {
|
||||
error("expected MKAY", tokens);
|
||||
parser_error_expected_token(TT_MKAY, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3456,7 +3491,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* All of the above should be on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3467,7 +3502,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* Parse the end-loop keywords */
|
||||
status = acceptToken(&tokens, TT_IMOUTTAYR);
|
||||
if (!status) {
|
||||
error("expected IM OUTTA YR", tokens);
|
||||
parser_error_expected_token(TT_IMOUTTAYR, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3475,13 +3510,13 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
name2 = parseIdentifierNode(&tokens);
|
||||
if (!name2) goto parseLoopStmtNodeAbort;
|
||||
else if (name2->type != IT_DIRECT) {
|
||||
error("expected loop name", tokens);
|
||||
parser_error(PR_EXPECTED_LOOP_NAME, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Make sure the beginning-of-loop and end-of-loop names match */
|
||||
if (strcmp((char *)(name1->id), (char *)(name2->id))) {
|
||||
error("expected matching loop name", tokens);
|
||||
parser_error(PR_EXPECTED_MATCHING_LOOP_NAME, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3491,7 +3526,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp)
|
|||
/* The end-of-loop structure should appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
goto parseLoopStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3577,14 +3612,14 @@ StmtNode *parseDeallocationStmtNode(Token ***tokenp)
|
|||
/* Parse the deallocation token */
|
||||
status = acceptToken(&tokens, TT_RNOOB);
|
||||
if (!status) {
|
||||
error("expected R NOOB", tokens);
|
||||
parser_error_expected_token(TT_RNOOB, tokens);
|
||||
goto parseDeallocationStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The deallocation statement must reside on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseDeallocationStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3645,7 +3680,7 @@ StmtNode *parseFuncDefStmtNode(Token ***tokenp)
|
|||
/* Parse the function definition token */
|
||||
status = acceptToken(&tokens, TT_HOWIZ);
|
||||
if (!status) {
|
||||
error("expected HOW IZ", tokens);
|
||||
parser_error_expected_token(TT_HOWIZ, tokens);
|
||||
goto parseFuncDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3688,7 +3723,7 @@ StmtNode *parseFuncDefStmtNode(Token ***tokenp)
|
|||
/* The function declaration should appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseFuncDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3699,14 +3734,14 @@ StmtNode *parseFuncDefStmtNode(Token ***tokenp)
|
|||
/* Parse the end-function token */
|
||||
status = acceptToken(&tokens, TT_IFUSAYSO);
|
||||
if (!status) {
|
||||
error("expected IF YOU SAY SO", tokens);
|
||||
parser_error_expected_token(TT_IFUSAYSO, tokens);
|
||||
goto parseFuncDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The end-function token should appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseFuncDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3769,7 +3804,7 @@ StmtNode *parseAltArrayDefStmtNode(Token ***tokenp)
|
|||
/* Parse the alternate array definition token */
|
||||
status = acceptToken(&tokens, TT_OHAIIM);
|
||||
if (!status) {
|
||||
error("expected O HAI IM", tokens);
|
||||
parser_error_expected_token(TT_OHAIIM, tokens);
|
||||
goto parseAltArrayDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3788,7 +3823,7 @@ StmtNode *parseAltArrayDefStmtNode(Token ***tokenp)
|
|||
* own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseAltArrayDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3800,14 +3835,14 @@ StmtNode *parseAltArrayDefStmtNode(Token ***tokenp)
|
|||
* line */
|
||||
status = acceptToken(&tokens, TT_KTHX);
|
||||
if (!status) {
|
||||
error("expected KTHX", tokens);
|
||||
parser_error_expected_token(TT_KTHX, tokens);
|
||||
goto parseAltArrayDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* The end-function token should appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseAltArrayDefStmtNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -3903,7 +3938,7 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
|||
|
||||
/* The expression should appear on its own line */
|
||||
if (!acceptToken(&tokens, TT_NEWLINE)) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
deleteExprNode(expr);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3966,7 +4001,7 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
|||
/* The expression should appear on its own line */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of expression", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_EXPRESSION, tokens);
|
||||
deleteExprNode(expr);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3982,7 +4017,7 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
|||
*tokenp = tokens;
|
||||
}
|
||||
else {
|
||||
error("expected statement", tokens);
|
||||
parser_error(PR_EXPECTED_STATEMENT, tokens);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -4088,7 +4123,7 @@ MainNode *parseMainNode(Token **tokens)
|
|||
/* All programs must start with the HAI token */
|
||||
status = acceptToken(&tokens, TT_HAI);
|
||||
if (!status) {
|
||||
error("expected HAI", tokens);
|
||||
parser_error_expected_token(TT_HAI, tokens);
|
||||
goto parseMainNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -4102,7 +4137,7 @@ MainNode *parseMainNode(Token **tokens)
|
|||
/* Make sure the header line ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
if (!status) {
|
||||
error("expected end of statement", tokens);
|
||||
parser_error(PR_EXPECTED_END_OF_STATEMENT, tokens);
|
||||
goto parseMainNodeAbort;
|
||||
}
|
||||
|
||||
|
@ -4113,7 +4148,7 @@ MainNode *parseMainNode(Token **tokens)
|
|||
/* Make sure the program ends with KTHXBYE */
|
||||
status = acceptToken(&tokens, TT_KTHXBYE);
|
||||
if (!status) {
|
||||
error("expected KTHXBYE", tokens);
|
||||
parser_error_expected_token(TT_KTHXBYE, tokens);
|
||||
goto parseMainNodeAbort;
|
||||
}
|
||||
|
||||
|
|
88
tokenizer.c
88
tokenizer.c
|
@ -1,81 +1,5 @@
|
|||
#include "tokenizer.h"
|
||||
|
||||
static const char *keywords[] = {
|
||||
"", /* TT_INTEGER */
|
||||
"", /* TT_FLOAT */
|
||||
"", /* TT_STRING */
|
||||
"", /* TT_IDENTIFIER */
|
||||
"", /* TT_BOOLEAN */
|
||||
"IT", /* TT_IT */
|
||||
"ITZ LIEK A", /* TT_ITZLIEKA */
|
||||
"NOOB", /* TT_NOOB */
|
||||
"NUMBR", /* TT_NUMBR */
|
||||
"NUMBAR", /* TT_NUMBAR */
|
||||
"TROOF", /* TT_TROOF */
|
||||
"YARN", /* TT_YARN */
|
||||
"BUKKIT", /* TT_BUKKIT */
|
||||
"", /* TT_EOF */
|
||||
"", /* TT_NEWLINE */
|
||||
"HAI", /* TT_HAI */
|
||||
"KTHXBYE", /* TT_KTHXBYE */
|
||||
"HAS A", /* TT_HASA */
|
||||
"ITZ A", /* TT_ITZA */
|
||||
"ITZ", /* TT_ITZ */
|
||||
"R NOOB", /* TT_RNOOB */
|
||||
"R", /* TT_R */
|
||||
"AN YR", /* TT_ANYR */
|
||||
"AN", /* TT_AN */
|
||||
"SUM OF", /* TT_SUMOF */
|
||||
"DIFF OF", /* TT_DIFFOF */
|
||||
"PRODUKT OF", /* TT_PRODUKTOF */
|
||||
"QUOSHUNT OF", /* TT_QUOSHUNTOF */
|
||||
"MOD OF", /* TT_MODOF */
|
||||
"BIGGR OF", /* TT_BIGGROF */
|
||||
"SMALLR OF", /* TT_SMALLROF */
|
||||
"BOTH OF", /* TT_BOTHOF */
|
||||
"EITHER OF", /* TT_EITHEROF */
|
||||
"WON OF", /* TT_WONOF */
|
||||
"NOT", /* TT_NOT */
|
||||
"MKAY", /* TT_MKAY */
|
||||
"ALL OF", /* TT_ALLOF */
|
||||
"ANY OF", /* TT_ANYOF */
|
||||
"BOTH SAEM", /* TT_BOTHSAEM */
|
||||
"DIFFRINT", /* TT_DIFFRINT */
|
||||
"MAEK", /* TT_MAEK */
|
||||
"A", /* TT_A */
|
||||
"IS NOW A", /* TT_ISNOWA */
|
||||
"VISIBLE", /* TT_VISIBLE */
|
||||
"SMOOSH", /* TT_SMOOSH */
|
||||
"!", /* TT_BANG */
|
||||
"GIMMEH", /* TT_GIMMEH */
|
||||
"O RLY?", /* TT_ORLY */
|
||||
"YA RLY", /* TT_YARLY */
|
||||
"MEBBE", /* TT_MEBBE */
|
||||
"NO WAI", /* TT_NOWAI */
|
||||
"OIC", /* TT_OIC */
|
||||
"WTF?", /* TT_WTF */
|
||||
"OMG", /* TT_OMG */
|
||||
"OMGWTF", /* TT_OMGWTF */
|
||||
"GTFO", /* TT_GTFO */
|
||||
"IM IN YR", /* TT_IMINYR */
|
||||
"UPPIN", /* TT_UPPIN */
|
||||
"NERFIN", /* TT_NERFIN */
|
||||
"YR", /* TT_YR */
|
||||
"TIL", /* TT_TIL */
|
||||
"WILE", /* TT_WILE */
|
||||
"IM OUTTA YR", /* TT_IMOUTTAYR */
|
||||
"HOW IZ", /* TT_HOWIZ */
|
||||
"IZ", /* TT_IZ */
|
||||
"IF U SAY SO", /* TT_IFUSAYSO */
|
||||
"FOUND YR", /* TT_FOUNDYR */
|
||||
"SRS", /* TT_SRS */
|
||||
"'Z", /* TT_APOSTROPHEZ */
|
||||
"O HAI IM", /* TT_OHAIIM */
|
||||
"IM LIEK", /* TT_IMLIEK */
|
||||
"KTHX", /* TT_KTHX */
|
||||
"" /* TT_ENDOFTOKENS */
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a string follows the format for an integer. Specifically, it
|
||||
* checks if the string matches the regular expression: (-?[1-9][0-9]*|0).
|
||||
|
@ -376,16 +300,14 @@ Token **tokenizeLexemes(LexemeList *list)
|
|||
/* Float */
|
||||
else if (isFloat(image)) {
|
||||
token = createToken(TT_FLOAT, image, fname, line);
|
||||
if (sscanf(lexeme->image, "%f", &(token->data.f)) != 1) {
|
||||
fprintf(stderr, "Expected floating point decimal value.\n");
|
||||
}
|
||||
if (sscanf(lexeme->image, "%f", &(token->data.f)) != 1)
|
||||
error2(TK_EXPECTED_FLOATING_POINT, fname, line);
|
||||
}
|
||||
/* Integer */
|
||||
else if (isInteger(image)) {
|
||||
token = createToken(TT_INTEGER, image, fname, line);
|
||||
if (sscanf(lexeme->image, "%i", &(token->data.i)) != 1) {
|
||||
fprintf(stderr, "Expected integer value.\n");
|
||||
}
|
||||
if (sscanf(lexeme->image, "%i", &(token->data.i)) != 1)
|
||||
error2(TK_EXPECTED_INTEGER, fname, line);
|
||||
}
|
||||
/* FAIL */
|
||||
else if (!strcmp(image, "FAIL")) {
|
||||
|
@ -441,7 +363,7 @@ Token **tokenizeLexemes(LexemeList *list)
|
|||
token = createToken(TT_EOF, "end of file", fname, line);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s:%u: unknown token at: %s\n", fname, line, image);
|
||||
error2(TK_UNKNOWN_TOKEN, fname, line, image);
|
||||
/* Clean up */
|
||||
deleteToken(ret[retsize - 1]);
|
||||
ret[retsize - 1] = NULL;
|
||||
|
|
83
tokenizer.h
83
tokenizer.h
|
@ -20,6 +20,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "lexer.h"
|
||||
#include "error.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
|
@ -28,8 +29,7 @@
|
|||
* the semantic type of token data or the lexemes which make up the particular
|
||||
* token.
|
||||
*
|
||||
* \note Remember to update the keywords array (in the tokens C file) with the
|
||||
* token image.
|
||||
* \note Remember to update the keywords array (below) with the token image.
|
||||
*/
|
||||
typedef enum {
|
||||
TT_INTEGER, /**< Integer literal. */
|
||||
|
@ -104,9 +104,86 @@ typedef enum {
|
|||
TT_OHAIIM, /**< Alternate array declaration. */
|
||||
TT_IMLIEK, /**< Alternate inherited object declaration. */
|
||||
TT_KTHX, /**< End of alternate array declaration. */
|
||||
TT_ENDOFTOKENS /**< The end of this enum -- don't move it! */
|
||||
|
||||
TT_ENDOFTOKENS /**< Sentinel end of this enum -- don't move it! */
|
||||
} TokenType;
|
||||
|
||||
static const char *keywords[] = {
|
||||
"", /* TT_INTEGER */
|
||||
"", /* TT_FLOAT */
|
||||
"", /* TT_STRING */
|
||||
"", /* TT_IDENTIFIER */
|
||||
"", /* TT_BOOLEAN */
|
||||
"IT", /* TT_IT */
|
||||
"ITZ LIEK A", /* TT_ITZLIEKA */
|
||||
"NOOB", /* TT_NOOB */
|
||||
"NUMBR", /* TT_NUMBR */
|
||||
"NUMBAR", /* TT_NUMBAR */
|
||||
"TROOF", /* TT_TROOF */
|
||||
"YARN", /* TT_YARN */
|
||||
"BUKKIT", /* TT_BUKKIT */
|
||||
"", /* TT_EOF */
|
||||
"", /* TT_NEWLINE */
|
||||
"HAI", /* TT_HAI */
|
||||
"KTHXBYE", /* TT_KTHXBYE */
|
||||
"HAS A", /* TT_HASA */
|
||||
"ITZ A", /* TT_ITZA */
|
||||
"ITZ", /* TT_ITZ */
|
||||
"R NOOB", /* TT_RNOOB */
|
||||
"R", /* TT_R */
|
||||
"AN YR", /* TT_ANYR */
|
||||
"AN", /* TT_AN */
|
||||
"SUM OF", /* TT_SUMOF */
|
||||
"DIFF OF", /* TT_DIFFOF */
|
||||
"PRODUKT OF", /* TT_PRODUKTOF */
|
||||
"QUOSHUNT OF", /* TT_QUOSHUNTOF */
|
||||
"MOD OF", /* TT_MODOF */
|
||||
"BIGGR OF", /* TT_BIGGROF */
|
||||
"SMALLR OF", /* TT_SMALLROF */
|
||||
"BOTH OF", /* TT_BOTHOF */
|
||||
"EITHER OF", /* TT_EITHEROF */
|
||||
"WON OF", /* TT_WONOF */
|
||||
"NOT", /* TT_NOT */
|
||||
"MKAY", /* TT_MKAY */
|
||||
"ALL OF", /* TT_ALLOF */
|
||||
"ANY OF", /* TT_ANYOF */
|
||||
"BOTH SAEM", /* TT_BOTHSAEM */
|
||||
"DIFFRINT", /* TT_DIFFRINT */
|
||||
"MAEK", /* TT_MAEK */
|
||||
"A", /* TT_A */
|
||||
"IS NOW A", /* TT_ISNOWA */
|
||||
"VISIBLE", /* TT_VISIBLE */
|
||||
"SMOOSH", /* TT_SMOOSH */
|
||||
"!", /* TT_BANG */
|
||||
"GIMMEH", /* TT_GIMMEH */
|
||||
"O RLY?", /* TT_ORLY */
|
||||
"YA RLY", /* TT_YARLY */
|
||||
"MEBBE", /* TT_MEBBE */
|
||||
"NO WAI", /* TT_NOWAI */
|
||||
"OIC", /* TT_OIC */
|
||||
"WTF?", /* TT_WTF */
|
||||
"OMG", /* TT_OMG */
|
||||
"OMGWTF", /* TT_OMGWTF */
|
||||
"GTFO", /* TT_GTFO */
|
||||
"IM IN YR", /* TT_IMINYR */
|
||||
"UPPIN", /* TT_UPPIN */
|
||||
"NERFIN", /* TT_NERFIN */
|
||||
"YR", /* TT_YR */
|
||||
"TIL", /* TT_TIL */
|
||||
"WILE", /* TT_WILE */
|
||||
"IM OUTTA YR", /* TT_IMOUTTAYR */
|
||||
"HOW IZ", /* TT_HOWIZ */
|
||||
"IZ", /* TT_IZ */
|
||||
"IF U SAY SO", /* TT_IFUSAYSO */
|
||||
"FOUND YR", /* TT_FOUNDYR */
|
||||
"SRS", /* TT_SRS */
|
||||
"'Z", /* TT_APOSTROPHEZ */
|
||||
"O HAI IM", /* TT_OHAIIM */
|
||||
"IM LIEK", /* TT_IMLIEK */
|
||||
"KTHX", /* TT_KTHX */
|
||||
"" /* TT_ENDOFTOKENS */
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores token data with semantic meaning.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue