Bulko lexer change for more efficient pre-scanned tokens.

Removed Str type - replaced with standard C strings.
Added hashed string tables for efficient string storage.


git-svn-id: http://picoc.googlecode.com/svn/trunk@43 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2009-02-01 11:31:18 +00:00
parent 921ccdf17d
commit 86af5318da
10 changed files with 463 additions and 424 deletions

View file

@ -3,7 +3,7 @@ CFLAGS=-Wall -g
LIBS=-lm LIBS=-lm
TARGET = picoc TARGET = picoc
SRCS = picoc.c table.c str.c parse.c lex.c intrinsic.c heap.c type.c variable.c SRCS = picoc.c table.c lex.c parse.c intrinsic.c heap.c type.c variable.c str.c
OBJS := $(SRCS:%.c=%.o) OBJS := $(SRCS:%.c=%.o)
all: $(TARGET) all: $(TARGET)

8
heap.c
View file

@ -88,7 +88,10 @@ void *HeapAlloc(int Size)
struct AllocNode *NewMem = NULL; struct AllocNode *NewMem = NULL;
struct AllocNode **FreeNode; struct AllocNode **FreeNode;
int AllocSize = MEM_ALIGN(Size) + sizeof(NewMem->Size); int AllocSize = MEM_ALIGN(Size) + sizeof(NewMem->Size);
int Bucket = AllocSize >> 2; int Bucket = AllocSize >> 2;
if (Size == 0)
return NULL;
if (Bucket < FREELIST_BUCKETS && FreeListBucket[Bucket] != NULL) if (Bucket < FREELIST_BUCKETS && FreeListBucket[Bucket] != NULL)
{ /* try to allocate from a freelist bucket first */ { /* try to allocate from a freelist bucket first */
@ -137,6 +140,9 @@ void HeapFree(void *Mem)
struct AllocNode *MemNode = (struct AllocNode *)(Mem-sizeof(int)); struct AllocNode *MemNode = (struct AllocNode *)(Mem-sizeof(int));
int Bucket = MemNode->Size >> 2; int Bucket = MemNode->Size >> 2;
if (Mem == NULL)
return;
if ((void *)MemNode == HeapBottom) if ((void *)MemNode == HeapBottom)
{ /* pop it off the bottom of the heap, reducing the heap size */ { /* pop it off the bottom of the heap, reducing the heap size */
HeapBottom += sizeof(int) + MemNode->Size; HeapBottom += sizeof(int) + MemNode->Size;

View file

@ -44,9 +44,7 @@ void IntrinsicInit(struct Table *GlobalTable)
for (Count = 0; Count < sizeof(Intrinsics) / sizeof(struct IntrinsicFunction); Count++) for (Count = 0; Count < sizeof(Intrinsics) / sizeof(struct IntrinsicFunction); Count++)
{ {
Source.Str = Intrinsics[Count].Prototype; LexInit(&Lexer, Intrinsics[Count].Prototype, strlen(Source.Str), &IntrinsicFilename, Count+1);
Source.Len = strlen(Source.Str);
LexInit(&Lexer, &Source, &IntrinsicFilename, Count+1);
TypeParse(&Lexer, &Typ, &Identifier); TypeParse(&Lexer, &Typ, &Identifier);
IntrinsicReferenceNo[Count] = -1 - Count; IntrinsicReferenceNo[Count] = -1 - Count;
IntrinsicValue[Count].Typ = &FunctionType; IntrinsicValue[Count].Typ = &FunctionType;

171
lex.c
View file

@ -1,5 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <string.h>
#include <stdarg.h>
#include "picoc.h" #include "picoc.h"
@ -49,28 +53,47 @@ static struct ReservedWord ReservedWords[] =
{ "while", TokenWhile } { "while", TokenWhile }
}; };
void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line) struct LexState
{ {
Lexer->Pos = Source->Str; const char *Pos;
Lexer->End = Source->Str + Source->Len; const char *End;
Lexer->Line = Line; int Line;
Lexer->FileName = FileName; const char *FileName;
};
void LexInit(struct ParseState *Parser, const char *Source, int SourceLen, const char *FileName, int Line)
{
Parser->Pos = Source;
Parser->End = Source + SourceLen;
Parser->Line = Line;
Parser->FileName = FileName;
} }
enum LexToken LexCheckReservedWord(const Str *Word) void LexFail(struct LexState *Lexer, const char *Message, ...)
{
va_list Args;
printf("%s:%d: ", Lexer->FileName, Lexer->Line);
va_start(Args, Message);
vprintf(Message, Args);
printf("\n");
exit(1);
}
enum LexToken LexCheckReservedWord(const char *Word)
{ {
int Count; int Count;
for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++)
{ {
if (StrEqualC(Word, ReservedWords[Count].Word)) if (strcmp(Word, ReservedWords[Count].Word) == 0)
return ReservedWords[Count].Token; return ReservedWords[Count].Token;
} }
return TokenNone; return TokenNone;
} }
enum LexToken LexGetNumber(struct LexState *Lexer, struct Value **Value) enum LexToken LexGetNumber(struct LexState *Lexer, struct Value *Value)
{ {
int Result = 0; int Result = 0;
double FPResult; double FPResult;
@ -79,12 +102,12 @@ enum LexToken LexGetNumber(struct LexState *Lexer, struct Value **Value)
for (; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++) for (; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++)
Result = Result * 10 + (*Lexer->Pos - '0'); Result = Result * 10 + (*Lexer->Pos - '0');
(*Value)->Typ = &IntType; Value->Typ = &IntType;
(*Value)->Val->Integer = Result; Value->Val->Integer = Result;
if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.') if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.')
return TokenIntegerConstant; return TokenIntegerConstant;
(*Value)->Typ = &FPType; Value->Typ = &FPType;
Lexer->Pos++; Lexer->Pos++;
for (FPDiv = 0.1, FPResult = (double)Result; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++, FPDiv /= 10.0) for (FPDiv = 0.1, FPResult = (double)Result; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++, FPDiv /= 10.0)
FPResult += (*Lexer->Pos - '0') * FPDiv; FPResult += (*Lexer->Pos - '0') * FPDiv;
@ -101,7 +124,7 @@ enum LexToken LexGetNumber(struct LexState *Lexer, struct Value **Value)
return TokenFPConstant; return TokenFPConstant;
} }
enum LexToken LexGetWord(struct LexState *Lexer, struct Value **Value) enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
{ {
const char *Pos = Lexer->Pos + 1; const char *Pos = Lexer->Pos + 1;
enum LexToken Token; enum LexToken Token;
@ -109,24 +132,24 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value **Value)
while (Lexer->Pos != Lexer->End && isCident(*Pos)) while (Lexer->Pos != Lexer->End && isCident(*Pos))
Pos++; Pos++;
(*Value)->Typ = &StringType; Value->Typ = &StringType;
(*Value)->Val->String.Str = Lexer->Pos; Value->Val->String = (char *)StrRegister2(Lexer->Pos, Pos - Lexer->Pos);
(*Value)->Val->String.Len = Pos - Lexer->Pos;
Lexer->Pos = Pos; Lexer->Pos = Pos;
Token = LexCheckReservedWord(&(*Value)->Val->String); Token = LexCheckReservedWord(Value->Val->String);
if (Token != TokenNone) if (Token != TokenNone)
return Token; return Token;
return TokenIdentifier; return TokenIdentifier;
} }
enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value **Value) enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value *Value)
{ {
int Escape = FALSE; int Escape = FALSE;
const char *StartPos = Lexer->Pos;
(*Value)->Typ = &StringType; // XXX - do escaping here
(*Value)->Val->String.Str = Lexer->Pos; Value->Typ = &StringType;
while (Lexer->Pos != Lexer->End && (*Lexer->Pos != '"' || Escape)) while (Lexer->Pos != Lexer->End && (*Lexer->Pos != '"' || Escape))
{ {
if (Escape) if (Escape)
@ -136,25 +159,25 @@ enum LexToken LexGetStringConstant(struct LexState *Lexer, struct Value **Value)
Lexer->Pos++; Lexer->Pos++;
} }
(*Value)->Val->String.Len = Lexer->Pos - (*Value)->Val->String.Str; Value->Val->String = (char *)StrRegister2(StartPos, Lexer->Pos - StartPos);
if (*Lexer->Pos == '"') if (*Lexer->Pos == '"')
Lexer->Pos++; Lexer->Pos++;
return TokenStringConstant; return TokenStringConstant;
} }
enum LexToken LexGetCharacterConstant(struct LexState *Lexer, struct Value **Value) enum LexToken LexGetCharacterConstant(struct LexState *Lexer, struct Value *Value)
{ {
(*Value)->Typ = &IntType; Value->Typ = &IntType;
(*Value)->Val->Integer = Lexer->Pos[1]; Value->Val->Integer = Lexer->Pos[1];
if (Lexer->Pos[2] != '\'') if (Lexer->Pos[2] != '\'')
ProgramFail(Lexer, "illegal character '%c'", Lexer->Pos[2]); LexFail(Lexer, "illegal character '%c'", Lexer->Pos[2]);
Lexer->Pos += 3; Lexer->Pos += 3;
return TokenCharacterConstant; return TokenCharacterConstant;
} }
enum LexToken LexGetComment(struct LexState *Lexer, char NextChar, struct Value **Value) enum LexToken LexGetComment(struct LexState *Lexer, char NextChar, struct Value *Value)
{ {
Lexer->Pos++; Lexer->Pos++;
if (NextChar == '*') if (NextChar == '*')
@ -174,11 +197,18 @@ enum LexToken LexGetComment(struct LexState *Lexer, char NextChar, struct Value
return LexGetToken(Lexer, Value); return LexGetToken(Lexer, Value);
} }
enum LexToken LexGetTokenUncached(struct LexState *Lexer, struct Value **Value) enum LexToken LexGetTokenToStack(struct LexState *Lexer, struct Value **Value)
{ {
char ThisChar; char ThisChar;
char NextChar; char NextChar;
if (Lexer->Pos == Lexer->End)
{
char LineBuffer[LINEBUFFER_MAX];
if (fgets(&LineBuffer[0], LINEBUFFER_MAX, stdin) == NULL)
return TokenEOF;
}
*Value = &LexValue; *Value = &LexValue;
while (Lexer->Pos != Lexer->End && isspace(*Lexer->Pos)) while (Lexer->Pos != Lexer->End && isspace(*Lexer->Pos))
{ {
@ -188,29 +218,26 @@ enum LexToken LexGetTokenUncached(struct LexState *Lexer, struct Value **Value)
Lexer->Pos++; Lexer->Pos++;
} }
if (Lexer->Pos == Lexer->End)
return TokenEOF;
ThisChar = *Lexer->Pos; ThisChar = *Lexer->Pos;
if (isCidstart(ThisChar)) if (isCidstart(ThisChar))
return LexGetWord(Lexer, Value); return LexGetWord(Lexer, *Value);
if (isdigit(ThisChar)) if (isdigit(ThisChar))
return LexGetNumber(Lexer, Value); return LexGetNumber(Lexer, *Value);
NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0; NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0;
Lexer->Pos++; Lexer->Pos++;
switch (ThisChar) switch (ThisChar)
{ {
case '"': return LexGetStringConstant(Lexer, Value); case '"': return LexGetStringConstant(Lexer, *Value);
case '\'': return LexGetCharacterConstant(Lexer, Value); case '\'': return LexGetCharacterConstant(Lexer, *Value);
case '(': return TokenOpenBracket; case '(': return TokenOpenBracket;
case ')': return TokenCloseBracket; case ')': return TokenCloseBracket;
case '=': NEXTIS('=', TokenEquality, TokenAssign); case '=': NEXTIS('=', TokenEquality, TokenAssign);
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus);
case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus);
case '*': return TokenAsterisk; case '*': return TokenAsterisk;
case '/': if (NextChar == '/' || NextChar == '*') return LexGetComment(Lexer, NextChar, Value); else return TokenSlash; case '/': if (NextChar == '/' || NextChar == '*') return LexGetComment(Lexer, NextChar, *Value); else return TokenSlash;
case '<': NEXTIS('=', TokenLessEqual, TokenLessThan); case '<': NEXTIS('=', TokenLessEqual, TokenLessThan);
case '>': NEXTIS('=', TokenGreaterEqual, TokenGreaterThan); case '>': NEXTIS('=', TokenGreaterEqual, TokenGreaterThan);
case ';': return TokenSemicolon; case ';': return TokenSemicolon;
@ -227,59 +254,47 @@ enum LexToken LexGetTokenUncached(struct LexState *Lexer, struct Value **Value)
case '.': return TokenDot; case '.': return TokenDot;
} }
ProgramFail(Lexer, "illegal character '%c'", ThisChar); LexFail(Lexer, "illegal character '%c'", ThisChar);
return TokenEOF; return TokenEOF;
} }
enum LexToken LexGetToken(struct LexState *Lexer, struct Value **Value) void LexTokeniseToStack(struct LexState *Lexer, struct Value **Value)
{ {
static const char *CachedPos = NULL; XXX - finish this
static union AnyValue CachedAnyValue; }
static struct Value CachedValue;
static struct LexState CachedLexer; enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos)
static enum LexToken CachedToken; {
enum LexToken;
while (Parser->Pos != Parser->End && (enum LexToken)*(unsigned char *)Parser->Pos == TokenEndOfLine)
{ /* skip leading newlines */
Pos->Line++;
Pos++;
}
if (Lexer->Pos == CachedPos) if (Parser->Pos == Parser->End)
{ return TokenEOF;
*Value = &CachedValue;
CachedValue.Val = &CachedAnyValue; LexToken = (enum LexToken)*(unsigned char *)Parser->Pos;
*Lexer = CachedLexer; if (LexToken >= TokenIdentifier && LexToken <= TokenCharacterConstant)
{ /* this token requires a value */
int ValueLen = sizeof(struct Value) + ((struct Value *)Parser->Pos)->Typ->Sizeof;
if (Value != NULL)
{ /* copy the value out (aligns it in the process) */
memcpy(LexValue, (struct Value *)Parser->Pos, ValueLen);
*Value = &LexValue;
}
if (IncPos)
Parser->Pos += ValueLen + 1;
} }
else else
{ {
CachedPos = Lexer->Pos; if (IncPos)
CachedToken = LexGetTokenUncached(Lexer, Value); Parser->Pos++;
CachedLexer = *Lexer;
CachedValue = **Value;
CachedAnyValue = *(*Value)->Val;
} }
return CachedToken; return LexToken;
} }
enum LexToken LexGetPlainToken(struct LexState *Lexer)
{
struct Value *Value;
return LexGetToken(Lexer, &Value);
}
/* look at the next token without changing the lexer state */
enum LexToken LexPeekToken(struct LexState *Lexer, struct Value **Value)
{
struct LexState LocalState = *Lexer;
return LexGetToken(&LocalState, Value);
}
enum LexToken LexPeekPlainToken(struct LexState *Lexer)
{
struct LexState LocalState = *Lexer;
struct Value *Value;
return LexGetToken(&LocalState, &Value);
}
/* skip everything up to the end of the line */
void LexToEndOfLine(struct LexState *Lexer)
{
while (Lexer->Pos != Lexer->End && *Lexer->Pos != '\n')
Lexer->Pos++;
}

386
parse.c
View file

@ -8,25 +8,27 @@ int ParameterUsed = 0;
struct Value *ReturnValue; struct Value *ReturnValue;
/* local prototypes */ /* local prototypes */
int ParseIntExpression(struct LexState *Lexer, int RunIt); int ParseIntExpression(struct ParseState *Parser, int RunIt);
int ParseStatement(struct LexState *Lexer, int RunIt); int ParseStatement(struct ParseState *Parser, int RunIt);
int ParseArguments(struct LexState *Lexer, int RunIt); int ParseArguments(struct ParseState *Parser, int RunIt);
/* initialise the parser */ /* initialise the parser */
void ParseInit() void ParseInit()
{ {
StrInit();
VariableInit(); VariableInit();
IntrinsicInit(&GlobalTable); IntrinsicInit(&GlobalTable);
TypeInit(); TypeInit();
} }
/* parse a parameter list, defining parameters as local variables in the current scope */ /* parse a parameter list, defining parameters as local variables in the current scope */
void ParseParameterList(struct LexState *CallLexer, struct LexState *FuncLexer, int RunIt) void ParseParameterList(struct ParseState *CallLexer, struct FuncDef *Func, int RunIt)
{ {
XXX - fix this
struct ValueType *Typ; struct ValueType *Typ;
Str Identifier; Str Identifier;
enum LexToken Token = LexGetPlainToken(FuncLexer); /* open bracket */ enum LexToken Token = LexGetToken(FuncLexer, NULL, TRUE); /* open bracket */
int ParamCount; int ParamCount;
for (ParamCount = 0; ParamCount < ParameterUsed; ParamCount++) for (ParamCount = 0; ParamCount < ParameterUsed; ParamCount++)
@ -43,7 +45,7 @@ void ParseParameterList(struct LexState *CallLexer, struct LexState *FuncLexer,
} }
} }
Token = LexGetPlainToken(FuncLexer); Token = LexGetToken(FuncLexer, NULL, TRUE);
if (ParamCount < ParameterUsed-1 && Token != TokenComma) if (ParamCount < ParameterUsed-1 && Token != TokenComma)
ProgramFail(FuncLexer, "comma expected"); ProgramFail(FuncLexer, "comma expected");
} }
@ -52,96 +54,97 @@ void ParseParameterList(struct LexState *CallLexer, struct LexState *FuncLexer,
ProgramFail(FuncLexer, "')' expected"); ProgramFail(FuncLexer, "')' expected");
if (ParameterUsed == 0) if (ParameterUsed == 0)
Token = LexGetPlainToken(FuncLexer); Token = LexGetToken(FuncLexer, NULL, TRUE);
if (Token != TokenCloseBracket) if (Token != TokenCloseBracket)
ProgramFail(CallLexer, "wrong number of arguments"); ProgramFail(CallLexer, "wrong number of arguments");
} }
/* do a function call */ /* do a function call */
void ParseFunctionCall(struct LexState *Lexer, struct Value **Result, int ResultOnHeap, Str *FuncName, int RunIt) void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, Str *FuncName, int RunIt)
{ {
enum LexToken Token = LexGetPlainToken(Lexer); /* open bracket */ XXX - fix this
enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */
/* parse arguments */ /* parse arguments */
ParameterUsed = 0; ParameterUsed = 0;
do { do {
if (ParseExpression(Lexer, &Parameter[ParameterUsed], FALSE, RunIt)) if (ParseExpression(Parser, &Parameter[ParameterUsed], FALSE, RunIt))
{ {
if (RunIt && ParameterUsed >= PARAMETER_MAX) if (RunIt && ParameterUsed >= PARAMETER_MAX)
ProgramFail(Lexer, "too many arguments"); ProgramFail(Parser, "too many arguments");
ParameterUsed++; ParameterUsed++;
Token = LexGetPlainToken(Lexer); Token = LexGetToken(Parser, NULL, TRUE);
if (Token != TokenComma && Token != TokenCloseBracket) if (Token != TokenComma && Token != TokenCloseBracket)
ProgramFail(Lexer, "comma expected"); ProgramFail(Parser, "comma expected");
} }
else else
{ {
Token = LexGetPlainToken(Lexer); Token = LexGetToken(Parser, NULL, TRUE);
if (!TokenCloseBracket) if (!TokenCloseBracket)
ProgramFail(Lexer, "bad argument"); ProgramFail(Parser, "bad argument");
} }
} while (Token != TokenCloseBracket); } while (Token != TokenCloseBracket);
if (RunIt) if (RunIt)
{ {
struct LexState FuncLexer; struct ParseState FuncLexer;
struct ValueType *ReturnType; struct ValueType *ReturnType;
struct Value *FuncValue; struct Value *FuncValue;
Str FuncName; Str FuncName;
int Count; int Count;
VariableGet(Lexer, &FuncName, &FuncValue); VariableGet(Parser, &FuncName, &FuncValue);
if ((*Result)->Typ->Base != TypeFunction) if ((*Result)->Typ->Base != TypeFunction)
ProgramFail(Lexer, "not a function - can't call"); ProgramFail(Parser, "not a function - can't call");
VariableStackFrameAdd(Lexer); VariableStackFrameAdd(Parser);
if (FuncValue->Val->Lexer.Line >= 0) if (FuncValue->Val->Parser.Line >= 0)
FuncLexer = FuncValue->Val->Lexer; FuncLexer = FuncValue->Val->Parser;
else else
IntrinsicGetLexer(&FuncLexer, FuncValue->Val->Lexer.Line); IntrinsicGetLexer(&FuncLexer, FuncValue->Val->Parser.Line);
TypeParse(&FuncLexer, &ReturnType, &FuncName); /* get the return type */ TypeParse(&FuncLexer, &ReturnType, &FuncName); /* get the return type */
*Result = VariableAllocValueFromType(Lexer, ReturnType, ResultOnHeap); *Result = VariableAllocValueFromType(Parser, ReturnType, ResultOnHeap);
ParseParameterList(Lexer, &FuncLexer, TRUE); /* parameters */ ParseParameterList(Parser, &FuncLexer, TRUE); /* parameters */
if (FuncValue->Val->Lexer.Line >= 0) if (FuncValue->Val->Parser.Line >= 0)
{ /* run a user-defined function */ { /* run a user-defined function */
if (LexPeekPlainToken(&FuncLexer) != TokenLeftBrace || !ParseStatement(&FuncLexer, TRUE)) if (LexGetToken(&FuncLexer, NULL, FALSE) != TokenLeftBrace || !ParseStatement(&FuncLexer, TRUE))
ProgramFail(&FuncLexer, "function body expected"); ProgramFail(&FuncLexer, "function body expected");
if (ReturnType != (*Result)->Typ) if (ReturnType != (*Result)->Typ)
ProgramFail(&FuncLexer, "bad return value"); ProgramFail(&FuncLexer, "bad return value");
} }
else else
IntrinsicCall(Lexer, *Result, ReturnType, (*Result)->Val->Lexer.Line); IntrinsicCall(Parser, *Result, ReturnType, (*Result)->Val->Parser.Line);
VariableStackFramePop(Lexer); VariableStackFramePop(Parser);
for (Count = ParameterUsed-1; Count >= 0; Count--) /* free stack space used by parameters */ for (Count = ParameterUsed-1; Count >= 0; Count--) /* free stack space used by parameters */
VariableStackPop(Lexer, Parameter[Count]); VariableStackPop(Parser, Parameter[Count]);
} }
} }
/* parse a single value */ /* parse a single value */
int ParseValue(struct LexState *Lexer, struct Value **Result, int ResultOnHeap, int RunIt) int ParseValue(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, int RunIt)
{ {
struct LexState PreState = *Lexer; struct ParseState PreState = *Parser;
struct Value *LexValue; struct Value *LexValue;
int IntValue; int IntValue;
enum LexToken Token = LexGetToken(Lexer, &LexValue); enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
switch (Token) switch (Token)
{ {
case TokenIntegerConstant: case TokenCharacterConstant: case TokenFPConstant: case TokenStringConstant: case TokenIntegerConstant: case TokenCharacterConstant: case TokenFPConstant: case TokenStringConstant:
*Result = VariableAllocValueAndCopy(Lexer, LexValue, ResultOnHeap); *Result = VariableAllocValueAndCopy(Parser, LexValue, ResultOnHeap);
break; break;
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot: case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
IntValue = ParseIntExpression(Lexer, RunIt); IntValue = ParseIntExpression(Parser, RunIt);
if (RunIt) if (RunIt)
{ {
*Result = VariableAllocValueFromType(Lexer, &IntType, ResultOnHeap); *Result = VariableAllocValueFromType(Parser, &IntType, ResultOnHeap);
switch(Token) switch(Token)
{ {
case TokenMinus: (*Result)->Val->Integer = -IntValue; break; case TokenMinus: (*Result)->Val->Integer = -IntValue; break;
@ -153,73 +156,73 @@ int ParseValue(struct LexState *Lexer, struct Value **Result, int ResultOnHeap,
break; break;
case TokenOpenBracket: case TokenOpenBracket:
if (!ParseExpression(Lexer, Result, ResultOnHeap, RunIt)) if (!ParseExpression(Parser, Result, ResultOnHeap, RunIt))
ProgramFail(Lexer, "invalid expression"); ProgramFail(Parser, "invalid expression");
if (LexGetPlainToken(Lexer) != TokenCloseBracket) if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
ProgramFail(Lexer, "')' expected"); ProgramFail(Parser, "')' expected");
break; break;
case TokenAsterisk: case TokenAsterisk:
case TokenAmpersand: case TokenAmpersand:
ProgramFail(Lexer, "not implemented"); ProgramFail(Parser, "not implemented");
case TokenIdentifier: case TokenIdentifier:
if (LexPeekPlainToken(Lexer) == TokenOpenBracket) if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
ParseFunctionCall(Lexer, Result, ResultOnHeap, &LexValue->Val->String, RunIt); ParseFunctionCall(Parser, Result, ResultOnHeap, &LexValue->Val->String, RunIt);
else else
{ {
if (RunIt) if (RunIt)
{ {
struct Value *IdentValue; struct Value *IdentValue;
VariableGet(Lexer, &LexValue->Val->String, &IdentValue); VariableGet(Parser, &LexValue->Val->String, &IdentValue);
if (IdentValue->Typ->Base == TypeMacro) if (IdentValue->Typ->Base == TypeMacro)
{ {
struct LexState MacroLexer = IdentValue->Val->Lexer; struct ParseState MacroLexer = IdentValue->Val->Parser;
if (!ParseExpression(&MacroLexer, Result, ResultOnHeap, TRUE)) if (!ParseExpression(&MacroLexer, Result, ResultOnHeap, TRUE))
ProgramFail(&MacroLexer, "expression expected"); ProgramFail(&MacroLexer, "expression expected");
} }
else if (!ISVALUETYPE(IdentValue->Typ)) else if (!ISVALUETYPE(IdentValue->Typ))
ProgramFail(Lexer, "bad variable type"); ProgramFail(Parser, "bad variable type");
} }
} }
break; break;
default: default:
*Lexer = PreState; *Parser = PreState;
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
struct Value *ParsePushFP(struct LexState *Lexer, int ResultOnHeap, double NewFP) struct Value *ParsePushFP(struct ParseState *Parser, int ResultOnHeap, double NewFP)
{ {
struct Value *Val = VariableAllocValueFromType(Lexer, &FPType, ResultOnHeap); struct Value *Val = VariableAllocValueFromType(Parser, &FPType, ResultOnHeap);
Val->Val->FP = NewFP; Val->Val->FP = NewFP;
return Val; return Val;
} }
struct Value *ParsePushInt(struct LexState *Lexer, int ResultOnHeap, int NewInt) struct Value *ParsePushInt(struct ParseState *Parser, int ResultOnHeap, int NewInt)
{ {
struct Value *Val = VariableAllocValueFromType(Lexer, &IntType, ResultOnHeap); struct Value *Val = VariableAllocValueFromType(Parser, &IntType, ResultOnHeap);
Val->Val->Integer = NewInt; Val->Val->Integer = NewInt;
return Val; return Val;
} }
/* parse an expression. operator precedence is not supported */ /* parse an expression. operator precedence is not supported */
int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnHeap, int RunIt) int ParseExpression(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, int RunIt)
{ {
struct Value *CurrentValue; struct Value *CurrentValue;
struct Value *TotalValue; struct Value *TotalValue;
if (!ParseValue(Lexer, &TotalValue, ResultOnHeap, RunIt)) if (!ParseValue(Parser, &TotalValue, ResultOnHeap, RunIt))
return FALSE; return FALSE;
while (TRUE) while (TRUE)
{ {
enum LexToken Token = LexPeekPlainToken(Lexer); enum LexToken Token = LexGetToken(Parser, NULL, FALSE);
switch (Token) switch (Token)
{ {
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash: case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
@ -227,18 +230,18 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd: case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr:
case TokenArithmeticExor: case TokenDot: case TokenArithmeticExor: case TokenDot:
LexGetPlainToken(Lexer); LexGetToken(Parser, NULL, TRUE);
break; break;
case TokenAssign: case TokenAddAssign: case TokenSubtractAssign: case TokenAssign: case TokenAddAssign: case TokenSubtractAssign:
LexGetPlainToken(Lexer); LexGetToken(Parser, NULL, TRUE);
if (!ParseExpression(Lexer, &CurrentValue, ResultOnHeap, RunIt)) if (!ParseExpression(Parser, &CurrentValue, ResultOnHeap, RunIt))
ProgramFail(Lexer, "expression expected"); ProgramFail(Parser, "expression expected");
if (RunIt) if (RunIt)
{ {
if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt) if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt)
ProgramFail(Lexer, "can't assign"); ProgramFail(Parser, "can't assign");
switch (Token) switch (Token)
{ {
@ -246,7 +249,7 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
case TokenSubtractAssign: TotalValue->Val->Integer -= CurrentValue->Val->Integer; break; case TokenSubtractAssign: TotalValue->Val->Integer -= CurrentValue->Val->Integer; break;
default: TotalValue->Val->Integer = CurrentValue->Val->Integer; break; default: TotalValue->Val->Integer = CurrentValue->Val->Integer; break;
} }
VariableStackPop(Lexer, CurrentValue); VariableStackPop(Parser, CurrentValue);
} }
// fallthrough // fallthrough
@ -256,7 +259,7 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
return TRUE; return TRUE;
} }
if (!ParseValue(Lexer, &CurrentValue, ResultOnHeap, RunIt)) if (!ParseValue(Parser, &CurrentValue, ResultOnHeap, RunIt))
return FALSE; return FALSE;
if (RunIt) if (RunIt)
@ -272,39 +275,39 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
else if (CurrentValue->Typ->Base == TypeFP) else if (CurrentValue->Typ->Base == TypeFP)
FPCurrent = CurrentValue->Val->FP; FPCurrent = CurrentValue->Val->FP;
else else
ProgramFail(Lexer, "bad type for operator"); ProgramFail(Parser, "bad type for operator");
if (TotalValue->Typ->Base == TypeInt) if (TotalValue->Typ->Base == TypeInt)
FPTotal = (double)TotalValue->Val->Integer; FPTotal = (double)TotalValue->Val->Integer;
else if (TotalValue->Typ->Base == TypeFP) else if (TotalValue->Typ->Base == TypeFP)
FPTotal = TotalValue->Val->FP; FPTotal = TotalValue->Val->FP;
else else
ProgramFail(Lexer, "bad type for operator"); ProgramFail(Parser, "bad type for operator");
} }
VariableStackPop(Lexer, CurrentValue); VariableStackPop(Parser, CurrentValue);
VariableStackPop(Lexer, TotalValue); VariableStackPop(Parser, TotalValue);
switch (Token) switch (Token)
{ {
case TokenPlus: TotalValue = ParsePushFP(Lexer, ResultOnHeap, FPTotal + FPCurrent); break; case TokenPlus: TotalValue = ParsePushFP(Parser, ResultOnHeap, FPTotal + FPCurrent); break;
case TokenMinus: TotalValue = ParsePushFP(Lexer, ResultOnHeap, FPTotal - FPCurrent); break; case TokenMinus: TotalValue = ParsePushFP(Parser, ResultOnHeap, FPTotal - FPCurrent); break;
case TokenAsterisk: TotalValue = ParsePushFP(Lexer, ResultOnHeap, FPTotal * FPCurrent); break; case TokenAsterisk: TotalValue = ParsePushFP(Parser, ResultOnHeap, FPTotal * FPCurrent); break;
case TokenSlash: TotalValue = ParsePushFP(Lexer, ResultOnHeap, FPTotal / FPCurrent); break; case TokenSlash: TotalValue = ParsePushFP(Parser, ResultOnHeap, FPTotal / FPCurrent); break;
case TokenEquality: TotalValue = ParsePushInt(Lexer, ResultOnHeap, FPTotal == FPCurrent); break; case TokenEquality: TotalValue = ParsePushInt(Parser, ResultOnHeap, FPTotal == FPCurrent); break;
case TokenLessThan: TotalValue = ParsePushInt(Lexer, ResultOnHeap, FPTotal < FPCurrent); break; case TokenLessThan: TotalValue = ParsePushInt(Parser, ResultOnHeap, FPTotal < FPCurrent); break;
case TokenGreaterThan: TotalValue = ParsePushInt(Lexer, ResultOnHeap, FPTotal > FPCurrent); break; case TokenGreaterThan: TotalValue = ParsePushInt(Parser, ResultOnHeap, FPTotal > FPCurrent); break;
case TokenLessEqual: TotalValue = ParsePushInt(Lexer, ResultOnHeap, FPTotal <= FPCurrent); break; case TokenLessEqual: TotalValue = ParsePushInt(Parser, ResultOnHeap, FPTotal <= FPCurrent); break;
case TokenGreaterEqual: TotalValue = ParsePushInt(Lexer, ResultOnHeap, FPTotal >= FPCurrent); break; case TokenGreaterEqual: TotalValue = ParsePushInt(Parser, ResultOnHeap, FPTotal >= FPCurrent); break;
case TokenLogicalAnd: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenArithmeticExor: ProgramFail(Lexer, "bad type for operator"); break; case TokenLogicalAnd: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenArithmeticExor: ProgramFail(Parser, "bad type for operator"); break;
case TokenDot: ProgramFail(Lexer, "operator not supported"); break; case TokenDot: ProgramFail(Parser, "operator not supported"); break;
default: break; default: break;
} }
} }
else else
{ {
if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt) if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt)
ProgramFail(Lexer, "bad operand types"); ProgramFail(Parser, "bad operand types");
/* integer arithmetic */ /* integer arithmetic */
switch (Token) switch (Token)
@ -323,11 +326,11 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
case TokenAmpersand: TotalValue->Val->Integer = TotalValue->Val->Integer & CurrentValue->Val->Integer; break; case TokenAmpersand: TotalValue->Val->Integer = TotalValue->Val->Integer & CurrentValue->Val->Integer; break;
case TokenArithmeticOr: TotalValue->Val->Integer = TotalValue->Val->Integer | CurrentValue->Val->Integer; break; case TokenArithmeticOr: TotalValue->Val->Integer = TotalValue->Val->Integer | CurrentValue->Val->Integer; break;
case TokenArithmeticExor: TotalValue->Val->Integer = TotalValue->Val->Integer ^ CurrentValue->Val->Integer; break; case TokenArithmeticExor: TotalValue->Val->Integer = TotalValue->Val->Integer ^ CurrentValue->Val->Integer; break;
case TokenDot: ProgramFail(Lexer, "operator not supported"); break; case TokenDot: ProgramFail(Parser, "operator not supported"); break;
default: break; default: break;
} }
} }
VariableStackPop(Lexer, CurrentValue); VariableStackPop(Parser, CurrentValue);
*Result = TotalValue; *Result = TotalValue;
} }
} }
@ -336,123 +339,157 @@ int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnH
} }
/* parse an expression. operator precedence is not supported */ /* parse an expression. operator precedence is not supported */
int ParseIntExpression(struct LexState *Lexer, int RunIt) int ParseIntExpression(struct ParseState *Parser, int RunIt)
{ {
struct Value *Val; struct Value *Val;
int Result = 0; int Result = 0;
if (!ParseExpression(Lexer, &Val, FALSE, RunIt)) if (!ParseExpression(Parser, &Val, FALSE, RunIt))
ProgramFail(Lexer, "expression expected"); ProgramFail(Parser, "expression expected");
if (RunIt) if (RunIt)
{ {
if (Val->Typ->Base != TypeInt) if (Val->Typ->Base != TypeInt)
ProgramFail(Lexer, "integer value expected"); ProgramFail(Parser, "integer value expected");
Result = Val->Val->Integer; Result = Val->Val->Integer;
VariableStackPop(Lexer, Val); VariableStackPop(Parser, Val);
} }
return Result; return Result;
} }
/* parse a function definition and store it for later */ /* parse a function definition and store it for later */
void ParseFunctionDefinition(struct LexState *Lexer, Str *Identifier, struct LexState *PreState) void ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, Str *Identifier)
{ {
struct Value *FuncValue = VariableAllocValueAndData(Lexer, sizeof(struct LexState), TRUE); struct ValueType *ParamTyp;
Str Identifier;
enum LexToken Token;
struct Value *FuncValue;
struct ParseState ParamParser;
int ParamCount = 0;
FuncValue->Val->Lexer = *PreState; LexGetToken(Parser, NULL, TRUE); /* open bracket */
LexGetPlainToken(Lexer); ParamParser = *Parser;
if (LexGetPlainToken(Lexer) != TokenCloseBracket || LexPeekPlainToken(Lexer) != TokenLeftBrace) Token = LexGetToken(Parser, NULL, TRUE);
ProgramFail(Lexer, "bad function definition"); if (Token != TokenCloseBracket && Token != TokenEOF)
{ /* count the number of parameters */
ParamCount++;
while ((Token = LexGetToken(Parser, NULL, TRUE)) != TokenCloseBracket && Token != TokenEOF)
{
if (Token == TokenComma)
ParamCount++;
}
}
if (!ParseStatement(Lexer, FALSE)) FuncValue = VariableAllocValueAndData(Parser, sizeof(struct FuncDef) + sizeof(struct ValueType *) * ParamCount + sizeof(Str *) * ParamCount, TRUE);
ProgramFail(Lexer, "function definition expected");
FuncValue->Val->Lexer.End = Lexer->Pos;
FuncValue->Typ = &FunctionType; FuncValue->Typ = &FunctionType;
FuncValue->Val->FuncDef.ReturnType = ReturnType;
FuncValue->Val->FuncDef.NumParams = ParamCount;
FuncValue->Val->FuncDef.ParamType = (void *)FuncValue->Val + sizeof(struct FuncDef);
FuncValue->Val->FuncDef.ParamName = (void *)FuncValue->Val->FuncDef.ParamType + sizeof(struct ValueType *) * ParamCount;
FuncValue->Val->FuncDef.Body = *Parser;
for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++)
{ /* harvest the parameters into the function definition */
TypeParse(ParamParser, &Typ, &Identifier);
FuncValue->Val->FuncDef.ParamType[ParamCount] = Typ;
FuncValue->Val->FuncDef.ParamName[ParamCount] = Typ;
Token = LexGetToken(ParamParser, NULL, TRUE);
if (Token != TokenComma)
ProgramFail(ParamParser, "comma expected");
}
if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace)
ProgramFail(Parser, "bad function definition");
if (!ParseStatement(Parser, FALSE))
ProgramFail(Parser, "function definition expected");
FuncValue->Val->FuncDef.Body.End = Parser->Pos;
if (!TableSet(&GlobalTable, Identifier, FuncValue)) if (!TableSet(&GlobalTable, Identifier, FuncValue))
ProgramFail(Lexer, "'%S' is already defined", Identifier); ProgramFail(Parser, "'%S' is already defined", Identifier);
} }
/* parse a #define macro definition and store it for later */ /* parse a #define macro definition and store it for later */
void ParseMacroDefinition(struct LexState *Lexer) void ParseMacroDefinition(struct ParseState *Parser)
{ {
XXX - fix this
struct Value *MacroName; struct Value *MacroName;
struct Value *MacroValue = VariableAllocValueAndData(Lexer, sizeof(struct LexState), TRUE); struct Value *MacroValue = VariableAllocValueAndData(Parser, sizeof(struct ParseState), TRUE);
if (LexGetToken(Lexer, &MacroName) != TokenIdentifier) if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
ProgramFail(Lexer, "identifier expected"); ProgramFail(Parser, "identifier expected");
MacroValue->Val->Lexer = *Lexer; MacroValue->Val->Parser = *Parser;
LexToEndOfLine(Lexer); MacroValue->Val->Parser.End = Parser->Pos;
MacroValue->Val->Lexer.End = Lexer->Pos;
MacroValue->Typ = &MacroType; MacroValue->Typ = &MacroType;
if (!TableSet(&GlobalTable, &MacroName->Val->String, MacroValue)) if (!TableSet(&GlobalTable, &MacroName->Val->String, MacroValue))
ProgramFail(Lexer, "'%S' is already defined", &MacroName->Val->String); ProgramFail(Parser, "'%S' is already defined", &MacroName->Val->String);
} }
void ParseFor(struct LexState *Lexer, int RunIt) void ParseFor(struct ParseState *Parser, int RunIt)
{ {
int Condition; int Condition;
struct LexState PreConditional; struct ParseState PreConditional;
struct LexState PreIncrement; struct ParseState PreIncrement;
struct LexState PreStatement; struct ParseState PreStatement;
struct LexState After; struct ParseState After;
if (LexGetPlainToken(Lexer) != TokenOpenBracket) if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
ProgramFail(Lexer, "'(' expected"); ProgramFail(Parser, "'(' expected");
if (!ParseStatement(Lexer, RunIt)) if (!ParseStatement(Parser, RunIt))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
PreConditional = *Lexer; PreConditional = *Parser;
Condition = ParseIntExpression(Lexer, RunIt); Condition = ParseIntExpression(Parser, RunIt);
if (LexGetPlainToken(Lexer) != TokenSemicolon) if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon)
ProgramFail(Lexer, "';' expected"); ProgramFail(Parser, "';' expected");
PreIncrement = *Lexer; PreIncrement = *Parser;
ParseStatement(Lexer, FALSE); ParseStatement(Parser, FALSE);
if (LexGetPlainToken(Lexer) != TokenCloseBracket) if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
ProgramFail(Lexer, "')' expected"); ProgramFail(Parser, "')' expected");
PreStatement = *Lexer; PreStatement = *Parser;
if (!ParseStatement(Lexer, RunIt && Condition)) if (!ParseStatement(Parser, RunIt && Condition))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
After = *Lexer; After = *Parser;
while (Condition && RunIt) while (Condition && RunIt)
{ {
*Lexer = PreIncrement; *Parser = PreIncrement;
ParseStatement(Lexer, TRUE); ParseStatement(Parser, TRUE);
*Lexer = PreConditional; *Parser = PreConditional;
Condition = ParseIntExpression(Lexer, RunIt); Condition = ParseIntExpression(Parser, RunIt);
if (Condition) if (Condition)
{ {
*Lexer = PreStatement; *Parser = PreStatement;
ParseStatement(Lexer, TRUE); ParseStatement(Parser, TRUE);
} }
} }
*Lexer = After; *Parser = After;
} }
/* parse a statement */ /* parse a statement */
int ParseStatement(struct LexState *Lexer, int RunIt) int ParseStatement(struct ParseState *Parser, int RunIt)
{ {
struct Value *CValue; struct Value *CValue;
int Condition; int Condition;
struct LexState PreState = *Lexer; struct ParseState PreState = *Parser;
Str Identifier; Str Identifier;
struct ValueType *Typ; struct ValueType *Typ;
enum LexToken Token = LexGetPlainToken(Lexer); enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
switch (Token) switch (Token)
{ {
@ -460,43 +497,43 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
return FALSE; return FALSE;
case TokenIdentifier: case TokenIdentifier:
*Lexer = PreState; *Parser = PreState;
ParseExpression(Lexer, &CValue, FALSE, RunIt); ParseExpression(Parser, &CValue, FALSE, RunIt);
if (RunIt) VariableStackPop(Lexer, CValue); if (RunIt) VariableStackPop(Parser, CValue);
break; break;
case TokenLeftBrace: case TokenLeftBrace:
while (ParseStatement(Lexer, RunIt)) while (ParseStatement(Parser, RunIt))
{} {}
if (LexGetPlainToken(Lexer) != TokenRightBrace) if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace)
ProgramFail(Lexer, "'}' expected"); ProgramFail(Parser, "'}' expected");
break; break;
case TokenIf: case TokenIf:
Condition = ParseIntExpression(Lexer, RunIt); Condition = ParseIntExpression(Parser, RunIt);
if (!ParseStatement(Lexer, RunIt && Condition)) if (!ParseStatement(Parser, RunIt && Condition))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
if (LexPeekPlainToken(Lexer) == TokenElse) if (LexGetToken(Parser, NULL, FALSE) == TokenElse)
{ {
LexGetPlainToken(Lexer); LexGetToken(Parser, NULL, TRUE);
if (!ParseStatement(Lexer, RunIt && !Condition)) if (!ParseStatement(Parser, RunIt && !Condition))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
} }
break; break;
case TokenWhile: case TokenWhile:
{ {
struct LexState PreConditional = *Lexer; struct ParseState PreConditional = *Parser;
do do
{ {
*Lexer = PreConditional; *Parser = PreConditional;
Condition = ParseIntExpression(Lexer, RunIt); Condition = ParseIntExpression(Parser, RunIt);
if (!ParseStatement(Lexer, RunIt && Condition)) if (!ParseStatement(Parser, RunIt && Condition))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
} while (RunIt && Condition); } while (RunIt && Condition);
} }
@ -504,21 +541,21 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenDo: case TokenDo:
{ {
struct LexState PreStatement = *Lexer; struct ParseState PreStatement = *Parser;
do do
{ {
*Lexer = PreStatement; *Parser = PreStatement;
if (!ParseStatement(Lexer, RunIt)) if (!ParseStatement(Parser, RunIt))
ProgramFail(Lexer, "statement expected"); ProgramFail(Parser, "statement expected");
Condition = ParseIntExpression(Lexer, RunIt); Condition = ParseIntExpression(Parser, RunIt);
} while (Condition && RunIt); } while (Condition && RunIt);
} }
break; break;
case TokenFor: case TokenFor:
ParseFor(Lexer, RunIt); ParseFor(Parser, RunIt);
break; break;
case TokenSemicolon: break; case TokenSemicolon: break;
@ -528,30 +565,29 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenFloatType: case TokenFloatType:
case TokenDoubleType: case TokenDoubleType:
case TokenVoidType: case TokenVoidType:
*Lexer = PreState; *Parser = PreState;
TypeParse(Lexer, &Typ, &Identifier); TypeParse(Parser, &Typ, &Identifier);
if (Identifier.Len == 0) if (Identifier.Len == 0)
ProgramFail(Lexer, "identifier expected"); ProgramFail(Parser, "identifier expected");
/* handle function definitions */ /* handle function definitions */
if (LexPeekPlainToken(Lexer) == TokenOpenBracket) if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
ParseFunctionDefinition(Lexer, &Identifier, &PreState); ParseFunctionDefinition(Parser, &Typ, &Identifier);
else else
VariableDefine(Lexer, &Identifier, VariableAllocValueFromType(Lexer, Typ, FALSE)); VariableDefine(Parser, &Identifier, VariableAllocValueFromType(Parser, Typ, FALSE));
break; break;
case TokenHashDefine: case TokenHashDefine:
ParseMacroDefinition(Lexer); ParseMacroDefinition(Parser);
break; break;
case TokenHashInclude: case TokenHashInclude:
{ {
struct Value *LexerValue; struct Value *LexerValue;
if (LexGetToken(Lexer, &LexerValue) != TokenStringConstant) if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
ProgramFail(Lexer, "\"filename.h\" expected"); ProgramFail(Parser, "\"filename.h\" expected");
ScanFile(&LexerValue->Val->String); ScanFile(&LexerValue->Val->String);
LexToEndOfLine(Lexer);
break; break;
} }
@ -560,11 +596,11 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenBreak: case TokenBreak:
case TokenReturn: case TokenReturn:
case TokenDefault: case TokenDefault:
ProgramFail(Lexer, "not implemented yet"); ProgramFail(Parser, "not implemented yet");
break; break;
default: default:
*Lexer = PreState; *Parser = PreState;
return FALSE; return FALSE;
} }
@ -572,15 +608,15 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
} }
/* quick scan a source file for definitions */ /* quick scan a source file for definitions */
void Parse(const Str *FileName, const Str *Source, int RunIt) void Parse(const Str *FileName, const Str *Source, int SourceLen, int RunIt)
{ {
struct LexState Lexer; struct ParseState Parser;
LexInit(&Lexer, Source, FileName, 1); LexInit(&Parser, Source, SourceLen, FileName, 1);
while (ParseStatement(&Lexer, RunIt)) while (ParseStatement(&Parser, RunIt))
{} {}
if (Lexer.Pos != Lexer.End) if (Parser.Pos != Parser.End)
ProgramFail(&Lexer, "parse error"); ProgramFail(&Parser, "parse error");
} }

62
picoc.c
View file

@ -9,79 +9,63 @@
/* all platform-dependent code is in this file */ /* all platform-dependent code is in this file */
void Fail(const char *Message, ...) void ProgramFail(struct ParseState *Parser, const char *Message, ...)
{
va_list Args;
va_start(Args, Message);
vStrPrintf(Message, Args);
exit(1);
}
void ProgramFail(struct LexState *Lexer, const char *Message, ...)
{ {
va_list Args; va_list Args;
if (Lexer != NULL) if (Parser != NULL)
StrPrintf("%S:%d: ", Lexer->FileName, Lexer->Line); printf("%s:%d: ", Parser->FileName, Parser->Line);
va_start(Args, Message); va_start(Args, Message);
vStrPrintf(Message, Args); vprintf(Message, Args);
StrPrintf("\n"); printf("\n");
exit(1); exit(1);
} }
/* read a file into memory. this is the only function using malloc(). /* read a file into memory */
* do it differently for embedded devices without malloc */ char *ReadFile(const char *FileName)
Str ReadFile(const Str *FileName)
{ {
struct stat FileInfo; struct stat FileInfo;
char *ReadText; char *ReadText;
Str Text;
FILE *InFile; FILE *InFile;
char CFileName[PATH_MAX];
StrToC(CFileName, PATH_MAX, FileName); if (stat(FileName, &FileInfo))
ProgramFail(NULL, "can't read file %s\n", FileName);
if (stat(CFileName, &FileInfo)) ReadText = HeapAlloc(FileInfo.st_size);
Fail("can't read file %s\n", CFileName);
ReadText = malloc(FileInfo.st_size);
if (ReadText == NULL) if (ReadText == NULL)
Fail("out of memory\n"); ProgramFail(NULL, "out of memory\n");
InFile = fopen(CFileName, "r"); InFile = fopen(FileName, "r");
if (InFile == NULL) if (InFile == NULL)
Fail("can't read file %s\n", CFileName); ProgramFail(NULL, "can't read file %s\n", FileName);
if (fread(ReadText, 1, FileInfo.st_size, InFile) != FileInfo.st_size) if (fread(ReadText, 1, FileInfo.st_size, InFile) != FileInfo.st_size)
Fail("can't read file %s\n", CFileName); ProgramFail(NULL, "can't read file %s\n", FileName);
Text.Str = ReadText;
Text.Len = FileInfo.st_size;
fclose(InFile); fclose(InFile);
return Text; return ReadText;
} }
/* read and scan a file for definitions */ /* read and scan a file for definitions */
void ScanFile(const Str *FileName) void ScanFile(const char *FileName)
{ {
Str SourceStr = ReadFile(FileName); char *SourceStr = ReadFile(FileName);
Parse(FileName, &SourceStr, TRUE); Parse(FileName, SourceStr, TRUE);
HeapFree(SourceStr);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Str FileName;
if (argc < 2) if (argc < 2)
Fail("Format: picoc <program.c> <args>...\n"); ProgramFail(NULL, "Format: picoc <program.c> <args>...\n");
HeapInit();
StrInit();
ParseInit(); ParseInit();
StrFromC(&FileName, argv[1]); ScanFile(argv[1]);
ScanFile(&FileName);
return 0; return 0;
} }

127
picoc.h
View file

@ -5,15 +5,16 @@
/* configurable options */ /* configurable options */
#define HEAP_SIZE 2048 /* space for the heap and the stack */ #define HEAP_SIZE 2048 /* space for the heap and the stack */
#define GLOBAL_TABLE_SIZE 397 /* global variable table */
#define FUNCTION_STORE_MAX 200 /* maximum number of used-defined functions and macros */
#define STACK_MAX 10 /* maximum function call stack depth */
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */
#define LOCAL_TABLE_SIZE 11 /* maximum number of local variables */
#define STRUCT_TABLE_SIZE 11 /* maximum number of struct/union members */
#define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */ #define LARGE_INT_POWER_OF_TEN 1000000000 /* the largest power of ten which fits in an int on this architecture */
#define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */ #define ARCH_ALIGN_WORDSIZE sizeof(int) /* memory alignment boundary on this architecture */
#define GLOBAL_TABLE_SIZE 397 /* global variable table */
#define STRING_TABLE_SIZE 97 /* shared string table size */
#define PARAMETER_MAX 10 /* maximum number of parameters to a function */
#define LINEBUFFER_MAX 256 /* maximum number of characters on a line */
#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) */
/* handy definitions */ /* handy definitions */
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
@ -61,28 +62,13 @@ enum LexToken
TokenHashDefine, TokenHashInclude TokenHashDefine, TokenHashInclude
}; };
/* string type so we can use source file strings */ /* parser state - has all this detail so we can parse nested files */
typedef struct _Str struct ParseState
{
int Len;
const char *Str;
} Str;
/* lexer state - so we can lex nested files */
struct LexState
{ {
const void *Pos;
const void *End;
int Line; int Line;
const char *Pos; const char *FileName;
const char *End;
const Str *FileName;
};
/* function definition - really just where it is in the source file */
struct FuncDef
{
Str Source;
Str FileName;
int StartLine;
}; };
/* values */ /* values */
@ -103,18 +89,30 @@ enum BaseType
TypeType /* a type (eg. typedef) */ TypeType /* a type (eg. typedef) */
}; };
/* data type */
struct ValueType struct ValueType
{ {
enum BaseType Base; /* what kind of type this is */ enum BaseType Base; /* what kind of type this is */
int ArraySize; /* the size of an array type */ int ArraySize; /* the size of an array type */
int Sizeof; /* the storage required */ int Sizeof; /* the storage required */
Str Identifier; /* the name of a struct or union */ const char *Identifier; /* the name of a struct or union */
struct ValueType *FromType; /* the type we're derived from (or NULL) */ struct ValueType *FromType; /* the type we're derived from (or NULL) */
struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */ struct ValueType *DerivedTypeList; /* first in a list of types derived from this one */
struct ValueType *Next; /* next item in the derived type list */ struct ValueType *Next; /* next item in the derived type list */
struct Table *Members; /* members of a struct, union or enum */ struct Table *Members; /* members of a struct, union or enum */
}; };
/* function definition */
struct FuncDef
{
struct ValueType *ReturnType; /* the return value type */
int NumParams; /* the number of parameters */
struct Typ *ParamType; /* array of parameter types */
const char **ParamName; /* array of parameter names */
void (*Intrinsic)(); /* intrinsic call address or NULL */
struct ParseState Body; /* lexical tokens of the function body if not intrinsic */
};
struct ArrayValue struct ArrayValue
{ {
unsigned int Size; /* the number of elements in the array */ unsigned int Size; /* the number of elements in the array */
@ -136,11 +134,12 @@ union AnyValue
short ShortInteger; short ShortInteger;
int Integer; int Integer;
double FP; double FP;
Str String; char *String;
struct ArrayValue Array; struct ArrayValue Array;
struct PointerValue Pointer; struct PointerValue Pointer;
struct LexState Lexer; struct ParseState Parser;
struct ValueType *Typ; struct ValueType *Typ;
struct FuncDef FuncDef;
}; };
struct Value struct Value
@ -154,7 +153,7 @@ struct Value
/* hash table data structure */ /* hash table data structure */
struct TableEntry struct TableEntry
{ {
Str Key; const char *Key;
struct Value *Val; struct Value *Val;
struct TableEntry *Next; struct TableEntry *Next;
}; };
@ -169,7 +168,7 @@ struct Table
/* stack frame for function calls */ /* stack frame for function calls */
struct StackFrame struct StackFrame
{ {
struct LexState ReturnLex; /* how we got here */ struct ParseState ReturnParser; /* how we got here */
struct Table LocalTable; /* the local variables and parameters */ struct Table LocalTable; /* the local variables and parameters */
struct TableEntry *LocalHashTable[LOCAL_TABLE_SIZE]; struct TableEntry *LocalHashTable[LOCAL_TABLE_SIZE];
struct StackFrame *PreviousStackFrame; /* the next lower stack frame */ struct StackFrame *PreviousStackFrame; /* the next lower stack frame */
@ -188,49 +187,38 @@ extern struct ValueType FPType;
extern struct ValueType VoidType; extern struct ValueType VoidType;
extern struct ValueType FunctionType; extern struct ValueType FunctionType;
extern struct ValueType MacroType; extern struct ValueType MacroType;
extern Str StrEmpty;
/* str.c */
void StrToC(char *Dest, int DestSize, const Str *Source);
void StrFromC(Str *Dest, const char *Source);
int StrEqual(const Str *Str1, const Str *Str2);
int StrEqualC(const Str *Str1, const char *Str2);
void StrPrintf(const char *Format, ...);
void vStrPrintf(const char *Format, va_list Args);
/* picoc.c */ /* picoc.c */
void Fail(const char *Message, ...); void ProgramFail(struct ParseState *Parser, const char *Message, ...);
void ProgramFail(struct LexState *Lexer, const char *Message, ...); void ScanFile(const char *FileName);
void ScanFile(const Str *FileName);
/* table.c */ /* table.c */
void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap); void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int OnHeap);
int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val); int TableSet(struct Table *Tbl, const char *Key, struct Value *Val);
int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val); int TableGet(struct Table *Tbl, const char *Key, struct Value **Val);
const char *TableSetKey(struct Table *Tbl, const char *Ident, int IdentLen);
/* lex.c */ /* lex.c */
void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line); void LexInit(struct ParseState *Parser, const char *Source, int SourceLen, const char *FileName, int Line);
enum LexToken LexGetToken(struct LexState *Lexer, struct Value **Value); enum LexToken LexGetToken(struct ParseState *Parser, struct Value **Value, int IncPos);
enum LexToken LexGetPlainToken(struct LexState *Lexer); void LexToEndOfLine(struct ParseState *Parser);
enum LexToken LexPeekToken(struct LexState *Lexer, struct Value **Value);
enum LexToken LexPeekPlainToken(struct LexState *Lexer);
void LexToEndOfLine(struct LexState *Lexer);
/* parse.c */ /* parse.c */
void ParseInit(void); void ParseInit(void);
int ParseExpression(struct LexState *Lexer, struct Value **Result, int ResultOnHeap, int RunIt); int ParseExpression(struct ParseState *Parser, struct Value **Result, int ResultOnHeap, int RunIt);
int ParseIntExpression(struct LexState *Lexer, int RunIt); int ParseIntExpression(struct ParseState *Parser, int RunIt);
void Parse(const Str *FileName, const Str *Source, int RunIt); int ParseStatement(struct ParseState *Parser, int RunIt);
void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt);
/* type.c */ /* type.c */
void TypeInit(); void TypeInit();
int TypeSizeof(struct ValueType *Typ); int TypeSizeof(struct ValueType *Typ);
void TypeParse(struct LexState *Lexer, struct ValueType **Typ, Str *Identifier); void TypeParse(struct ParseState *Parser, struct ValueType **Typ, const char **Identifier);
/* intrinsic.c */ /* intrinsic.c */
void IntrinsicInit(struct Table *GlobalTable); void IntrinsicInit(struct Table *GlobalTable);
void IntrinsicGetLexer(struct LexState *Lexer, int IntrinsicId); void IntrinsicGetLexer(struct ParseState *Parser, int IntrinsicId);
void IntrinsicCall(struct LexState *Lexer, struct Value *Result, struct ValueType *ReturnType, int IntrinsicId); void IntrinsicCall(struct ParseState *Parser, struct Value *Result, struct ValueType *ReturnType, int IntrinsicId);
/* heap.c */ /* heap.c */
void HeapInit(); void HeapInit();
@ -243,15 +231,20 @@ void HeapFree(void *Mem);
/* variable.c */ /* variable.c */
void VariableInit(); void VariableInit();
void *VariableAlloc(struct LexState *Lexer, int Size, int OnHeap); void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap);
void VariableStackPop(struct LexState *Lexer, struct Value *Var); void VariableStackPop(struct ParseState *Parser, struct Value *Var);
struct Value *VariableAllocValueAndData(struct LexState *Lexer, int DataSize, int OnHeap); struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, int OnHeap);
struct Value *VariableAllocValueAndCopy(struct LexState *Lexer, struct Value *FromValue, int OnHeap); struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap);
struct Value *VariableAllocValueFromType(struct LexState *Lexer, struct ValueType *Typ, int OnHeap); struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int OnHeap);
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue); void VariableDefine(struct ParseState *Parser, const char *Ident, struct Value *InitValue);
int VariableDefined(Str *Ident); int VariableDefined(const char *Ident);
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value **LVal); void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal);
void VariableStackFrameAdd(struct LexState *Lexer); void VariableStackFrameAdd(struct ParseState *Parser);
void VariableStackFramePop(struct LexState *Lexer); void VariableStackFramePop(struct ParseState *Parser);
/* str.c */
void StrInit();
const char *StrRegister(const char *Str);
const char *StrRegister2(const char *Str, int Len);
#endif /* PICOC_H */ #endif /* PICOC_H */

37
str.c
View file

@ -1,41 +1,29 @@
/* maintains a shared string table so we don't have to worry about string allocation */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <math.h> #include <math.h>
#include "picoc.h" #include "picoc.h"
Str StrEmpty = { 0, "" }; struct Table StringTable;
struct TableEntry *StringHashTable[STRING_TABLE_SIZE];
/* convert a Str to a C string */ /* initialise the shared string system */
void StrToC(char *Dest, int DestSize, const Str *Source) void StrInit()
{ {
int CopyLen = min(DestSize-1, Source->Len); TableInit(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE);
memcpy(Dest, Source->Str, CopyLen);
Dest[CopyLen] = '\0';
} }
/* convert a C string to a Str */ /* register a string in the shared string store */
void StrFromC(Str *Dest, const char *Source) const char *StrRegister2(const char *Str, int Len)
{ {
Dest->Str = Source; return TableSetKey(&StringTable, Str, Len);
Dest->Len = strlen(Source);
} }
/* compare two Strs for equality */ const char *StrRegister(const char *Str)
int StrEqual(const Str *Str1, const Str *Str2)
{ {
if (Str1->Len != Str2->Len) return StrRegister2(Str, strlen(Str));
return FALSE;
return memcmp(Str1->Str, Str2->Str, Str1->Len) == 0;
}
/* compare a Str to a C string */
int StrEqualC(const Str *Str1, const char *Str2)
{
return strncmp(Str1->Str, Str2, Str1->Len) == 0 && Str2[Str1->Len] == '\0';
} }
/* print an integer to a stream without using printf/sprintf */ /* print an integer to a stream without using printf/sprintf */
@ -93,6 +81,7 @@ void StrPrintFP(double Num, FILE *Stream)
} }
} }
#if 0
/* Str version of printf */ /* Str version of printf */
void StrPrintf(const char *Format, ...) void StrPrintf(const char *Format, ...)
{ {
@ -128,3 +117,5 @@ void vStrPrintf(const char *Format, va_list Args)
putchar(*FPos); putchar(*FPos);
} }
} }
#endif

48
table.c
View file

@ -2,12 +2,12 @@
#include "picoc.h" #include "picoc.h"
/* quick hash function */ /* quick hash function */
static unsigned int TableHash(const Str *Key) static unsigned int TableHash(const char *Key, int KeyLen)
{ {
if (Key->Len == 0) if (KeyLen == 0)
return 0; return 0;
else else
return ((*Key->Str << 24) | (Key->Str[Key->Len-1] << 16) | (Key->Str[Key->Len >> 1] << 8)) ^ Key->Len; return ((*Key << 24) | (Key[KeyLen-1] << 16) | (Key[KeyLen >> 1] << 8)) ^ KeyLen;
} }
/* initialise a table */ /* initialise a table */
@ -20,14 +20,14 @@ void TableInit(struct Table *Tbl, struct TableEntry **HashTable, int Size, int O
} }
/* check a hash table entry for a key */ /* check a hash table entry for a key */
static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt) static int TableSearch(struct Table *Tbl, const char *Key, int Len, int *AddAt)
{ {
struct TableEntry *Entry; struct TableEntry *Entry;
int HashValue = TableHash(Key) % Tbl->Size;; int HashValue = TableHash(Key, Len) % Tbl->Size;
for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next) for (Entry = Tbl->HashTable[HashValue]; Entry != NULL; Entry = Entry->Next)
{ {
if (StrEqual(&Entry->Key, Key)) if (strncmp(Entry->Key, Key, Len) == 0 && Entry->Key[Len] == '\0')
return HashValue; /* found */ return HashValue; /* found */
} }
@ -36,17 +36,16 @@ static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt)
} }
/* set an identifier to a value. returns FALSE if it already exists */ /* set an identifier to a value. returns FALSE if it already exists */
int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val) int TableSet(struct Table *Tbl, const char *Key, struct Value *Val)
{ {
int HashPos;
int AddAt; int AddAt;
int KeyLen = strlen(Key);
int HashPos = TableSearch(Tbl, Key, KeyLen, &AddAt);
HashPos = TableSearch(Tbl, Key, &AddAt);
if (HashPos == -1) if (HashPos == -1)
{ /* add it to the table */ { /* add it to the table */
struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap); struct TableEntry *NewEntry = VariableAlloc(NULL, sizeof(struct TableEntry), Tbl->OnHeap);
NewEntry->Key = *Key; NewEntry->Key = Key;
NewEntry->Val = Val; NewEntry->Val = Val;
NewEntry->Next = Tbl->HashTable[AddAt]; NewEntry->Next = Tbl->HashTable[AddAt];
Tbl->HashTable[AddAt] = NewEntry; Tbl->HashTable[AddAt] = NewEntry;
@ -57,16 +56,33 @@ int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val)
} }
/* find a value in a table. returns FALSE if not found */ /* find a value in a table. returns FALSE if not found */
int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val) int TableGet(struct Table *Tbl, const char *Key, struct Value **Val)
{ {
int HashPos;
int AddAt; int AddAt;
int HashPos = TableSearch(Tbl, Key, strlen(Key), &AddAt);
HashPos = TableSearch(Tbl, Key, &AddAt);
if (HashPos == -1) if (HashPos == -1)
return FALSE; return FALSE;
*Val = Tbl->HashTable[HashPos]->Val; *Val = Tbl->HashTable[HashPos]->Val;
return TRUE; return TRUE;
} }
/* set an identifier and return the identifier. share if possible */
const char *TableSetKey(struct Table *Tbl, const char *Ident, int IdentLen)
{
int AddAt;
int HashPos = TableSearch(Tbl, Ident, IdentLen, &AddAt);
if (HashPos != -1)
return Tbl->HashTable[HashPos]->Key;
else
{ /* add it to the table */
struct TableEntry *NewEntry = HeapAlloc(sizeof(struct TableEntry) + IdentLen + 1);
NewEntry->Key = (void *)NewEntry + sizeof(struct TableEntry);
strncpy((char *)NewEntry->Key, Ident, IdentLen);
NewEntry->Val = NULL;
NewEntry->Next = Tbl->HashTable[AddAt];
Tbl->HashTable[AddAt] = NewEntry;
return NewEntry->Key;
}
}

View file

@ -18,7 +18,7 @@ void VariableInit()
} }
/* allocate some memory, either on the heap or the stack and check if we've run out */ /* allocate some memory, either on the heap or the stack and check if we've run out */
void *VariableAlloc(struct LexState *Lexer, int Size, int OnHeap) void *VariableAlloc(struct ParseState *Parser, int Size, int OnHeap)
{ {
void *NewValue; void *NewValue;
@ -28,15 +28,15 @@ void *VariableAlloc(struct LexState *Lexer, int Size, int OnHeap)
NewValue = HeapAllocStack(Size); NewValue = HeapAllocStack(Size);
if (NewValue == NULL) if (NewValue == NULL)
ProgramFail(Lexer, "out of memory"); ProgramFail(Parser, "out of memory");
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack using space dependent on what type we want */ /* allocate a value either on the heap or the stack using space dependent on what type we want */
struct Value *VariableAllocValueAndData(struct LexState *Lexer, int DataSize, int OnHeap) struct Value *VariableAllocValueAndData(struct ParseState *Parser, int DataSize, int OnHeap)
{ {
struct Value *NewValue = VariableAlloc(Lexer, DataSize, OnHeap); struct Value *NewValue = VariableAlloc(Parser, DataSize, OnHeap);
NewValue->Val = (union AnyValue *)((void *)NewValue + sizeof(struct Value)); NewValue->Val = (union AnyValue *)((void *)NewValue + sizeof(struct Value));
NewValue->ValOnHeap = OnHeap; NewValue->ValOnHeap = OnHeap;
NewValue->ValOnStack = !OnHeap; NewValue->ValOnStack = !OnHeap;
@ -45,31 +45,31 @@ struct Value *VariableAllocValueAndData(struct LexState *Lexer, int DataSize, in
} }
/* allocate a value given its type */ /* allocate a value given its type */
struct Value *VariableAllocValueFromType(struct LexState *Lexer, struct ValueType *Typ, int OnHeap) struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct ValueType *Typ, int OnHeap)
{ {
struct Value *NewValue = VariableAllocValueAndData(Lexer, Typ->Sizeof, OnHeap); struct Value *NewValue = VariableAllocValueAndData(Parser, Typ->Sizeof, OnHeap);
NewValue->Typ = Typ; NewValue->Typ = Typ;
return NewValue; return NewValue;
} }
/* allocate a value either on the heap or the stack and copy its value */ /* allocate a value either on the heap or the stack and copy its value */
struct Value *VariableAllocValueAndCopy(struct LexState *Lexer, struct Value *FromValue, int OnHeap) struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap)
{ {
struct Value *NewValue = VariableAllocValueAndData(Lexer, FromValue->Typ->Sizeof, OnHeap); struct Value *NewValue = VariableAllocValueAndData(Parser, FromValue->Typ->Sizeof, OnHeap);
NewValue->Typ = FromValue->Typ; NewValue->Typ = FromValue->Typ;
memcpy(NewValue->Val, FromValue->Val, FromValue->Typ->Sizeof); memcpy(NewValue->Val, FromValue->Val, FromValue->Typ->Sizeof);
return NewValue; return NewValue;
} }
/* define a variable */ /* define a variable */
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue) void VariableDefine(struct ParseState *Parser, const char *Ident, struct Value *InitValue)
{ {
if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, VariableAllocValueAndCopy(Lexer, InitValue, TopStackFrame == NULL))) if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL)))
ProgramFail(Lexer, "'%S' is already defined", Ident); ProgramFail(Parser, "'%S' is already defined", Ident);
} }
/* check if a variable with a given name is defined */ /* check if a variable with a given name is defined */
int VariableDefined(Str *Ident) int VariableDefined(const char *Ident)
{ {
struct Value *FoundValue; struct Value *FoundValue;
@ -83,17 +83,17 @@ int VariableDefined(Str *Ident)
} }
/* get the value of a variable. must be defined */ /* get the value of a variable. must be defined */
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value **LVal) void VariableGet(struct ParseState *Parser, const char *Ident, struct Value **LVal)
{ {
if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal)) if (TopStackFrame == NULL || !TableGet(&TopStackFrame->LocalTable, Ident, LVal))
{ {
if (!TableGet(&GlobalTable, Ident, LVal)) if (!TableGet(&GlobalTable, Ident, LVal))
ProgramFail(Lexer, "'%S' is undefined", Ident); ProgramFail(Parser, "'%S' is undefined", Ident);
} }
} }
/* free and/or pop the top value off the stack. Var must be the top value on the stack! */ /* free and/or pop the top value off the stack. Var must be the top value on the stack! */
void VariableStackPop(struct LexState *Lexer, struct Value *Var) void VariableStackPop(struct ParseState *Parser, struct Value *Var)
{ {
int Success; int Success;
@ -108,29 +108,29 @@ void VariableStackPop(struct LexState *Lexer, struct Value *Var)
Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */ Success = HeapPopStack(Var, sizeof(struct Value)); /* value isn't our problem */
if (!Success) if (!Success)
ProgramFail(Lexer, "stack underrun"); ProgramFail(Parser, "stack underrun");
} }
/* add a stack frame when doing a function call */ /* add a stack frame when doing a function call */
void VariableStackFrameAdd(struct LexState *Lexer) void VariableStackFrameAdd(struct ParseState *Parser)
{ {
struct StackFrame *NewFrame; struct StackFrame *NewFrame;
HeapPushStackFrame(); HeapPushStackFrame();
NewFrame = HeapAllocStack(sizeof(struct StackFrame)); NewFrame = HeapAllocStack(sizeof(struct StackFrame));
NewFrame->ReturnLex = *Lexer; NewFrame->ReturnParser = *Parser;
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE);
NewFrame->PreviousStackFrame = TopStackFrame; NewFrame->PreviousStackFrame = TopStackFrame;
TopStackFrame = NewFrame; TopStackFrame = NewFrame;
} }
/* remove a stack frame */ /* remove a stack frame */
void VariableStackFramePop(struct LexState *Lexer) void VariableStackFramePop(struct ParseState *Parser)
{ {
if (TopStackFrame == NULL) if (TopStackFrame == NULL)
ProgramFail(Lexer, "stack is empty - can't go back"); ProgramFail(Parser, "stack is empty - can't go back");
TopStackFrame = TopStackFrame->PreviousStackFrame; TopStackFrame = TopStackFrame->PreviousStackFrame;
*Lexer = TopStackFrame->ReturnLex; *Parser = TopStackFrame->ReturnParser;
HeapPopStackFrame(); HeapPopStackFrame();
} }