2008-10-12 20:53:28 -04:00
|
|
|
#include <stdio.h>
|
2008-12-18 19:22:52 -05:00
|
|
|
#include <string.h>
|
2008-10-12 20:53:28 -04:00
|
|
|
|
|
|
|
#include "picoc.h"
|
|
|
|
|
|
|
|
/* the table of global definitions */
|
|
|
|
struct Table GlobalTable;
|
|
|
|
struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE];
|
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
/* the table of function definitions */
|
|
|
|
struct LexState FunctionStore[FUNCTION_STORE_MAX];
|
|
|
|
int FunctionStoreUsed = 0;
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2008-12-21 21:29:19 -05:00
|
|
|
/* the stack */
|
|
|
|
struct StackFrame Stack[STACK_MAX];
|
|
|
|
int StackUsed = 0;
|
|
|
|
|
2008-12-23 21:30:29 -05:00
|
|
|
/* parameter passing area */
|
|
|
|
struct Value Parameter[PARAMETER_MAX];
|
|
|
|
int ParameterUsed = 0;
|
|
|
|
struct Value ReturnValue;
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* local prototypes */
|
2008-12-20 22:46:32 -05:00
|
|
|
int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt);
|
|
|
|
void ParseIntExpression(struct LexState *Lexer, struct Value *Result, int RunIt);
|
2008-12-20 20:36:09 -05:00
|
|
|
int ParseStatement(struct LexState *Lexer, int RunIt);
|
2008-12-23 21:30:29 -05:00
|
|
|
int ParseArguments(struct LexState *Lexer, int RunIt);
|
2008-10-14 00:51:34 -04:00
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
|
|
|
|
/* initialise the parser */
|
2008-10-12 20:53:28 -04:00
|
|
|
void ParseInit()
|
|
|
|
{
|
2008-12-21 21:29:19 -05:00
|
|
|
TableInit(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE);
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* define a variable */
|
2008-12-23 21:30:29 -05:00
|
|
|
void VariableDefine(struct LexState *Lexer, const Str *Ident, struct Value *InitValue)
|
2008-12-18 19:22:52 -05:00
|
|
|
{
|
2008-12-23 21:30:29 -05:00
|
|
|
if (!TableSet((StackUsed == 0) ? &GlobalTable : &Stack[StackUsed-1].LocalTable, Ident, InitValue))
|
2008-12-18 19:22:52 -05:00
|
|
|
ProgramFail(Lexer, "'%S' is already defined", Ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the value of a variable. must be defined */
|
2008-12-20 05:24:34 -05:00
|
|
|
void VariableGet(struct LexState *Lexer, Str *Ident, struct Value *Val, struct Value **LVal)
|
2008-12-18 19:22:52 -05:00
|
|
|
{
|
2008-12-21 21:29:19 -05:00
|
|
|
int Frame;
|
|
|
|
|
|
|
|
for (Frame = StackUsed-1; Frame >= 0; Frame--)
|
|
|
|
{
|
|
|
|
if (TableGet(&Stack[Frame].LocalTable, Ident, LVal))
|
|
|
|
{
|
|
|
|
*Val = **LVal;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-20 05:24:34 -05:00
|
|
|
if (!TableGet(&GlobalTable, Ident, LVal))
|
2008-12-18 19:22:52 -05:00
|
|
|
ProgramFail(Lexer, "'%S' is undefined", Ident);
|
|
|
|
|
2008-12-20 05:24:34 -05:00
|
|
|
*Val = **LVal;
|
2008-12-18 19:22:52 -05:00
|
|
|
}
|
|
|
|
|
2008-12-21 21:29:19 -05:00
|
|
|
/* add a stack frame when doing a function call */
|
|
|
|
void StackFrameAdd(struct LexState *Lexer)
|
|
|
|
{
|
|
|
|
struct StackFrame *NewFrame = &Stack[StackUsed];
|
|
|
|
|
|
|
|
if (StackUsed >= STACK_MAX)
|
|
|
|
ProgramFail(Lexer, "too many nested function calls");
|
|
|
|
|
|
|
|
NewFrame->ReturnLex = *Lexer;
|
|
|
|
TableInit(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE);
|
|
|
|
StackUsed++;
|
|
|
|
}
|
|
|
|
|
2008-12-23 21:30:29 -05:00
|
|
|
/* parse a type specification */
|
|
|
|
int ParseType(struct LexState *Lexer, enum ValueType *Typ)
|
|
|
|
{
|
|
|
|
struct LexState Before = *Lexer;
|
|
|
|
enum LexToken Token = LexGetPlainToken(Lexer);
|
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenIntType: case TokenCharType: *Typ = TypeInt; return TRUE;
|
|
|
|
case TokenVoidType: *Typ = TypeVoid; return TRUE;
|
|
|
|
default: *Lexer = Before; return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse a parameter list, defining parameters as local variables in the current scope */
|
|
|
|
void ParseParameterList(struct LexState *CallLexer, struct LexState *FuncLexer, int RunIt)
|
|
|
|
{
|
|
|
|
enum ValueType Typ;
|
|
|
|
union AnyValue Identifier;
|
2008-12-23 22:27:53 -05:00
|
|
|
enum LexToken Token = LexGetPlainToken(FuncLexer); /* open bracket */
|
2008-12-23 21:30:29 -05:00
|
|
|
int ParamCount;
|
|
|
|
|
2008-12-23 22:27:53 -05:00
|
|
|
for (ParamCount = 0; ParamCount < ParameterUsed; ParamCount++)
|
2008-12-23 21:30:29 -05:00
|
|
|
{
|
|
|
|
ParseType(FuncLexer, &Typ);
|
|
|
|
Token = LexGetToken(FuncLexer, &Identifier);
|
2008-12-23 22:27:53 -05:00
|
|
|
if (Token != TokenIdentifier)
|
|
|
|
ProgramFail(FuncLexer, "invalid parameter");
|
|
|
|
|
|
|
|
if (RunIt)
|
2008-12-23 21:30:29 -05:00
|
|
|
{
|
2008-12-23 22:27:53 -05:00
|
|
|
if (Parameter[ParamCount].Typ != Typ)
|
|
|
|
ProgramFail(CallLexer, "parameter %d has the wrong type", ParamCount+1);
|
2008-12-23 21:30:29 -05:00
|
|
|
|
2008-12-23 22:27:53 -05:00
|
|
|
VariableDefine(FuncLexer, &Identifier.String, &Parameter[ParamCount]);
|
2008-12-23 21:30:29 -05:00
|
|
|
}
|
2008-12-23 22:27:53 -05:00
|
|
|
|
|
|
|
Token = LexGetPlainToken(FuncLexer);
|
2008-12-23 21:30:29 -05:00
|
|
|
if (Token != TokenComma && Token != TokenCloseBracket)
|
|
|
|
ProgramFail(FuncLexer, "comma expected");
|
2008-12-23 22:27:53 -05:00
|
|
|
}
|
|
|
|
if (ParameterUsed == 0)
|
|
|
|
Token = LexGetPlainToken(FuncLexer);
|
2008-12-23 21:30:29 -05:00
|
|
|
|
2008-12-23 22:27:53 -05:00
|
|
|
if (Token != TokenCloseBracket)
|
2008-12-23 21:30:29 -05:00
|
|
|
ProgramFail(CallLexer, "wrong number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do a function call */
|
|
|
|
void ParseFunctionCall(struct LexState *Lexer, struct Value *Result, Str *FuncName, int RunIt)
|
|
|
|
{
|
|
|
|
enum LexToken Token = LexGetPlainToken(Lexer); /* open bracket */
|
|
|
|
|
|
|
|
/* parse arguments */
|
|
|
|
ParameterUsed = 0;
|
|
|
|
do {
|
|
|
|
if (ParseExpression(Lexer, &Parameter[ParameterUsed], RunIt))
|
|
|
|
{
|
|
|
|
if (RunIt && ParameterUsed >= PARAMETER_MAX)
|
|
|
|
ProgramFail(Lexer, "too many arguments");
|
|
|
|
|
|
|
|
ParameterUsed++;
|
|
|
|
Token = LexGetPlainToken(Lexer);
|
|
|
|
if (Token != TokenComma && Token != TokenCloseBracket)
|
|
|
|
ProgramFail(Lexer, "comma expected");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Token = LexGetPlainToken(Lexer);
|
2008-12-23 22:27:53 -05:00
|
|
|
if (!TokenCloseBracket)
|
2008-12-23 21:30:29 -05:00
|
|
|
ProgramFail(Lexer, "bad argument");
|
|
|
|
}
|
|
|
|
} while (Token != TokenCloseBracket);
|
|
|
|
|
|
|
|
if (RunIt)
|
|
|
|
{
|
|
|
|
struct LexState FuncLexer;
|
|
|
|
enum ValueType ReturnType;
|
|
|
|
struct Value *LValue;
|
|
|
|
|
|
|
|
VariableGet(Lexer, FuncName, Result, &LValue);
|
|
|
|
if (Result->Typ != TypeFunction)
|
|
|
|
ProgramFail(Lexer, "not a function - can't call");
|
|
|
|
|
|
|
|
StackFrameAdd(Lexer);
|
|
|
|
FuncLexer = FunctionStore[Result->Val.Integer];
|
|
|
|
ParseType(&FuncLexer, &ReturnType); /* return type */
|
|
|
|
Result->Typ = TypeVoid;
|
|
|
|
LexGetPlainToken(&FuncLexer); /* function name again */
|
|
|
|
ParseParameterList(Lexer, &FuncLexer, TRUE); /* parameters */
|
|
|
|
if (LexPeekPlainToken(&FuncLexer) != TokenLeftBrace || !ParseStatement(&FuncLexer, TRUE))
|
|
|
|
ProgramFail(&FuncLexer, "function body expected");
|
|
|
|
|
|
|
|
if (ReturnType != Result->Typ)
|
|
|
|
ProgramFail(&FuncLexer, "bad return value");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* parse a single value */
|
2008-12-20 22:46:32 -05:00
|
|
|
int ParseValue(struct LexState *Lexer, struct Value *Result, struct Value **LValue, int RunIt)
|
2008-10-16 03:04:23 -04:00
|
|
|
{
|
2008-11-21 21:56:08 -05:00
|
|
|
struct LexState PreState = *Lexer;
|
2008-12-20 20:36:09 -05:00
|
|
|
enum LexToken Token = LexGetToken(Lexer, &Result->Val);
|
2008-12-20 05:24:34 -05:00
|
|
|
*LValue = NULL;
|
2008-10-16 03:04:23 -04:00
|
|
|
|
2008-11-21 21:56:08 -05:00
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenIntegerConstant: case TokenCharacterConstant: case TokenStringConstant:
|
|
|
|
Result->Typ = TypeInt;
|
|
|
|
if (Token == TokenStringConstant)
|
|
|
|
Result->Typ = TypeString;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, Result, RunIt);
|
2008-12-18 19:22:52 -05:00
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (RunIt)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
2008-12-20 22:46:32 -05:00
|
|
|
switch(Token)
|
|
|
|
{
|
|
|
|
case TokenMinus: Result->Val.Integer = -(Result->Val.Integer); break;
|
|
|
|
case TokenUnaryExor: Result->Val.Integer = ~(Result->Val.Integer); break;
|
|
|
|
case TokenUnaryNot: Result->Val.Integer = !(Result->Val.Integer); break;
|
|
|
|
default: break;
|
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenOpenBracket:
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseExpression(Lexer, Result, RunIt))
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "invalid expression");
|
|
|
|
|
2008-12-22 06:52:31 -05:00
|
|
|
if (LexGetPlainToken(Lexer) != TokenCloseBracket)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "')' expected");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenAsterisk:
|
|
|
|
case TokenAmpersand:
|
|
|
|
ProgramFail(Lexer, "not implemented");
|
|
|
|
|
|
|
|
case TokenIdentifier:
|
2008-12-23 21:30:29 -05:00
|
|
|
if (LexPeekPlainToken(Lexer) == TokenOpenBracket)
|
|
|
|
ParseFunctionCall(Lexer, Result, &Result->Val.String, RunIt);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (RunIt)
|
|
|
|
VariableGet(Lexer, &Result->Val.String, Result, LValue);
|
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
*Lexer = PreState;
|
2008-12-20 05:24:34 -05:00
|
|
|
return FALSE;
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
2008-10-16 03:04:23 -04:00
|
|
|
|
2008-11-21 21:56:08 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* parse an expression. operator precedence is not supported */
|
2008-12-20 22:46:32 -05:00
|
|
|
int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
|
|
|
struct Value CurrentValue;
|
2008-12-20 05:24:34 -05:00
|
|
|
struct Value *CurrentLValue;
|
2008-11-21 21:56:08 -05:00
|
|
|
struct Value TotalValue;
|
2008-12-20 05:24:34 -05:00
|
|
|
struct Value *TotalLValue;
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseValue(Lexer, &TotalValue, &TotalLValue, RunIt))
|
2008-11-21 21:56:08 -05:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
while (TRUE)
|
2008-10-16 03:04:23 -04:00
|
|
|
{
|
2008-12-20 20:36:09 -05:00
|
|
|
enum LexToken Token = LexPeekToken(Lexer, &CurrentValue.Val);
|
2008-11-21 21:56:08 -05:00
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
|
|
|
|
case TokenEquality: case TokenLessThan: case TokenGreaterThan:
|
|
|
|
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
|
2008-12-20 05:24:34 -05:00
|
|
|
case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr:
|
|
|
|
case TokenArithmeticExor: case TokenDot:
|
2008-12-22 06:52:31 -05:00
|
|
|
LexGetPlainToken(Lexer);
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
2008-12-20 05:24:34 -05:00
|
|
|
|
|
|
|
case TokenAssign: case TokenAddAssign: case TokenSubtractAssign:
|
2008-12-22 06:52:31 -05:00
|
|
|
LexGetPlainToken(Lexer);
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseExpression(Lexer, &CurrentValue, RunIt))
|
2008-12-20 05:24:34 -05:00
|
|
|
ProgramFail(Lexer, "expression expected");
|
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (RunIt)
|
2008-12-20 05:24:34 -05:00
|
|
|
{
|
2008-12-20 22:46:32 -05:00
|
|
|
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
|
|
|
ProgramFail(Lexer, "can't assign");
|
|
|
|
|
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenAddAssign: TotalValue.Val.Integer += CurrentValue.Val.Integer; break;
|
|
|
|
case TokenSubtractAssign: TotalValue.Val.Integer -= CurrentValue.Val.Integer; break;
|
|
|
|
default: TotalValue.Val.Integer = CurrentValue.Val.Integer; printf("---> %d\n", TotalValue.Val.Integer); break;
|
|
|
|
}
|
|
|
|
*TotalLValue = TotalValue;
|
2008-12-20 05:24:34 -05:00
|
|
|
}
|
|
|
|
// fallthrough
|
2008-11-21 21:56:08 -05:00
|
|
|
|
|
|
|
default:
|
2008-12-20 22:46:32 -05:00
|
|
|
if (RunIt)
|
|
|
|
*Result = TotalValue;
|
2008-11-21 21:56:08 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseValue(Lexer, &CurrentValue, &CurrentLValue, RunIt))
|
2008-11-21 21:56:08 -05:00
|
|
|
return FALSE;
|
2008-12-20 05:24:34 -05:00
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (RunIt)
|
2008-10-16 03:04:23 -04:00
|
|
|
{
|
2008-12-20 22:46:32 -05:00
|
|
|
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
|
|
|
ProgramFail(Lexer, "bad operand types");
|
|
|
|
|
|
|
|
switch (Token)
|
|
|
|
{
|
|
|
|
case TokenPlus: TotalValue.Val.Integer += CurrentValue.Val.Integer; break;
|
|
|
|
case TokenMinus: TotalValue.Val.Integer -= CurrentValue.Val.Integer; break;
|
|
|
|
case TokenAsterisk: TotalValue.Val.Integer *= CurrentValue.Val.Integer; break;
|
|
|
|
case TokenSlash: TotalValue.Val.Integer /= CurrentValue.Val.Integer; break;
|
|
|
|
case TokenEquality: TotalValue.Val.Integer = TotalValue.Val.Integer == CurrentValue.Val.Integer; break;
|
|
|
|
case TokenLessThan: TotalValue.Val.Integer = TotalValue.Val.Integer < CurrentValue.Val.Integer; break;
|
|
|
|
case TokenGreaterThan: TotalValue.Val.Integer = TotalValue.Val.Integer > CurrentValue.Val.Integer; break;
|
|
|
|
case TokenLessEqual: printf("compare %d <= %d\n", TotalValue.Val.Integer, CurrentValue.Val.Integer); TotalValue.Val.Integer = TotalValue.Val.Integer <= CurrentValue.Val.Integer; break;
|
|
|
|
case TokenGreaterEqual: TotalValue.Val.Integer = TotalValue.Val.Integer >= CurrentValue.Val.Integer; break;
|
|
|
|
case TokenLogicalAnd: TotalValue.Val.Integer = TotalValue.Val.Integer && CurrentValue.Val.Integer; break;
|
|
|
|
case TokenLogicalOr: 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 TokenArithmeticExor: TotalValue.Val.Integer = TotalValue.Val.Integer ^ CurrentValue.Val.Integer; break;
|
|
|
|
case TokenDot: ProgramFail(Lexer, "operator not supported"); break;
|
|
|
|
default: break;
|
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* parse an expression. operator precedence is not supported */
|
2008-12-20 22:46:32 -05:00
|
|
|
void ParseIntExpression(struct LexState *Lexer, struct Value *Result, int RunIt)
|
2008-12-18 19:22:52 -05:00
|
|
|
{
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseExpression(Lexer, Result, RunIt))
|
2008-12-18 19:22:52 -05:00
|
|
|
ProgramFail(Lexer, "expression expected");
|
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
if (RunIt && Result->Typ != TypeInt)
|
2008-12-18 19:22:52 -05:00
|
|
|
ProgramFail(Lexer, "integer value expected");
|
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
/* parse a function definition and store it for later */
|
|
|
|
void ParseFunctionDefinition(struct LexState *Lexer, Str *Identifier, struct LexState *PreState)
|
2008-12-20 06:46:21 -05:00
|
|
|
{
|
2008-12-20 20:36:09 -05:00
|
|
|
struct Value FuncValue;
|
|
|
|
|
|
|
|
if (FunctionStoreUsed >= FUNCTION_STORE_MAX)
|
|
|
|
ProgramFail(Lexer, "too many functions defined");
|
|
|
|
FunctionStore[FunctionStoreUsed] = *PreState;
|
|
|
|
|
2008-12-22 06:52:31 -05:00
|
|
|
LexGetPlainToken(Lexer);
|
|
|
|
if (LexGetPlainToken(Lexer) != TokenCloseBracket || LexPeekToken(Lexer, &FuncValue.Val) != TokenLeftBrace)
|
2008-12-20 20:36:09 -05:00
|
|
|
ProgramFail(Lexer, "bad function definition");
|
|
|
|
|
|
|
|
if (!ParseStatement(Lexer, FALSE))
|
|
|
|
ProgramFail(Lexer, "function definition expected");
|
|
|
|
|
|
|
|
FunctionStore[FunctionStoreUsed].End = Lexer->Pos;
|
|
|
|
FuncValue.Typ = TypeFunction;
|
|
|
|
FuncValue.Val.Integer = FunctionStoreUsed;
|
|
|
|
FunctionStoreUsed++;
|
|
|
|
|
2008-12-20 22:13:25 -05:00
|
|
|
if (!TableSet(&GlobalTable, Identifier, &FuncValue))
|
2008-12-20 20:36:09 -05:00
|
|
|
ProgramFail(Lexer, "'%S' is already defined", Identifier);
|
2008-12-20 06:46:21 -05:00
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* parse a statement */
|
2008-11-21 21:56:08 -05:00
|
|
|
int ParseStatement(struct LexState *Lexer, int RunIt)
|
|
|
|
{
|
2008-12-18 19:22:52 -05:00
|
|
|
struct Value Conditional;
|
2008-11-21 21:56:08 -05:00
|
|
|
struct LexState PreState = *Lexer;
|
2008-12-20 20:36:09 -05:00
|
|
|
union AnyValue LexerValue;
|
2008-12-22 06:52:31 -05:00
|
|
|
enum ValueType Typ;
|
2008-12-20 20:36:09 -05:00
|
|
|
enum LexToken Token = LexGetToken(Lexer, &LexerValue);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
|
|
|
switch (Token)
|
|
|
|
{
|
2008-12-20 05:24:34 -05:00
|
|
|
case TokenEOF:
|
|
|
|
return FALSE;
|
|
|
|
|
2008-11-21 21:56:08 -05:00
|
|
|
case TokenIdentifier:
|
2008-12-20 06:46:21 -05:00
|
|
|
*Lexer = PreState;
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenLeftBrace:
|
|
|
|
while (ParseStatement(Lexer, RunIt))
|
|
|
|
{}
|
|
|
|
|
2008-12-22 06:52:31 -05:00
|
|
|
if (LexGetPlainToken(Lexer) != TokenRightBrace)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "'}' expected");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenIf:
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
if (!ParseStatement(Lexer, RunIt && Conditional.Val.Integer))
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
if (LexPeekToken(Lexer, &LexerValue) == TokenElse)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
2008-12-20 20:36:09 -05:00
|
|
|
LexGetToken(Lexer, &LexerValue);
|
2008-12-18 19:22:52 -05:00
|
|
|
if (!ParseStatement(Lexer, RunIt && !Conditional.Val.Integer))
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
}
|
2008-10-16 03:04:23 -04:00
|
|
|
break;
|
|
|
|
|
2008-11-21 21:56:08 -05:00
|
|
|
case TokenWhile:
|
2008-10-16 03:04:23 -04:00
|
|
|
{
|
2008-11-21 21:56:08 -05:00
|
|
|
struct LexState PreConditional = *Lexer;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
*Lexer = PreConditional;
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
if (!ParseStatement(Lexer, RunIt && Conditional.Val.Integer))
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
} while (RunIt && Conditional.Val.Integer);
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenDo:
|
|
|
|
{
|
|
|
|
struct LexState PreStatement = *Lexer;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
*Lexer = PreStatement;
|
|
|
|
if (!ParseStatement(Lexer, RunIt))
|
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
} while (Conditional.Val.Integer && RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenFor:
|
|
|
|
{
|
|
|
|
struct LexState PreConditional;
|
|
|
|
struct LexState PreIncrement;
|
|
|
|
struct LexState PreStatement;
|
|
|
|
struct LexState After;
|
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
if (LexGetToken(Lexer, &LexerValue) != TokenOpenBracket)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "'(' expected");
|
|
|
|
|
|
|
|
if (!ParseStatement(Lexer, RunIt))
|
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
|
|
|
|
PreConditional = *Lexer;
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
if (LexGetToken(Lexer, &LexerValue) != TokenSemicolon)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "';' expected");
|
|
|
|
|
|
|
|
PreIncrement = *Lexer;
|
|
|
|
ParseStatement(Lexer, FALSE);
|
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
if (LexGetToken(Lexer, &LexerValue) != TokenCloseBracket)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "')' expected");
|
|
|
|
|
|
|
|
PreStatement = *Lexer;
|
2008-12-20 22:46:32 -05:00
|
|
|
if (!ParseStatement(Lexer, RunIt && Conditional.Val.Integer))
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "statement expected");
|
|
|
|
|
|
|
|
After = *Lexer;
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
while (Conditional.Val.Integer && RunIt)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
|
|
|
*Lexer = PreIncrement;
|
|
|
|
ParseStatement(Lexer, TRUE);
|
|
|
|
|
|
|
|
*Lexer = PreConditional;
|
2008-12-20 22:46:32 -05:00
|
|
|
ParseIntExpression(Lexer, &Conditional, RunIt);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
if (Conditional.Val.Integer)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
|
|
|
*Lexer = PreStatement;
|
|
|
|
ParseStatement(Lexer, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*Lexer = After;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenSemicolon: break;
|
|
|
|
|
|
|
|
case TokenIntType:
|
|
|
|
case TokenCharType:
|
|
|
|
case TokenVoidType:
|
2008-12-22 06:52:31 -05:00
|
|
|
*Lexer = PreState;
|
|
|
|
ParseType(Lexer, &Typ);
|
2008-12-20 20:36:09 -05:00
|
|
|
if (LexGetToken(Lexer, &LexerValue) != TokenIdentifier)
|
2008-11-21 21:56:08 -05:00
|
|
|
ProgramFail(Lexer, "identifier expected");
|
|
|
|
|
2008-12-20 06:46:21 -05:00
|
|
|
/* handle function definitions */
|
2008-12-22 06:52:31 -05:00
|
|
|
if (LexPeekPlainToken(Lexer) == TokenOpenBracket)
|
2008-12-20 20:36:09 -05:00
|
|
|
ParseFunctionDefinition(Lexer, &LexerValue.String, &PreState);
|
2008-12-20 06:46:21 -05:00
|
|
|
else
|
2008-12-23 21:30:29 -05:00
|
|
|
{
|
|
|
|
struct Value InitValue;
|
|
|
|
InitValue.Val.Integer = 0;
|
|
|
|
InitValue.Typ = Typ;
|
|
|
|
VariableDefine(Lexer, &LexerValue.String, &InitValue);
|
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
2008-12-23 22:27:53 -05:00
|
|
|
|
|
|
|
case TokenDefault:
|
|
|
|
if (RunIt)
|
|
|
|
printf("Hello\n");
|
|
|
|
break;
|
2008-11-21 21:56:08 -05:00
|
|
|
|
|
|
|
default:
|
|
|
|
*Lexer = PreState;
|
|
|
|
return FALSE;
|
2008-10-16 03:04:23 -04:00
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-10-12 20:53:28 -04:00
|
|
|
/* quick scan a source file for definitions */
|
2008-12-20 05:24:34 -05:00
|
|
|
void Parse(const Str *FileName, const Str *Source, int RunIt)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
2008-10-14 00:51:34 -04:00
|
|
|
struct LexState Lexer;
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2008-10-14 00:51:34 -04:00
|
|
|
LexInit(&Lexer, Source, FileName, 1);
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2008-12-20 05:24:34 -05:00
|
|
|
while (ParseStatement(&Lexer, RunIt))
|
|
|
|
{}
|
|
|
|
|
|
|
|
if (Lexer.Pos != Lexer.End)
|
|
|
|
ProgramFail(&Lexer, "parse error");
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
|
|
|
|