New fancy error reporting feature makes nice error messages

git-svn-id: http://picoc.googlecode.com/svn/trunk@330 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-06-04 07:41:06 +00:00
parent 2a69c48777
commit 3a1e39f9d3
8 changed files with 188 additions and 75 deletions

View file

@ -1,5 +1,5 @@
CC=gcc
CFLAGS=-Wall -pedantic -g -DUNIX_HOST #-DDEBUG_HEAP #-DDEBUG_EXPRESSIONS #-DDEBUG_LEXER
CFLAGS=-Wall -pedantic -g -DUNIX_HOST
LIBS=#-lm
TARGET = picoc
@ -18,7 +18,7 @@ clean:
rm -f $(TARGET) $(OBJS) *~
count:
cat picoc.h picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
cat picoc.h picoc.c table.c lex.c parse.c expression.c platform.c heap.c type.c variable.c | grep -v '^[ ]*/\*' | grep -v '^[ ]*$$' | wc
depend:
$(CC) -MM $(SRCS) >.depend

View file

@ -21,7 +21,7 @@ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct Libr
for (Count = 0; (*FuncList)[Count].Prototype != NULL; Count++)
{
Tokens = LexAnalyse(IntrinsicName, (*FuncList)[Count].Prototype, strlen((char *)(*FuncList)[Count].Prototype), NULL);
LexInitParser(&Parser, Tokens, IntrinsicName, Count+1, TRUE);
LexInitParser(&Parser, (*FuncList)[Count].Prototype, Tokens, IntrinsicName, TRUE);
TypeParse(&Parser, &ReturnType, &Identifier);
NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier, TRUE);
NewValue->Val->FuncDef.Intrinsic = (*FuncList)[Count].Func;

View file

@ -163,6 +163,10 @@ void ExpressionStackPushValueNode(struct ParseState *Parser, struct ExpressionSt
StackNode->Next = *StackTop;
StackNode->p.Val = ValueLoc;
*StackTop = StackNode;
#ifdef FANCY_ERROR_MESSAGES
StackNode->Line = Parser->Line;
StackNode->CharacterPos = Parser->CharacterPos;
#endif
#ifdef DEBUG_EXPRESSIONS
ExpressionStackShow(*StackTop);
#endif
@ -217,22 +221,6 @@ void ExpressionPushFP(struct ParseState *Parser, struct ExpressionStack **StackT
}
#endif
/* like ProgramFail() but gives descriptive error messages for assignment */
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo)
{
PlatformPrintf("%s:%d: can't %s ", Parser->FileName, Parser->Line, (FuncName == NULL) ? "assign" : "set");
if (Type1 != NULL)
PlatformPrintf(Format, Type1, Type2);
else
PlatformPrintf(Format, Num1, Num2);
if (FuncName != NULL)
PlatformPrintf(" in argument %d of call to %s()", ParamNo, FuncName);
ProgramFail(NULL, "");
}
/* assign to a pointer, leaving a value on the expression stack */
void ExpressionAssignToPointer(struct ParseState *Parser, struct Value *ToValue, struct Value *FromValue, const char *FuncName, int ParamNo)
{
@ -876,6 +864,10 @@ void ExpressionStackPushOperator(struct ParseState *Parser, struct ExpressionSta
StackNode->Precedence = Precedence;
*StackTop = StackNode;
debugf("ExpressionStackPushOperator()\n");
#ifdef FANCY_ERROR_MESSAGES
StackNode->Line = Parser->Line;
StackNode->CharacterPos = Parser->CharacterPos;
#endif
#ifdef DEBUG_EXPRESSIONS
ExpressionStackShow(*StackTop);
#endif

134
lex.c
View file

@ -13,11 +13,21 @@
#define IS_BASE_DIGIT(c,b) (((c) >= '0' && (c) < '0' + (((b)<10)?(b):10)) || (((b) > 10) ? IS_HEX_ALPHA_DIGIT(c) : FALSE))
#define GET_BASE_DIGIT(c) (((c) <= '9') ? ((c) - '0') : (((c) <= 'F') ? ((c) - 'A' + 10) : ((c) - 'a' + 10)))
#define NEXTIS(c,x,y) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else GotToken = (y); }
#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else NEXTIS(d,y,z) }
#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else NEXTIS3(d,y,e,z,a) }
#define NEXTIS3PLUS(c,x,d,y,e,z,a) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else if (NextChar == (d)) { if (Lexer->Pos[1] == (e)) { Lexer->Pos += 2; GotToken = (z); } else { Lexer->Pos++; GotToken = (y); } } else GotToken = (a); }
#define NEXTISEXACTLY3(c,d,y,z) { if (NextChar == (c) && Lexer->Pos[1] == (d)) { Lexer->Pos += 2; GotToken = (y); } else GotToken = (z); }
#define NEXTIS(c,x,y) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else GotToken = (y); }
#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS(d,y,z) }
#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else NEXTIS3(d,y,e,z,a) }
#define NEXTIS3PLUS(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXER_INC(Lexer); GotToken = (x); } else if (NextChar == (d)) { if (Lexer->Pos[1] == (e)) { LEXER_INCN(Lexer, 2); GotToken = (z); } else { LEXER_INC(Lexer); GotToken = (y); } } else GotToken = (a); }
#define NEXTISEXACTLY3(c,d,y,z) { if (NextChar == (c) && Lexer->Pos[1] == (d)) { LEXER_INCN(Lexer, 2); GotToken = (y); } else GotToken = (z); }
#ifdef FANCY_ERROR_REPORTING
#define LEXER_INC(l) ( (l)->Pos++, (l)->CharacterPos++ )
#define LEXER_INCN(l, n) ( (l)->Pos+=(n), (l)->CharacterPos+=(n) )
#define TOKEN_DATA_OFFSET 2
#else
#define LEXER_INC(l) (l)->Pos++
#define LEXER_INCN(l, n) (l)->Pos+=(n)
#define TOKEN_DATA_OFFSET 1
#endif
#define MAX_CHAR_VALUE 255 /* maximum value which can be represented by a "char" data type */
@ -110,19 +120,6 @@ enum LexToken LexCheckReservedWord(const char *Word)
return TokenNone;
}
int IsBaseDigit(unsigned char c, int b)
{
if (c >= '0' && c < '0' + b)
return TRUE;
else
{
if (b > 10)
return IS_HEX_ALPHA_DIGIT(c);
}
return FALSE;
}
/* get a numeric literal - used while scanning */
enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value)
{
@ -137,20 +134,20 @@ enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value)
if (*Lexer->Pos == '0')
{
/* a binary, octal or hex literal */
Lexer->Pos++;
LEXER_INC(Lexer);
if (Lexer->Pos != Lexer->End)
{
if (*Lexer->Pos == 'x' || *Lexer->Pos == 'X')
{ Base = 16; Lexer->Pos++; }
{ Base = 16; LEXER_INC(Lexer); }
else if (*Lexer->Pos == 'b' || *Lexer->Pos == 'B')
{ Base = 2; Lexer->Pos++; }
{ Base = 2; LEXER_INC(Lexer); }
else if (*Lexer->Pos != '.')
Base = 8;
}
}
/* get the value */
for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); Lexer->Pos++)
for (; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer))
Result = Result * Base + GET_BASE_DIGIT(*Lexer->Pos);
if (Result <= MAX_CHAR_VALUE)
@ -170,14 +167,14 @@ enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value)
return ResultToken;
Value->Typ = &FPType;
Lexer->Pos++;
for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); Lexer->Pos++, FPDiv /= (double)Base)
LEXER_INC(Lexer);
for (FPDiv = 1.0/Base, FPResult = (double)Result; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer), FPDiv /= (double)Base)
FPResult += GET_BASE_DIGIT(*Lexer->Pos) * FPDiv;
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E'))
{
Lexer->Pos++;
for (Result = 0; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); Lexer->Pos++)
LEXER_INC(Lexer);
for (Result = 0; Lexer->Pos != Lexer->End && IS_BASE_DIGIT(*Lexer->Pos, Base); LEXER_INC(Lexer))
Result = Result * (double)Base + GET_BASE_DIGIT(*Lexer->Pos);
FPResult *= math_pow((double)Base, (double)Result);
@ -194,15 +191,15 @@ enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value)
/* get a reserved word or identifier - used while scanning */
enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
{
const char *Pos = Lexer->Pos + 1;
const char *StartPos = Lexer->Pos;
enum LexToken Token;
while (Lexer->Pos != Lexer->End && isCident(*Pos))
Pos++;
do {
LEXER_INC(Lexer);
} while (Lexer->Pos != Lexer->End && isCident(*Lexer->Pos));
Value->Typ = NULL;
Value->Val->Identifier = TableStrRegister2(Lexer->Pos, Pos - Lexer->Pos);
Lexer->Pos = Pos;
Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos);
Token = LexCheckReservedWord(Value->Val->Identifier);
if (Token != TokenNone)
@ -282,7 +279,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
else if (*Lexer->Pos == '\\')
Escape = TRUE;
Lexer->Pos++;
LEXER_INC(Lexer);
}
EndPos = Lexer->Pos;
@ -316,7 +313,7 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
Value->Val->NativePointer = ArrayValue;
#endif
if (*Lexer->Pos == '"')
Lexer->Pos++;
LEXER_INC(Lexer);
return TokenStringConstant;
}
@ -329,28 +326,28 @@ enum LexToken LexGetCharacterConstant(struct LexState *Lexer, struct Value *Valu
if (Lexer->Pos != Lexer->End && *Lexer->Pos != '\'')
LexFail(Lexer, "expected \"'\"");
Lexer->Pos++;
LEXER_INC(Lexer);
return TokenCharacterConstant;
}
/* skip a comment - used while scanning */
void LexSkipComment(struct LexState *Lexer, char NextChar)
{
Lexer->Pos++;
LEXER_INC(Lexer);
if (NextChar == '*')
{
/* conventional C comment */
while (Lexer->Pos != Lexer->End && (*(Lexer->Pos-1) != '*' || *Lexer->Pos != '/'))
Lexer->Pos++;
LEXER_INC(Lexer);
if (Lexer->Pos != Lexer->End)
Lexer->Pos++;
LEXER_INC(Lexer);
}
else
{
/* C++ style comment */
while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n')
Lexer->Pos++;
LEXER_INC(Lexer);
}
}
@ -370,10 +367,13 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
{
Lexer->Line++;
Lexer->Pos++;
#ifdef FANCY_ERROR_REPORTING
Lexer->CharacterPos = 0;
#endif
return TokenEndOfLine;
}
Lexer->Pos++;
LEXER_INC(Lexer);
}
if (Lexer->Pos == Lexer->End || *Lexer->Pos == '\0')
@ -387,7 +387,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
return LexGetNumber(Lexer, *Value);
NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0;
Lexer->Pos++;
LEXER_INC(Lexer);
switch (ThisChar)
{
case '"': GotToken = LexGetStringConstant(Lexer, *Value); break;
@ -444,9 +444,17 @@ void *LexTokenise(struct LexState *Lexer, int *TokenLen)
struct Value *GotValue;
int MemUsed = 0;
int ValueSize;
#ifdef FANCY_ERROR_REPORTING
int ReserveSpace = (Lexer->End - Lexer->Pos) * 4 + 1;
#else
int ReserveSpace = (Lexer->End - Lexer->Pos) * 3 + 1;
#endif
void *TokenSpace = HeapAllocStack(ReserveSpace);
char *TokenPos = (char *)TokenSpace;
#ifdef FANCY_ERROR_REPORTING
int LastCharacterPos = 0;
#endif
if (TokenSpace == NULL)
LexFail(Lexer, "out of memory");
@ -461,6 +469,12 @@ void *LexTokenise(struct LexState *Lexer, int *TokenLen)
TokenPos++;
MemUsed++;
#ifdef FANCY_ERROR_REPORTING
*(unsigned char *)TokenPos = (unsigned char)LastCharacterPos;
TokenPos++;
MemUsed++;
#endif
ValueSize = LexTokenSize(Token);
if (ValueSize > 0)
{
@ -470,19 +484,24 @@ void *LexTokenise(struct LexState *Lexer, int *TokenLen)
MemUsed += ValueSize;
}
#ifdef FANCY_ERROR_REPORTING
LastCharacterPos = Lexer->CharacterPos;
#endif
} while (Token != TokenEOF);
HeapMem = HeapAllocMem(MemUsed);
if (HeapMem == NULL)
LexFail(Lexer, "out of memory");
assert(ReserveSpace >= MemUsed);
memcpy(HeapMem, TokenSpace, MemUsed);
HeapPopStack(TokenSpace, ReserveSpace);
#ifdef DEBUG_LEXER
{
int Count;
for (Count = 0; Count < MemUsed; Count++)
printf("%02x ", *(unsigned char *)(HeapMem+Count));
printf("%02x ", *((unsigned char *)HeapMem+Count));
printf("\n");
}
#endif
@ -501,17 +520,25 @@ void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *T
Lexer.End = Source + SourceLen;
Lexer.Line = 1;
Lexer.FileName = FileName;
#ifdef FANCY_ERROR_REPORTING
Lexer.CharacterPos = 1;
Lexer.SourceText = Source;
#endif
return LexTokenise(&Lexer, TokenLen);
}
/* prepare to parse a pre-tokenised buffer */
void LexInitParser(struct ParseState *Parser, void *TokenSource, const char *FileName, int Line, int RunIt)
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt)
{
Parser->Pos = TokenSource;
Parser->Line = Line;
Parser->Line = 1;
Parser->FileName = FileName;
Parser->Mode = RunIt ? RunModeRun : RunModeSkip;
Parser->SearchLabel = 0;
#ifdef FANCY_ERROR_REPORTING
Parser->CharacterPos = 0;
Parser->SourceText = SourceText;
#endif
}
/* get the next token given a parser state */
@ -532,7 +559,7 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
while ((Token = (enum LexToken)*(unsigned char *)Parser->Pos) == TokenEndOfLine)
{
Parser->Line++;
Parser->Pos++;
Parser->Pos += TOKEN_DATA_OFFSET;
}
}
@ -544,7 +571,7 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
int LineBytes;
struct TokenLine *LineNode;
if (InteractiveHead == NULL || (unsigned char *)Parser->Pos == &InteractiveTail->Tokens[InteractiveTail->NumBytes-1])
if (InteractiveHead == NULL || (unsigned char *)Parser->Pos == &InteractiveTail->Tokens[InteractiveTail->NumBytes-TOKEN_DATA_OFFSET])
{
/* get interactive input */
if (LexUseStatementPrompt)
@ -568,6 +595,7 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
/* start a new list */
InteractiveHead = LineNode;
Parser->Line = 1;
Parser->CharacterPos = 0;
}
else
InteractiveTail->Next = LineNode;
@ -579,10 +607,10 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
else
{
/* go to the next token line */
if (Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-1])
if (Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET])
{
/* scan for the line */
for (InteractiveCurrentLine = InteractiveHead; Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-1]; InteractiveCurrentLine = InteractiveCurrentLine->Next)
for (InteractiveCurrentLine = InteractiveHead; Parser->Pos != &InteractiveCurrentLine->Tokens[InteractiveCurrentLine->NumBytes-TOKEN_DATA_OFFSET]; InteractiveCurrentLine = InteractiveCurrentLine->Next)
{}
}
@ -594,6 +622,10 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
}
} while ((Parser->FileName == StrEmpty && Token == TokenEOF) || Token == TokenEndOfLine);
#ifdef FANCY_ERROR_REPORTING
Parser->CharacterPos = *((unsigned char *)Parser->Pos + 1);
#endif
ValueSize = LexTokenSize(Token);
if (ValueSize > 0)
{
@ -612,7 +644,7 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
default: break;
}
memcpy((void *)LexValue.Val, (void *)((char *)Parser->Pos+1), ValueSize);
memcpy((void *)LexValue.Val, (void *)((char *)Parser->Pos + TOKEN_DATA_OFFSET), ValueSize);
LexValue.ValOnHeap = FALSE;
LexValue.ValOnStack = FALSE;
LexValue.IsLValue = FALSE;
@ -621,16 +653,16 @@ enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int I
}
if (IncPos)
Parser->Pos += ValueSize + 1;
Parser->Pos += ValueSize + TOKEN_DATA_OFFSET;
}
else
{
if (IncPos && Token != TokenEOF)
Parser->Pos++;
Parser->Pos += TOKEN_DATA_OFFSET;
}
#ifdef DEBUG_LEXER
printf("Got token=%02x inc=%d\n", Token, IncPos);
printf("Got token=%02x inc=%d pos=%d\n", Token, IncPos, Parser->CharacterPos);
#endif
return Token;
}

View file

@ -188,6 +188,9 @@ void ParserCopyPos(struct ParseState *To, struct ParseState *From)
{
To->Pos = From->Pos;
To->Line = From->Line;
#ifdef FANCY_ERROR_REPORTING
To->CharacterPos = From->CharacterPos;
#endif
}
/* parse a "for" statement */
@ -572,7 +575,7 @@ void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt)
if (OldCleanupTokens == NULL)
CleanupTokens = Tokens;
LexInitParser(&Parser, Tokens, FileName, 1, RunIt);
LexInitParser(&Parser, Source, Tokens, FileName, RunIt);
do {
Ok = ParseStatement(&Parser);
@ -593,7 +596,7 @@ void ParseInteractive()
enum ParseResult Ok;
PlatformPrintf(INTERACTIVE_PROMPT_START);
LexInitParser(&Parser, NULL, StrEmpty, 1, TRUE);
LexInitParser(&Parser, NULL, NULL, StrEmpty, TRUE);
PlatformSetExitPoint();
LexInteractiveClear(&Parser);

14
picoc.h
View file

@ -96,6 +96,10 @@ struct ParseState
const char *FileName;
enum RunMode Mode; /* whether to skip or run code */
int SearchLabel; /* what case label we're searching for */
#ifdef FANCY_ERROR_REPORTING
int CharacterPos;
const char *SourceText;
#endif
};
/* values */
@ -229,8 +233,12 @@ struct LexState
{
const char *Pos;
const char *End;
int Line;
const char *FileName;
int Line;
#ifdef FANCY_ERROR_REPORTING
int CharacterPos;
const char *SourceText;
#endif
};
/* library function definition */
@ -261,6 +269,7 @@ struct OutputStream
union OutputStreamInfo i;
};
/* possible results of parsing a statement */
enum ParseResult { ParseResultEOF, ParseResultError, ParseResultOk };
/* globals */
@ -300,7 +309,7 @@ void TableStrFree();
void LexInit();
void LexCleanup();
void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *TokenLen);
void LexInitParser(struct ParseState *Parser, void *TokenSource, const char *FileName, int Line, int RunIt);
void LexInitParser(struct ParseState *Parser, const char *SourceText, void *TokenSource, const char *FileName, int RunIt);
enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos);
void LexToEndOfLine(struct ParseState *Parser);
void *LexCopyTokens(struct ParseState *StartParser, struct ParseState *EndParser);
@ -376,6 +385,7 @@ void PrintType(struct ValueType *Typ, struct OutputStream *Stream);
/* platform.c */
void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo);
void LexFail(struct LexState *Lexer, const char *Message, ...);
void PlatformCleanup();
void PlatformScanFile(const char *FileName);

View file

@ -1,12 +1,58 @@
#include "picoc.h"
#ifdef FANCY_ERROR_REPORTING
void PrintSourceTextErrorLine(const char *FileName, const char *SourceText, int Line, int CharacterPos)
{
int LineCount;
const char *LinePos;
const char *CPos;
int CCount;
if (SourceText != NULL)
{
/* find the source line */
for (LinePos = SourceText, LineCount = 1; *LinePos != '\0' && LineCount < Line; LinePos++)
{
if (*LinePos == '\n')
LineCount++;
}
/* display the line */
for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++)
PrintCh(*CPos, &CStdOut);
PrintCh('\n', &CStdOut);
/* display the error position */
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++)
{
if (*CPos == '\t')
PrintCh('\t', &CStdOut);
else
PrintCh(' ', &CStdOut);
}
}
else
{
/* assume we're in interactive mode - try to make the arrow match up with the input text */
for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++)
PrintCh(' ', &CStdOut);
}
PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos);
}
#endif
/* exit with a message */
void ProgramFail(struct ParseState *Parser, const char *Message, ...)
{
va_list Args;
if (Parser != NULL)
#ifdef FANCY_ERROR_REPORTING
PrintSourceTextErrorLine(Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos);
#else
PlatformPrintf("%s:%d: ", Parser->FileName, Parser->Line);
#endif
va_start(Args, Message);
PlatformVPrintf(Message, Args);
@ -15,12 +61,40 @@ void ProgramFail(struct ParseState *Parser, const char *Message, ...)
PlatformExit(1);
}
/* like ProgramFail() but gives descriptive error messages for assignment */
void AssignFail(struct ParseState *Parser, const char *Format, struct ValueType *Type1, struct ValueType *Type2, int Num1, int Num2, const char *FuncName, int ParamNo)
{
if (Parser != NULL)
#ifdef FANCY_ERROR_REPORTING
PrintSourceTextErrorLine(Parser->FileName, Parser->SourceText, Parser->Line, Parser->CharacterPos);
#else
PlatformPrintf("%s:%d: ", Parser->FileName, Parser->Line);
#endif
PlatformPrintf("can't %s ", (FuncName == NULL) ? "assign" : "set");
if (Type1 != NULL)
PlatformPrintf(Format, Type1, Type2);
else
PlatformPrintf(Format, Num1, Num2);
if (FuncName != NULL)
PlatformPrintf(" in argument %d of call to %s()", ParamNo, FuncName);
ProgramFail(NULL, "");
}
/* exit lexing with a message */
void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
#ifdef FANCY_ERROR_REPORTING
PrintSourceTextErrorLine(Lexer->FileName, Lexer->SourceText, Lexer->Line, Lexer->CharacterPos);
#else
PlatformPrintf("%s:%d: ", Lexer->FileName, Lexer->Line);
#endif
va_start(Args, Message);
PlatformVPrintf(Message, Args);
va_end(Args);

View file

@ -24,6 +24,8 @@
#define LOCAL_TABLE_SIZE 11 /* size of local variable table (can expand) */
#define STRUCT_TABLE_SIZE 11 /* size of struct/union member table (can expand) */
#define FANCY_ERROR_REPORTING /* optional feature - gives more detailed error messages but uses more memory */
#define INTERACTIVE_PROMPT_START "starting picoc\n"
#define INTERACTIVE_PROMPT_STATEMENT "picoc> "
#define INTERACTIVE_PROMPT_LINE " > "