2008-10-12 20:53:28 -04:00
|
|
|
#include "picoc.h"
|
|
|
|
|
2009-03-11 19:49:10 -04:00
|
|
|
/* a chunk of heap-allocated tokens we should cleanup when we're done */
|
|
|
|
static void *CleanupTokens = NULL;
|
|
|
|
|
|
|
|
/* deallocate any memory */
|
|
|
|
void ParseCleanup()
|
|
|
|
{
|
|
|
|
if (CleanupTokens != NULL)
|
|
|
|
HeapFree(CleanupTokens);
|
|
|
|
}
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
/* parse a statement, but only run it if Condition is TRUE */
|
|
|
|
int ParseStatementMaybeRun(struct ParseState *Parser, int Condition)
|
2009-03-03 05:53:45 -05:00
|
|
|
{
|
2009-03-08 03:56:28 -04:00
|
|
|
if (Parser->Mode != RunModeSkip && !Condition)
|
2009-03-04 05:09:56 -05:00
|
|
|
{
|
2009-03-08 03:56:28 -04:00
|
|
|
enum RunMode OldMode = Parser->Mode;
|
|
|
|
Parser->Mode = RunModeSkip;
|
|
|
|
int Result = ParseStatement(Parser);
|
|
|
|
Parser->Mode = OldMode;
|
|
|
|
return Result;
|
2009-03-03 05:53:45 -05:00
|
|
|
}
|
2009-03-08 03:56:28 -04:00
|
|
|
else
|
|
|
|
return ParseStatement(Parser);
|
2009-03-03 05:53:45 -05:00
|
|
|
}
|
|
|
|
|
2008-12-20 20:36:09 -05:00
|
|
|
/* parse a function definition and store it for later */
|
2009-02-20 21:35:52 -05:00
|
|
|
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier, int IsPrototype)
|
2008-12-20 06:46:21 -05:00
|
|
|
{
|
2009-02-02 06:08:36 -05:00
|
|
|
struct ValueType *ParamType;
|
2009-02-20 21:35:52 -05:00
|
|
|
char *ParamIdentifier;
|
2009-02-01 06:31:18 -05:00
|
|
|
enum LexToken Token;
|
|
|
|
struct Value *FuncValue;
|
|
|
|
struct ParseState ParamParser;
|
2009-03-07 01:17:11 -05:00
|
|
|
struct ParseState FuncBody;
|
2009-02-01 06:31:18 -05:00
|
|
|
int ParamCount = 0;
|
2008-12-20 20:36:09 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
|
|
|
ParamParser = *Parser;
|
|
|
|
Token = LexGetToken(Parser, NULL, TRUE);
|
|
|
|
if (Token != TokenCloseBracket && Token != TokenEOF)
|
|
|
|
{ /* count the number of parameters */
|
|
|
|
ParamCount++;
|
|
|
|
while ((Token = LexGetToken(Parser, NULL, TRUE)) != TokenCloseBracket && Token != TokenEOF)
|
|
|
|
{
|
|
|
|
if (Token == TokenComma)
|
|
|
|
ParamCount++;
|
|
|
|
}
|
|
|
|
}
|
2009-02-02 06:08:36 -05:00
|
|
|
if (ParamCount > PARAMETER_MAX)
|
|
|
|
ProgramFail(Parser, "too many parameters");
|
2008-12-20 20:36:09 -05:00
|
|
|
|
2009-02-26 04:56:22 -05:00
|
|
|
FuncValue = VariableAllocValueAndData(Parser, sizeof(struct FuncDef) + sizeof(struct ValueType *) * ParamCount + sizeof(const char *) * ParamCount, FALSE, NULL, TRUE);
|
2009-01-21 04:02:05 -05:00
|
|
|
FuncValue->Typ = &FunctionType;
|
2009-02-01 06:31:18 -05:00
|
|
|
FuncValue->Val->FuncDef.ReturnType = ReturnType;
|
|
|
|
FuncValue->Val->FuncDef.NumParams = ParamCount;
|
2009-02-20 04:04:45 -05:00
|
|
|
FuncValue->Val->FuncDef.VarArgs = FALSE;
|
2009-02-01 06:31:18 -05:00
|
|
|
FuncValue->Val->FuncDef.ParamType = (void *)FuncValue->Val + sizeof(struct FuncDef);
|
|
|
|
FuncValue->Val->FuncDef.ParamName = (void *)FuncValue->Val->FuncDef.ParamType + sizeof(struct ValueType *) * ParamCount;
|
|
|
|
|
|
|
|
for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++)
|
|
|
|
{ /* harvest the parameters into the function definition */
|
2009-02-20 04:04:45 -05:00
|
|
|
if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, FALSE) == TokenEllipsis)
|
|
|
|
{ /* ellipsis at end */
|
|
|
|
FuncValue->Val->FuncDef.NumParams--;
|
|
|
|
FuncValue->Val->FuncDef.VarArgs = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* add a parameter */
|
|
|
|
TypeParse(&ParamParser, &ParamType, &ParamIdentifier);
|
|
|
|
FuncValue->Val->FuncDef.ParamType[ParamCount] = ParamType;
|
|
|
|
FuncValue->Val->FuncDef.ParamName[ParamCount] = ParamIdentifier;
|
|
|
|
}
|
2009-02-01 06:31:18 -05:00
|
|
|
|
2009-02-02 06:08:36 -05:00
|
|
|
Token = LexGetToken(&ParamParser, NULL, TRUE);
|
2009-02-20 04:04:45 -05:00
|
|
|
if (Token != TokenComma && ParamCount < FuncValue->Val->FuncDef.NumParams-1)
|
2009-02-02 06:08:36 -05:00
|
|
|
ProgramFail(&ParamParser, "comma expected");
|
2009-02-01 06:31:18 -05:00
|
|
|
}
|
|
|
|
|
2009-02-01 22:27:05 -05:00
|
|
|
if (!IsPrototype)
|
|
|
|
{
|
|
|
|
if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace)
|
|
|
|
ProgramFail(Parser, "bad function definition");
|
|
|
|
|
2009-03-07 01:17:11 -05:00
|
|
|
FuncBody = *Parser;
|
2009-02-18 03:19:06 -05:00
|
|
|
if (!ParseStatementMaybeRun(Parser, FALSE))
|
2009-02-01 22:27:05 -05:00
|
|
|
ProgramFail(Parser, "function definition expected");
|
2009-03-07 01:17:11 -05:00
|
|
|
|
|
|
|
FuncValue->Val->FuncDef.Body = FuncBody;
|
|
|
|
FuncValue->Val->FuncDef.Body.Pos = LexCopyTokens(&FuncBody, Parser);
|
2009-02-01 22:27:05 -05:00
|
|
|
}
|
|
|
|
|
2009-01-21 04:02:05 -05:00
|
|
|
if (!TableSet(&GlobalTable, Identifier, FuncValue))
|
2009-02-02 06:08:36 -05:00
|
|
|
ProgramFail(Parser, "'%s' is already defined", Identifier);
|
2009-02-01 22:27:05 -05:00
|
|
|
|
|
|
|
return FuncValue;
|
2008-12-20 06:46:21 -05:00
|
|
|
}
|
|
|
|
|
2009-03-05 23:55:11 -05:00
|
|
|
/* declare a variable or function */
|
|
|
|
void ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|
|
|
{
|
|
|
|
char *Identifier;
|
2009-03-06 01:00:51 -05:00
|
|
|
struct ValueType *BasicType;
|
2009-03-05 23:55:11 -05:00
|
|
|
struct ValueType *Typ;
|
|
|
|
struct Value *CValue;
|
|
|
|
|
2009-03-06 01:00:51 -05:00
|
|
|
TypeParseFront(Parser, &BasicType);
|
|
|
|
do
|
2009-03-05 23:55:11 -05:00
|
|
|
{
|
2009-03-06 01:00:51 -05:00
|
|
|
TypeParseIdentPart(Parser, BasicType, &Typ, &Identifier);
|
2009-03-10 04:03:10 -04:00
|
|
|
if ((Token != TokenVoidType && Token != TokenStructType && Token != TokenUnionType && Token != TokenEnumType) && Identifier == StrEmpty)
|
2009-03-06 01:00:51 -05:00
|
|
|
ProgramFail(Parser, "identifier expected");
|
|
|
|
|
|
|
|
if (Identifier != StrEmpty)
|
2009-03-05 23:55:11 -05:00
|
|
|
{
|
2009-03-06 01:00:51 -05:00
|
|
|
/* handle function definitions */
|
|
|
|
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
|
|
|
|
ParseFunctionDefinition(Parser, Typ, Identifier, FALSE);
|
2009-03-05 23:55:11 -05:00
|
|
|
else
|
2009-03-06 01:00:51 -05:00
|
|
|
{
|
2009-03-08 20:43:31 -04:00
|
|
|
if (Token == TokenVoidType && Identifier != StrEmpty)
|
|
|
|
ProgramFail(Parser, "can't define a void variable");
|
|
|
|
|
2009-03-06 01:00:51 -05:00
|
|
|
if (LexGetToken(Parser, NULL, FALSE) != TokenAssign)
|
|
|
|
VariableDefine(Parser, Identifier, VariableAllocValueFromType(Parser, Typ, TRUE, NULL));
|
|
|
|
else
|
|
|
|
{ /* we're assigning an initial value */
|
|
|
|
LexGetToken(Parser, NULL, TRUE);
|
2009-03-08 03:56:28 -04:00
|
|
|
if (!ExpressionParse(Parser, &CValue))
|
2009-03-06 01:00:51 -05:00
|
|
|
ProgramFail(Parser, "expression expected");
|
|
|
|
|
|
|
|
VariableDefine(Parser, Identifier, CValue);
|
|
|
|
if (Parser->Mode == RunModeRun)
|
|
|
|
VariableStackPop(Parser, CValue);
|
|
|
|
}
|
2009-03-05 23:55:11 -05:00
|
|
|
}
|
|
|
|
}
|
2009-03-06 01:00:51 -05:00
|
|
|
|
|
|
|
Token = LexGetToken(Parser, NULL, FALSE);
|
|
|
|
if (Token == TokenComma)
|
|
|
|
LexGetToken(Parser, NULL, TRUE);
|
|
|
|
|
|
|
|
} while (Token == TokenComma);
|
2009-03-05 23:55:11 -05:00
|
|
|
}
|
|
|
|
|
2009-01-04 23:28:54 -05:00
|
|
|
/* parse a #define macro definition and store it for later */
|
2009-02-01 06:31:18 -05:00
|
|
|
void ParseMacroDefinition(struct ParseState *Parser)
|
2009-01-04 23:28:54 -05:00
|
|
|
{
|
2009-01-26 03:57:32 -05:00
|
|
|
struct Value *MacroName;
|
2009-02-26 04:56:22 -05:00
|
|
|
struct Value *MacroValue = VariableAllocValueAndData(Parser, sizeof(struct ParseState), FALSE, NULL, TRUE);
|
2009-01-04 23:28:54 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
|
|
|
|
ProgramFail(Parser, "identifier expected");
|
2009-01-04 23:28:54 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
MacroValue->Val->Parser = *Parser;
|
2009-01-21 04:02:05 -05:00
|
|
|
MacroValue->Typ = &MacroType;
|
2009-03-07 01:17:11 -05:00
|
|
|
LexToEndOfLine(Parser);
|
|
|
|
MacroValue->Val->Parser.Pos = LexCopyTokens(&MacroValue->Val->Parser, Parser);
|
2009-01-04 23:28:54 -05:00
|
|
|
|
2009-02-20 21:35:52 -05:00
|
|
|
if (!TableSet(&GlobalTable, MacroName->Val->Identifier, MacroValue))
|
|
|
|
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier);
|
2009-01-04 23:28:54 -05:00
|
|
|
}
|
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
/* copy where we're at in the parsing */
|
|
|
|
void ParserCopyPos(struct ParseState *To, struct ParseState *From)
|
|
|
|
{
|
|
|
|
To->Pos = From->Pos;
|
|
|
|
To->Line = From->Line;
|
|
|
|
}
|
|
|
|
|
2009-02-12 07:15:25 -05:00
|
|
|
/* parse a "for" statement */
|
2009-02-18 03:19:06 -05:00
|
|
|
void ParseFor(struct ParseState *Parser)
|
2009-01-03 23:08:49 -05:00
|
|
|
{
|
2009-01-26 03:57:32 -05:00
|
|
|
int Condition;
|
2009-02-01 06:31:18 -05:00
|
|
|
struct ParseState PreConditional;
|
|
|
|
struct ParseState PreIncrement;
|
|
|
|
struct ParseState PreStatement;
|
|
|
|
struct ParseState After;
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
|
|
|
ProgramFail(Parser, "'(' expected");
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
if (!ParseStatement(Parser))
|
2009-02-01 06:31:18 -05:00
|
|
|
ProgramFail(Parser, "statement expected");
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(&PreConditional, Parser);
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon)
|
|
|
|
ProgramFail(Parser, "';' expected");
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(&PreIncrement, Parser);
|
2009-02-18 03:19:06 -05:00
|
|
|
ParseStatementMaybeRun(Parser, FALSE);
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
|
|
|
ProgramFail(Parser, "')' expected");
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(&PreStatement, Parser);
|
2009-02-18 03:19:06 -05:00
|
|
|
if (!ParseStatementMaybeRun(Parser, Condition))
|
2009-02-01 06:31:18 -05:00
|
|
|
ProgramFail(Parser, "statement expected");
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
if (Parser->Mode == RunModeContinue)
|
|
|
|
Parser->Mode = RunModeRun;
|
|
|
|
|
|
|
|
ParserCopyPos(&After, Parser);
|
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
while (Condition && Parser->Mode == RunModeRun)
|
2009-01-03 23:08:49 -05:00
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(Parser, &PreIncrement);
|
2009-02-18 03:19:06 -05:00
|
|
|
ParseStatement(Parser);
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(Parser, &PreConditional);
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-01-03 23:08:49 -05:00
|
|
|
|
2009-01-26 03:57:32 -05:00
|
|
|
if (Condition)
|
2009-01-03 23:08:49 -05:00
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(Parser, &PreStatement);
|
2009-02-18 03:19:06 -05:00
|
|
|
ParseStatement(Parser);
|
2009-02-19 04:07:00 -05:00
|
|
|
|
|
|
|
if (Parser->Mode == RunModeContinue)
|
|
|
|
Parser->Mode = RunModeRun;
|
2009-01-03 23:08:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
if (Parser->Mode == RunModeBreak)
|
|
|
|
Parser->Mode = RunModeRun;
|
|
|
|
|
|
|
|
ParserCopyPos(Parser, &After);
|
2009-01-03 23:08:49 -05:00
|
|
|
}
|
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
/* parse a block of code and return what mode it returned in */
|
|
|
|
enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition)
|
|
|
|
{
|
|
|
|
if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace)
|
|
|
|
ProgramFail(Parser, "'{' expected");
|
|
|
|
|
|
|
|
if (Parser->Mode != RunModeSkip && !Condition)
|
|
|
|
{ /* condition failed - skip this block instead */
|
|
|
|
enum RunMode OldMode = Parser->Mode;
|
|
|
|
Parser->Mode = RunModeSkip;
|
|
|
|
while (ParseStatement(Parser))
|
|
|
|
{}
|
|
|
|
Parser->Mode = OldMode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* just run it in its current mode */
|
|
|
|
while (ParseStatement(Parser))
|
|
|
|
{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace)
|
|
|
|
ProgramFail(Parser, "'}' expected");
|
|
|
|
|
|
|
|
return Parser->Mode;
|
|
|
|
}
|
|
|
|
|
2008-12-18 19:22:52 -05:00
|
|
|
/* parse a statement */
|
2009-02-18 03:19:06 -05:00
|
|
|
int ParseStatement(struct ParseState *Parser)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
2009-01-26 03:57:32 -05:00
|
|
|
struct Value *CValue;
|
2009-03-15 06:44:56 -04:00
|
|
|
struct Value *LexerValue;
|
2009-01-26 03:57:32 -05:00
|
|
|
int Condition;
|
2009-03-08 20:34:32 -04:00
|
|
|
int CheckTrailingSemicolon = TRUE;
|
2009-02-01 06:31:18 -05:00
|
|
|
struct ParseState PreState = *Parser;
|
|
|
|
enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
|
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:
|
2009-02-01 06:31:18 -05:00
|
|
|
*Parser = PreState;
|
2009-03-08 03:56:28 -04:00
|
|
|
ExpressionParse(Parser, &CValue);
|
2009-02-18 03:19:06 -05:00
|
|
|
if (Parser->Mode == RunModeRun)
|
2009-02-12 07:15:25 -05:00
|
|
|
VariableStackPop(Parser, CValue);
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenLeftBrace:
|
2009-02-19 04:07:00 -05:00
|
|
|
ParseBlock(Parser, FALSE, TRUE);
|
2009-03-09 22:18:17 -04:00
|
|
|
CheckTrailingSemicolon = FALSE;
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenIf:
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "'(' expected");
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "')' expected");
|
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
if (!ParseStatementMaybeRun(Parser, Condition))
|
2009-02-01 06:31:18 -05:00
|
|
|
ProgramFail(Parser, "statement expected");
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, NULL, FALSE) == TokenElse)
|
2008-11-21 21:56:08 -05:00
|
|
|
{
|
2009-02-01 06:31:18 -05:00
|
|
|
LexGetToken(Parser, NULL, TRUE);
|
2009-02-18 03:19:06 -05:00
|
|
|
if (!ParseStatementMaybeRun(Parser, !Condition))
|
2009-02-01 06:31:18 -05:00
|
|
|
ProgramFail(Parser, "statement expected");
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
2009-03-08 20:34:32 -04:00
|
|
|
CheckTrailingSemicolon = FALSE;
|
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
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
struct ParseState PreConditional;
|
|
|
|
ParserCopyPos(&PreConditional, Parser);
|
2008-11-21 21:56:08 -05:00
|
|
|
do
|
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(Parser, &PreConditional);
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-02-19 04:07:00 -05:00
|
|
|
ParseBlock(Parser, TRUE, Condition);
|
|
|
|
if (Parser->Mode == RunModeContinue)
|
|
|
|
Parser->Mode = RunModeRun;
|
|
|
|
|
|
|
|
} while (Parser->Mode == RunModeRun && Condition);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
if (Parser->Mode == RunModeBreak)
|
|
|
|
Parser->Mode = RunModeRun;
|
2009-03-08 20:34:32 -04:00
|
|
|
|
|
|
|
CheckTrailingSemicolon = FALSE;
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenDo:
|
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
struct ParseState PreStatement;
|
|
|
|
ParserCopyPos(&PreStatement, Parser);
|
2008-11-21 21:56:08 -05:00
|
|
|
do
|
|
|
|
{
|
2009-02-19 04:07:00 -05:00
|
|
|
ParserCopyPos(Parser, &PreStatement);
|
|
|
|
ParseBlock(Parser, TRUE, TRUE);
|
|
|
|
if (Parser->Mode == RunModeContinue)
|
|
|
|
Parser->Mode = RunModeRun;
|
|
|
|
|
2009-02-19 06:01:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenWhile)
|
|
|
|
ProgramFail(Parser, "'while' expected");
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
} while (Condition && Parser->Mode == RunModeRun);
|
2009-02-19 04:07:00 -05:00
|
|
|
|
|
|
|
if (Parser->Mode == RunModeBreak)
|
|
|
|
Parser->Mode = RunModeRun;
|
2008-11-21 21:56:08 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenFor:
|
2009-02-18 03:19:06 -05:00
|
|
|
ParseFor(Parser);
|
2009-03-08 20:34:32 -04:00
|
|
|
CheckTrailingSemicolon = FALSE;
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenSemicolon: break;
|
|
|
|
|
|
|
|
case TokenIntType:
|
|
|
|
case TokenCharType:
|
2008-12-26 21:25:49 -05:00
|
|
|
case TokenFloatType:
|
|
|
|
case TokenDoubleType:
|
2008-11-21 21:56:08 -05:00
|
|
|
case TokenVoidType:
|
2009-02-10 03:42:09 -05:00
|
|
|
case TokenStructType:
|
|
|
|
case TokenUnionType:
|
2009-03-09 18:36:01 -04:00
|
|
|
case TokenEnumType:
|
2009-02-01 06:31:18 -05:00
|
|
|
*Parser = PreState;
|
2009-03-05 23:55:11 -05:00
|
|
|
ParseDeclaration(Parser, Token);
|
2008-11-21 21:56:08 -05:00
|
|
|
break;
|
2008-12-23 22:27:53 -05:00
|
|
|
|
2009-01-03 23:08:49 -05:00
|
|
|
case TokenHashDefine:
|
2009-02-01 06:31:18 -05:00
|
|
|
ParseMacroDefinition(Parser);
|
2009-03-08 20:34:32 -04:00
|
|
|
CheckTrailingSemicolon = FALSE;
|
2009-01-03 23:08:49 -05:00
|
|
|
break;
|
|
|
|
|
2009-03-12 16:44:50 -04:00
|
|
|
#ifndef NO_HASH_INCLUDE
|
2009-01-03 23:08:49 -05:00
|
|
|
case TokenHashInclude:
|
2009-02-01 06:31:18 -05:00
|
|
|
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenStringConstant)
|
|
|
|
ProgramFail(Parser, "\"filename.h\" expected");
|
2009-01-04 23:38:19 -05:00
|
|
|
|
2009-03-09 21:01:57 -04:00
|
|
|
PlatformScanFile(LexerValue->Val->Pointer.Segment->Val->Array.Data);
|
2009-03-08 20:34:32 -04:00
|
|
|
CheckTrailingSemicolon = FALSE;
|
2009-01-04 23:38:19 -05:00
|
|
|
break;
|
2009-03-12 16:44:50 -04:00
|
|
|
#endif
|
2009-01-04 23:38:19 -05:00
|
|
|
|
2009-01-04 23:28:54 -05:00
|
|
|
case TokenSwitch:
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "'(' expected");
|
|
|
|
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-02-17 18:36:09 -05:00
|
|
|
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "')' expected");
|
|
|
|
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, FALSE) != TokenLeftBrace)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "'{' expected");
|
|
|
|
|
2009-02-18 06:03:14 -05:00
|
|
|
{ /* new block so we can store parser state */
|
2009-02-18 03:19:06 -05:00
|
|
|
enum RunMode OldMode = Parser->Mode;
|
|
|
|
int OldSearchLabel = Parser->SearchLabel;
|
|
|
|
Parser->Mode = RunModeCaseSearch;
|
|
|
|
Parser->SearchLabel = Condition;
|
|
|
|
|
2009-02-19 04:07:00 -05:00
|
|
|
ParseBlock(Parser, TRUE, TRUE);
|
2009-02-18 03:19:06 -05:00
|
|
|
|
|
|
|
Parser->Mode = OldMode;
|
|
|
|
Parser->SearchLabel = OldSearchLabel;
|
|
|
|
}
|
2009-03-08 20:34:32 -04:00
|
|
|
|
|
|
|
CheckTrailingSemicolon = FALSE;
|
2009-02-17 18:36:09 -05:00
|
|
|
break;
|
|
|
|
|
2009-01-04 23:28:54 -05:00
|
|
|
case TokenCase:
|
2009-02-19 04:07:00 -05:00
|
|
|
if (Parser->Mode == RunModeCaseSearch)
|
|
|
|
{
|
|
|
|
Parser->Mode = RunModeRun;
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-02-19 04:07:00 -05:00
|
|
|
Parser->Mode = RunModeCaseSearch;
|
|
|
|
}
|
|
|
|
else
|
2009-03-08 03:56:28 -04:00
|
|
|
Condition = ExpressionParseInt(Parser);
|
2009-02-19 04:07:00 -05:00
|
|
|
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenColon)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "':' expected");
|
2009-02-18 03:19:06 -05:00
|
|
|
|
|
|
|
if (Parser->Mode == RunModeCaseSearch && Condition == Parser->SearchLabel)
|
|
|
|
Parser->Mode = RunModeRun;
|
2009-03-08 20:34:32 -04:00
|
|
|
|
|
|
|
CheckTrailingSemicolon = FALSE;
|
2009-02-17 18:36:09 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenDefault:
|
2009-02-18 06:03:14 -05:00
|
|
|
if (LexGetToken(Parser, NULL, TRUE) != TokenColon)
|
2009-02-17 18:36:09 -05:00
|
|
|
ProgramFail(Parser, "':' expected");
|
2009-02-18 03:19:06 -05:00
|
|
|
|
|
|
|
if (Parser->Mode == RunModeCaseSearch)
|
|
|
|
Parser->Mode = RunModeRun;
|
2009-03-08 20:34:32 -04:00
|
|
|
|
|
|
|
CheckTrailingSemicolon = FALSE;
|
2009-02-17 18:36:09 -05:00
|
|
|
break;
|
|
|
|
|
2009-01-05 00:50:04 -05:00
|
|
|
case TokenBreak:
|
2009-02-18 03:19:06 -05:00
|
|
|
if (Parser->Mode == RunModeRun)
|
|
|
|
Parser->Mode = RunModeBreak;
|
2009-02-17 18:36:09 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TokenContinue:
|
2009-02-18 03:19:06 -05:00
|
|
|
if (Parser->Mode == RunModeRun)
|
|
|
|
Parser->Mode = RunModeContinue;
|
2009-02-17 18:36:09 -05:00
|
|
|
break;
|
|
|
|
|
2009-01-04 23:28:54 -05:00
|
|
|
case TokenReturn:
|
2009-02-18 03:19:06 -05:00
|
|
|
if (Parser->Mode == RunModeRun)
|
|
|
|
{
|
2009-03-08 03:56:28 -04:00
|
|
|
if (!ExpressionParse(Parser, &CValue) && TopStackFrame->ReturnValue->Typ->Base != TypeVoid)
|
2009-02-19 19:12:58 -05:00
|
|
|
ProgramFail(Parser, "value required in return");
|
|
|
|
|
|
|
|
if (CValue->Typ != TopStackFrame->ReturnValue->Typ)
|
|
|
|
ProgramFail(Parser, "wrong return type");
|
|
|
|
|
|
|
|
// XXX - make assignment a separate function
|
2009-02-23 21:28:35 -05:00
|
|
|
// XXX - also arrays need cleverer assignment
|
2009-02-20 21:35:52 -05:00
|
|
|
memcpy(TopStackFrame->ReturnValue->Val, CValue->Val, TypeSizeValue(CValue));
|
2009-02-19 19:12:58 -05:00
|
|
|
Parser->Mode = RunModeReturn;
|
2009-02-18 03:19:06 -05:00
|
|
|
}
|
2009-03-09 22:18:17 -04:00
|
|
|
else
|
|
|
|
ExpressionParse(Parser, &CValue);
|
2008-12-23 22:27:53 -05:00
|
|
|
break;
|
2009-03-15 06:44:56 -04:00
|
|
|
|
|
|
|
case TokenDelete:
|
|
|
|
if (LexGetToken(Parser, &LexerValue, TRUE) != TokenIdentifier)
|
|
|
|
ProgramFail(Parser, "identifier expected");
|
|
|
|
|
|
|
|
CValue = TableDelete(&GlobalTable, LexerValue->Val->Identifier);
|
|
|
|
|
|
|
|
if (CValue == NULL)
|
|
|
|
ProgramFail(Parser, "'%s' is not defined", LexerValue->Val->Identifier);
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-03-15 06:44:56 -04:00
|
|
|
VariableFree(CValue);
|
|
|
|
break;
|
|
|
|
|
2008-11-21 21:56:08 -05:00
|
|
|
default:
|
2009-02-01 06:31:18 -05:00
|
|
|
*Parser = PreState;
|
2008-11-21 21:56:08 -05:00
|
|
|
return FALSE;
|
2008-10-16 03:04:23 -04:00
|
|
|
}
|
2008-11-21 21:56:08 -05:00
|
|
|
|
2009-03-08 20:34:32 -04:00
|
|
|
if (CheckTrailingSemicolon && LexGetToken(Parser, NULL, FALSE) == TokenSemicolon)
|
|
|
|
LexGetToken(Parser, NULL, TRUE);
|
|
|
|
|
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 */
|
2009-02-02 06:08:36 -05:00
|
|
|
void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt)
|
2008-10-12 20:53:28 -04:00
|
|
|
{
|
2009-02-01 06:31:18 -05:00
|
|
|
struct ParseState Parser;
|
2008-10-12 20:53:28 -04:00
|
|
|
|
2009-03-11 19:49:10 -04:00
|
|
|
void *OldCleanupTokens = CleanupTokens;
|
2009-03-07 02:49:17 -05:00
|
|
|
void *Tokens = LexAnalyse(FileName, Source, SourceLen, NULL);
|
2009-03-11 19:49:10 -04:00
|
|
|
if (OldCleanupTokens == NULL)
|
|
|
|
CleanupTokens = Tokens;
|
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
LexInitParser(&Parser, Tokens, FileName, 1, RunIt);
|
2009-02-02 06:50:55 -05:00
|
|
|
|
2009-02-18 03:19:06 -05:00
|
|
|
while (ParseStatement(&Parser))
|
2008-12-20 05:24:34 -05:00
|
|
|
{}
|
|
|
|
|
2009-02-02 06:08:36 -05:00
|
|
|
if (LexGetToken(&Parser, NULL, FALSE) != TokenEOF)
|
2009-02-01 06:31:18 -05:00
|
|
|
ProgramFail(&Parser, "parse error");
|
2009-03-07 02:49:17 -05:00
|
|
|
|
|
|
|
HeapFree(Tokens);
|
2009-03-11 19:49:10 -04:00
|
|
|
if (OldCleanupTokens == NULL)
|
|
|
|
CleanupTokens = NULL;
|
2008-10-12 20:53:28 -04:00
|
|
|
}
|
2009-03-07 06:23:42 -05:00
|
|
|
|
|
|
|
/* parse interactively */
|
|
|
|
void ParseInteractive()
|
|
|
|
{
|
|
|
|
struct ParseState Parser;
|
2009-03-07 23:26:28 -05:00
|
|
|
int Ok;
|
2009-03-07 06:23:42 -05:00
|
|
|
|
2009-03-08 19:03:59 -04:00
|
|
|
PlatformPrintf(INTERACTIVE_PROMPT_START);
|
2009-03-07 06:23:42 -05:00
|
|
|
LexInitParser(&Parser, NULL, StrEmpty, 1, TRUE);
|
2009-03-07 23:26:28 -05:00
|
|
|
PlatformSetExitPoint();
|
|
|
|
LexInteractiveClear(&Parser);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
LexInteractiveStatementPrompt();
|
|
|
|
Ok = ParseStatement(&Parser);
|
2009-03-07 06:23:42 -05:00
|
|
|
LexInteractiveCompleted(&Parser);
|
2009-03-07 23:26:28 -05:00
|
|
|
|
|
|
|
} while (Ok);
|
|
|
|
|
|
|
|
PlatformPrintf("\n");
|
2009-03-07 06:23:42 -05:00
|
|
|
}
|