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:
parent
2a69c48777
commit
3a1e39f9d3
4
Makefile
4
Makefile
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
24
expression.c
24
expression.c
|
@ -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
134
lex.c
|
@ -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;
|
||||
}
|
||||
|
|
7
parse.c
7
parse.c
|
@ -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
14
picoc.h
|
@ -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);
|
||||
|
|
74
platform.c
74
platform.c
|
@ -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);
|
||||
|
|
|
@ -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 " > "
|
||||
|
|
Loading…
Reference in a new issue