Split parsing across two files parse.c and the new expression.c
git-svn-id: http://picoc.googlecode.com/svn/trunk@170 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
679e235822
commit
dc04ba8dd0
4
Makefile
4
Makefile
|
@ -3,7 +3,7 @@ CFLAGS=-Wall -g
|
|||
LIBS=-lm
|
||||
|
||||
TARGET = picoc
|
||||
SRCS = picoc.c table.c lex.c parse.c heap.c type.c variable.c clibrary.c platform_library.c platform_support.c
|
||||
SRCS = picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c clibrary.c platform_library.c platform_support.c
|
||||
OBJS := $(SRCS:%.c=%.o)
|
||||
|
||||
all: depend $(TARGET)
|
||||
|
@ -18,7 +18,7 @@ clean:
|
|||
rm -f $(TARGET) $(OBJS) *~
|
||||
|
||||
count:
|
||||
wc picoc.h picoc.c table.c lex.c parse.c heap.c type.c variable.c clibrary.c
|
||||
wc picoc.h picoc.c table.c lex.c parse.c expression.c heap.c type.c variable.c clibrary.c
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(SRCS) >.depend
|
||||
|
|
1
TODO
1
TODO
|
@ -7,6 +7,7 @@ Implement:
|
|||
* casts
|
||||
* enum
|
||||
* fix #include
|
||||
* char access/char array access/char * access
|
||||
|
||||
Improvements:
|
||||
* #define with arguments
|
||||
|
|
603
expression.c
Normal file
603
expression.c
Normal file
|
@ -0,0 +1,603 @@
|
|||
#include "picoc.h"
|
||||
|
||||
/* local prototypes */
|
||||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName);
|
||||
|
||||
#if 1
|
||||
/* parse a single value */
|
||||
int ExpressionParseValue(struct ParseState *Parser, struct Value **Result)
|
||||
{
|
||||
struct ParseState PreState = *Parser;
|
||||
struct Value *LexValue;
|
||||
int IntValue;
|
||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
struct Value *LocalLValue = NULL;
|
||||
struct ValueType *VType;
|
||||
int Success = TRUE;
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIntegerConstant: case TokenCharacterConstant: case TokenFPConstant: case TokenStringConstant:
|
||||
*Result = VariableAllocValueAndCopy(Parser, LexValue, FALSE);
|
||||
break;
|
||||
|
||||
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
||||
IntValue = ExpressionParseInt(Parser);
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
*Result = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
||||
switch(Token)
|
||||
{
|
||||
case TokenMinus: (*Result)->Val->Integer = -IntValue; break;
|
||||
case TokenUnaryExor: (*Result)->Val->Integer = ~IntValue; break;
|
||||
case TokenUnaryNot: (*Result)->Val->Integer = !IntValue; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenOpenBracket:
|
||||
if (!ExpressionParse(Parser, Result))
|
||||
ProgramFail(Parser, "invalid expression");
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
break;
|
||||
|
||||
case TokenAsterisk:
|
||||
if (!ExpressionParse(Parser, Result))
|
||||
ProgramFail(Parser, "invalid expression");
|
||||
|
||||
if ((*Result)->Typ->Base != TypePointer)
|
||||
ProgramFail(Parser, "can't dereference this non-pointer");
|
||||
|
||||
LocalLValue = (*Result)->Val->Pointer.Segment;
|
||||
VariableStackPop(Parser, *Result);
|
||||
#if 0
|
||||
*Result = VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap)
|
||||
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (void *)LocalLValue->Val + LocalLValue->Val->Pointer.Segment,
|
||||
LocalLValue->IsLValue, FromValue->IsLValue ? FromValue : NULL);
|
||||
#endif
|
||||
*Result = VariableAllocValueShared(Parser, LocalLValue);
|
||||
break;
|
||||
|
||||
case TokenAmpersand:
|
||||
if (!ExpressionParseValue(Parser, Result) || !(*Result)->IsLValue)
|
||||
ProgramFail(Parser, "can't get the address of this");
|
||||
|
||||
VType = (*Result)->Typ;
|
||||
LocalLValue = (*Result)->LValueFrom;
|
||||
VariableStackPop(Parser, *Result);
|
||||
*Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, VType, TypePointer, 0, StrEmpty), FALSE, NULL);
|
||||
(*Result)->Val->Pointer.Segment = LocalLValue;
|
||||
(*Result)->Val->Pointer.Data.Offset = (void *)(*Result)->Val - (void *)(*Result)->LValueFrom;
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
|
||||
ExpressionParseFunctionCall(Parser, Result, LexValue->Val->Identifier);
|
||||
else
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
VariableGet(Parser, LexValue->Val->Identifier, &LocalLValue);
|
||||
if (LocalLValue->Typ->Base == TypeMacro)
|
||||
{
|
||||
struct ParseState MacroParser = LocalLValue->Val->Parser;
|
||||
|
||||
if (!ExpressionParse(&MacroParser, Result) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
||||
ProgramFail(&MacroParser, "expression expected");
|
||||
}
|
||||
else if (LocalLValue->Typ == TypeVoid)
|
||||
ProgramFail(Parser, "a void value isn't much use here");
|
||||
else
|
||||
{ /* it's a value variable */
|
||||
*Result = VariableAllocValueShared(Parser, LocalLValue);
|
||||
}
|
||||
}
|
||||
|
||||
/* see if there's a postfix operator */
|
||||
Token = LexGetToken(Parser, &LexValue, FALSE);
|
||||
if (Token == TokenIncrement || Token == TokenDecrement)
|
||||
{ /* it's a postincrement or postdecrement */
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (!(*Result)->IsLValue || (*Result)->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "can't %s this", (Token == TokenIncrement) ? "increment" : "decrement");
|
||||
|
||||
if (Token == TokenIncrement)
|
||||
(*Result)->Val->Integer++;
|
||||
else
|
||||
(*Result)->Val->Integer--;
|
||||
}
|
||||
}
|
||||
else if (Token == TokenLeftSquareBracket)
|
||||
{ /* array access */
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
IntValue = ExpressionParseInt(Parser);
|
||||
if (LexGetToken(Parser, &LexValue, TRUE) != TokenRightSquareBracket)
|
||||
ProgramFail(Parser, "expected ']'");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* look up the array element */
|
||||
if ((*Result)->Typ->Base != TypeArray)
|
||||
ProgramFail(Parser, "not an array");
|
||||
|
||||
if (IntValue < 0 || IntValue >= (*Result)->Val->Array.Size)
|
||||
ProgramFail(Parser, "illegal array index");
|
||||
|
||||
VariableStackPop(Parser, *Result);
|
||||
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (union AnyValue *)((*Result)->Val->Array.Data + TypeSize((*Result)->Typ->FromType, 0) * IntValue), (*Result)->IsLValue, (*Result)->LValueFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*Parser = PreState;
|
||||
Success = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
#ifndef NO_FP
|
||||
struct Value *ParsePushFP(struct ParseState *Parser, double NewFP)
|
||||
{
|
||||
struct Value *Val = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL);
|
||||
Val->Val->FP = NewFP;
|
||||
return Val;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Value *ParsePushInt(struct ParseState *Parser, int NewInt)
|
||||
{
|
||||
struct Value *Val = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
||||
Val->Val->Integer = NewInt;
|
||||
return Val;
|
||||
}
|
||||
|
||||
/* parse an expression. operator precedence is not supported */
|
||||
int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||
{
|
||||
struct Value *CurrentValue;
|
||||
struct Value *TotalValue;
|
||||
|
||||
if (!ExpressionParseValue(Parser, &TotalValue))
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, FALSE);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
|
||||
case TokenEqual: case TokenLessThan: case TokenGreaterThan:
|
||||
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
|
||||
case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr:
|
||||
case TokenArithmeticExor:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
break;
|
||||
|
||||
case TokenDot:
|
||||
{
|
||||
struct Value *Ident;
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
if (LexGetToken(Parser, &Ident, TRUE) != TokenIdentifier)
|
||||
ProgramFail(Parser, "need an structure or union member after '.'");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
void *TotalValueData = (void *)TotalValue->Val;
|
||||
|
||||
if (TotalValue->Typ->Base != TypeStruct && TotalValue->Typ->Base != TypeUnion)
|
||||
ProgramFail(Parser, "can't use '.' on something that's not a struct or union");
|
||||
|
||||
if (!TableGet(TotalValue->Typ->Members, Ident->Val->Identifier, &CurrentValue))
|
||||
ProgramFail(Parser, "structure doesn't have a member called '%s'", Ident->Val->Identifier);
|
||||
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
TotalValue = VariableAllocValueFromExistingData(Parser, CurrentValue->Typ, TotalValueData + CurrentValue->Val->Integer, TRUE, TotalValue->LValueFrom);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case TokenAssign:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
if (!ExpressionParse(Parser, &CurrentValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* do the assignment */
|
||||
if (!TotalValue->IsLValue)
|
||||
ProgramFail(Parser, "can't assign to this");
|
||||
|
||||
if (CurrentValue->Typ != TotalValue->Typ)
|
||||
ProgramFail(Parser, "can't assign incompatible types");
|
||||
|
||||
if (TotalValue->Typ->Base != TypeArray)
|
||||
memcpy(TotalValue->Val, CurrentValue->Val, TotalValue->Typ->Sizeof);
|
||||
else
|
||||
{ /* array assignment */
|
||||
if (TotalValue->Val->Array.Size != CurrentValue->Val->Array.Size)
|
||||
ProgramFail(Parser, "incompatible array sizes in assignment");
|
||||
|
||||
//memcpy(TotalValue->Val->Array.Data, CurrentValue->Val->Array.Data, CurrentValue->Typ->Sizeof * CurrentValue->Val->Array.Size);
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
*Result = TotalValue;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case TokenAddAssign: case TokenSubtractAssign:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
if (!ExpressionParse(Parser, &CurrentValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* do the assignment */
|
||||
if (!TotalValue->IsLValue)
|
||||
ProgramFail(Parser, "can't assign");
|
||||
|
||||
if (CurrentValue->Typ->Base == TypeInt && TotalValue->Typ->Base == TypeInt)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenAddAssign: TotalValue->Val->Integer += CurrentValue->Val->Integer; break;
|
||||
case TokenSubtractAssign: TotalValue->Val->Integer -= CurrentValue->Val->Integer; break;
|
||||
default: break;
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
}
|
||||
#ifndef NO_FP
|
||||
else if (CurrentValue->Typ->Base == TypeFP && TotalValue->Typ->Base == TypeFP)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenAddAssign: TotalValue->Val->FP += CurrentValue->Val->FP; break;
|
||||
case TokenSubtractAssign: TotalValue->Val->FP -= CurrentValue->Val->FP; break;
|
||||
default: break;
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ProgramFail(Parser, "can't operate and assign these types");
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
default:
|
||||
if (Parser->Mode == RunModeRun)
|
||||
*Result = TotalValue;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ExpressionParseValue(Parser, &CurrentValue))
|
||||
return FALSE;
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
#ifndef NO_FP
|
||||
if (CurrentValue->Typ->Base == TypeFP || TotalValue->Typ->Base == TypeFP)
|
||||
{ /* floating point expression */
|
||||
double FPTotal, FPCurrent, FPResult;
|
||||
|
||||
if (CurrentValue->Typ->Base != TypeFP || TotalValue->Typ->Base != TypeFP)
|
||||
{ /* convert both to floating point */
|
||||
if (CurrentValue->Typ->Base == TypeInt)
|
||||
FPCurrent = (double)CurrentValue->Val->Integer;
|
||||
else if (CurrentValue->Typ->Base == TypeFP)
|
||||
FPCurrent = CurrentValue->Val->FP;
|
||||
else
|
||||
ProgramFail(Parser, "bad type for operator");
|
||||
|
||||
if (TotalValue->Typ->Base == TypeInt)
|
||||
FPTotal = (double)TotalValue->Val->Integer;
|
||||
else if (TotalValue->Typ->Base == TypeFP)
|
||||
FPTotal = TotalValue->Val->FP;
|
||||
else
|
||||
ProgramFail(Parser, "bad type for operator");
|
||||
}
|
||||
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: FPResult = FPTotal + FPCurrent; break;
|
||||
case TokenMinus: FPResult = FPTotal - FPCurrent; break;
|
||||
case TokenAsterisk: FPResult = FPTotal * FPCurrent; break;
|
||||
case TokenSlash: FPResult = FPTotal / FPCurrent; break;
|
||||
case TokenEqual: FPResult = FPTotal == FPCurrent; break;
|
||||
case TokenLessThan: FPResult = FPTotal < FPCurrent; break;
|
||||
case TokenGreaterThan: FPResult = FPTotal > FPCurrent; break;
|
||||
case TokenLessEqual: FPResult = FPTotal <= FPCurrent; break;
|
||||
case TokenGreaterEqual: FPResult = FPTotal >= FPCurrent; break;
|
||||
case TokenLogicalAnd: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenArithmeticExor: ProgramFail(Parser, "bad type for operator"); break;
|
||||
default: break;
|
||||
}
|
||||
TotalValue = ParsePushFP(Parser, FPResult);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ /* integer expression */
|
||||
int IntX, IntY, IntResult;
|
||||
|
||||
if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "bad operand types");
|
||||
|
||||
IntX = TotalValue->Val->Integer;
|
||||
IntY = CurrentValue->Val->Integer;
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
|
||||
/* integer arithmetic */
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: IntResult = IntX + IntY; break;
|
||||
case TokenMinus: IntResult = IntX - IntY; break;
|
||||
case TokenAsterisk: IntResult = IntX * IntY; break;
|
||||
case TokenSlash: IntResult = IntX / IntY; break;
|
||||
case TokenEqual: IntResult = IntX == IntY; break;
|
||||
case TokenLessThan: IntResult = IntX < IntY; break;
|
||||
case TokenGreaterThan: IntResult = IntX > IntY; break;
|
||||
case TokenLessEqual: IntResult = IntX <= IntY; break;
|
||||
case TokenGreaterEqual: IntResult = IntX >= IntY; break;
|
||||
case TokenLogicalAnd: IntResult = IntX && IntY; break;
|
||||
case TokenLogicalOr: IntResult = IntX || IntY; break;
|
||||
case TokenAmpersand: IntResult = IntX & IntY; break;
|
||||
case TokenArithmeticOr: IntResult = IntX | IntY; break;
|
||||
case TokenArithmeticExor: IntResult = IntX ^ IntY; break;
|
||||
default: break;
|
||||
}
|
||||
TotalValue = ParsePushInt(Parser, IntResult);
|
||||
}
|
||||
|
||||
*Result = TotalValue;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
|
||||
/* operator precedence definitions */
|
||||
struct OpPrecedence
|
||||
{
|
||||
unsigned char PrefixPrecedence:4;
|
||||
unsigned char PostfixPrecedence:4;
|
||||
unsigned char InfixPrecedence:4;
|
||||
};
|
||||
|
||||
static struct OpPrecedence OperatorPrecedence[] =
|
||||
{
|
||||
/* TokenComma, */ { 0, 0, 1 },
|
||||
/* TokenAssign, */ { 0, 0, 2 }, /* TokenAddAssign, */ { 0, 0, 2 }, /* TokenSubtractAssign, */ { 0, 0, 2 },
|
||||
/* TokenMultiplyAssign, */ { 0, 0, 2 }, /* TokenDivideAssign, */ { 0, 0, 2 }, /* TokenModulusAssign, */ { 0, 0, 2 },
|
||||
/* TokenShiftLeftAssign, */ { 0, 0, 2 }, /* TokenShiftRightAssign, */ { 0, 0, 2 }, /* TokenArithmeticAndAssign, */ { 0, 0, 2 },
|
||||
/* TokenArithmeticOrAssign, */ { 0, 0, 2 }, /* TokenArithmeticExorAssign, */ { 0, 0, 2 },
|
||||
/* TokenQuestionMark, */ { 0, 0, 3 }, /* TokenColon, */ { 0, 0, 3 },
|
||||
/* TokenLogicalOr, */ { 0, 0, 4 },
|
||||
/* TokenLogicalAnd, */ { 0, 0, 5 },
|
||||
/* TokenArithmeticOr, */ { 0, 0, 6 },
|
||||
/* TokenTilde, */ { 0, 0, 7 },
|
||||
/* TokenAmpersand, */ { 14, 0, 8 },
|
||||
/* TokenEqual, TokenNotEqual, */ { 0, 0, 9 },
|
||||
/* TokenLessThan, */ { 0, 0, 10 }, /* TokenGreaterThan, */ { 0, 0, 10 }, /* TokenLessEqual, */ { 0, 0, 10 }, /* TokenGreaterEqual, */ { 0, 0, 10 },
|
||||
/* TokenShiftLeft, */ { 0, 0, 11 }, /* TokenShiftRight, */ { 0, 0, 11 },
|
||||
/* TokenPlus, */ { 14, 0, 12 }, /* TokenMinus, */ { 14, 0, 12 },
|
||||
/* TokenAsterisk, */ { 14, 0, 13 }, /* TokenSlash, */ { 0, 0, 13 }, /* TokenModulus, */ { 0, 0, 13 },
|
||||
/* TokenIncrement, */ { 14, 15, 0 }, /* TokenDecrement, */ { 14, 15, 0 }, /* TokenUnaryNot, */ { 14, 0, 0 }, /* TokenUnaryExor, */ { 14, 0, 0 }, /* TokenSizeof, */ { 14, 0, 0 },
|
||||
/* TokenLeftSquareBracket, */ { 15, 0, 0 }, /* TokenRightSquareBracket, */ { 0, 15, 0 }, /* TokenDot, */ { 0, 0, 15 }, /* TokenArrow, */ { 0, 0, 15 },
|
||||
/* TokenOpenBracket, */ { 15, 0, 0 }, /* TokenCloseBracket, */ { 0, 15, 0 }
|
||||
};
|
||||
|
||||
/* parse an expression with operator precedence */
|
||||
int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
||||
{
|
||||
struct Value *LexValue;
|
||||
bool PrefixState = false;
|
||||
bool Done = false;
|
||||
int BracketPrecedence = 0;
|
||||
int Precedence = 0;
|
||||
|
||||
do
|
||||
{
|
||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
if ((int)Token <= (int)TokenCloseBracket)
|
||||
{ /* it's an operator with precedence */
|
||||
if (PrefixState)
|
||||
{ /* expect a prefix operator */
|
||||
if (OperatorPrecedence[(int)Token].PrefixPrecedence == 0)
|
||||
ProgramFail(Parser, "operator not expected here");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (Token == TokenOpenBracket || Token == TokenLeftSquareBracket)
|
||||
{
|
||||
/* boost the bracket operator precedence */
|
||||
BracketPrecedence += BRACKET_PREDECENCE;
|
||||
/* push the operator */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* expect an infix or postfix operator */
|
||||
if (OperatorPrecedence[(int)Token].PostfixPrecedence != 0)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenCloseBracket:
|
||||
if (BracketPrecedence == 0)
|
||||
{ /* assume this bracket is after the end of the expression */
|
||||
/* scan and collapse the stack to precedence 0 */
|
||||
Done = true;
|
||||
}
|
||||
else
|
||||
BracketPrecedence -= BRACKET_PRECEDENCE;
|
||||
break;
|
||||
|
||||
case TokenRightSquareBracket:
|
||||
if (BracketPrecedence == 0)
|
||||
ProgramFail(Parser, "no matching open square bracket");
|
||||
|
||||
/* scan and collapse the stack to bracket precedence */
|
||||
BracketPrecedence -= BRACKET_PRECEDENCE;
|
||||
|
||||
/* apply the array index operator */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0)
|
||||
{
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
PrefixState = true;
|
||||
}
|
||||
else
|
||||
ProgramFail(Parser, "operator not expected here");
|
||||
}
|
||||
}
|
||||
else if ((int)Token <= (int)TokenCharacterConstant)
|
||||
{ /* it's a value of some sort */
|
||||
if (!PrefixState)
|
||||
ProgramFail(Parser, "value not expected here");
|
||||
|
||||
PrefixState = false;
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
/* push the value */
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* it isn't a token from an expression */
|
||||
/* scan and collapse the stack to precedence 0 */
|
||||
Done = true;
|
||||
}
|
||||
|
||||
} while (!Done);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* parse an expression. operator precedence is not supported */
|
||||
int ExpressionParseInt(struct ParseState *Parser)
|
||||
{
|
||||
struct Value *Val;
|
||||
int Result = 0;
|
||||
|
||||
if (!ExpressionParse(Parser, &Val))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (Val->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "integer value expected");
|
||||
|
||||
Result = Val->Val->Integer;
|
||||
VariableStackPop(Parser, Val);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* do a function call */
|
||||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName)
|
||||
{
|
||||
struct Value *FuncValue;
|
||||
struct Value *Param;
|
||||
struct Value **ParamArray;
|
||||
int ArgCount;
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* get the function definition */
|
||||
VariableGet(Parser, FuncName, &FuncValue);
|
||||
if (FuncValue->Typ->Base != TypeFunction)
|
||||
ProgramFail(Parser, "not a function - can't call");
|
||||
|
||||
*Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, FALSE, NULL);
|
||||
HeapPushStackFrame();
|
||||
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
||||
if (ParamArray == NULL)
|
||||
ProgramFail(Parser, "out of memory");
|
||||
}
|
||||
|
||||
/* parse arguments */
|
||||
ArgCount = 0;
|
||||
do {
|
||||
if (ExpressionParse(Parser, &Param))
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (ArgCount >= FuncValue->Val->FuncDef.NumParams)
|
||||
{
|
||||
if (!FuncValue->Val->FuncDef.VarArgs)
|
||||
ProgramFail(Parser, "too many arguments to %s()", FuncName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FuncValue->Val->FuncDef.ParamType[ArgCount] != Param->Typ)
|
||||
ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount+1, FuncName);
|
||||
}
|
||||
|
||||
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||
ParamArray[ArgCount] = Param;
|
||||
}
|
||||
|
||||
ArgCount++;
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token != TokenComma && Token != TokenCloseBracket)
|
||||
ProgramFail(Parser, "comma expected");
|
||||
}
|
||||
else
|
||||
{ /* end of argument list? */
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (!TokenCloseBracket)
|
||||
ProgramFail(Parser, "bad argument");
|
||||
}
|
||||
} while (Token != TokenCloseBracket);
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* run the function */
|
||||
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||
ProgramFail(Parser, "not enough arguments to '%s'", FuncName);
|
||||
|
||||
if (FuncValue->Val->FuncDef.Intrinsic == NULL)
|
||||
{ /* run a user-defined function */
|
||||
struct ParseState FuncParser = FuncValue->Val->FuncDef.Body;
|
||||
int Count;
|
||||
|
||||
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
||||
TopStackFrame->NumParams = ArgCount;
|
||||
TopStackFrame->ReturnValue = *Result;
|
||||
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
||||
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]);
|
||||
|
||||
if (!ParseStatement(&FuncParser))
|
||||
ProgramFail(&FuncParser, "function body expected");
|
||||
|
||||
if (FuncValue->Val->FuncDef.ReturnType != (*Result)->Typ)
|
||||
ProgramFail(&FuncParser, "bad type of return value");
|
||||
|
||||
VariableStackFramePop(Parser);
|
||||
}
|
||||
else
|
||||
FuncValue->Val->FuncDef.Intrinsic(Parser, *Result, ParamArray, ArgCount);
|
||||
|
||||
HeapPopStackFrame();
|
||||
}
|
||||
}
|
642
parse.c
642
parse.c
|
@ -1,607 +1,18 @@
|
|||
#include "picoc.h"
|
||||
|
||||
/* local prototypes */
|
||||
int ParseArguments(struct ParseState *Parser, int RunIt);
|
||||
int ParseStatementMaybeRun(struct ParseState *Parser, int Condition);
|
||||
void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName);
|
||||
|
||||
#if 1
|
||||
/* parse a single value */
|
||||
int ParseValue(struct ParseState *Parser, struct Value **Result)
|
||||
/* parse a statement, but only run it if Condition is TRUE */
|
||||
int ParseStatementMaybeRun(struct ParseState *Parser, int Condition)
|
||||
{
|
||||
struct ParseState PreState = *Parser;
|
||||
struct Value *LexValue;
|
||||
int IntValue;
|
||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
struct Value *LocalLValue = NULL;
|
||||
struct ValueType *VType;
|
||||
int Success = TRUE;
|
||||
|
||||
switch (Token)
|
||||
if (Parser->Mode != RunModeSkip && !Condition)
|
||||
{
|
||||
case TokenIntegerConstant: case TokenCharacterConstant: case TokenFPConstant: case TokenStringConstant:
|
||||
*Result = VariableAllocValueAndCopy(Parser, LexValue, FALSE);
|
||||
break;
|
||||
|
||||
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
||||
IntValue = ParseIntExpression(Parser);
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
*Result = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
||||
switch(Token)
|
||||
{
|
||||
case TokenMinus: (*Result)->Val->Integer = -IntValue; break;
|
||||
case TokenUnaryExor: (*Result)->Val->Integer = ~IntValue; break;
|
||||
case TokenUnaryNot: (*Result)->Val->Integer = !IntValue; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenOpenBracket:
|
||||
if (!ParseExpression(Parser, Result))
|
||||
ProgramFail(Parser, "invalid expression");
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
break;
|
||||
|
||||
case TokenAsterisk:
|
||||
if (!ParseExpression(Parser, Result))
|
||||
ProgramFail(Parser, "invalid expression");
|
||||
|
||||
if ((*Result)->Typ->Base != TypePointer)
|
||||
ProgramFail(Parser, "can't dereference this non-pointer");
|
||||
|
||||
LocalLValue = (*Result)->Val->Pointer.Segment;
|
||||
VariableStackPop(Parser, *Result);
|
||||
#if 0
|
||||
*Result = VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap)
|
||||
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (void *)LocalLValue->Val + LocalLValue->Val->Pointer.Segment,
|
||||
LocalLValue->IsLValue, FromValue->IsLValue ? FromValue : NULL);
|
||||
#endif
|
||||
*Result = VariableAllocValueShared(Parser, LocalLValue);
|
||||
break;
|
||||
|
||||
case TokenAmpersand:
|
||||
if (!ParseValue(Parser, Result) || !(*Result)->IsLValue)
|
||||
ProgramFail(Parser, "can't get the address of this");
|
||||
|
||||
VType = (*Result)->Typ;
|
||||
LocalLValue = (*Result)->LValueFrom;
|
||||
VariableStackPop(Parser, *Result);
|
||||
*Result = VariableAllocValueFromType(Parser, TypeGetMatching(Parser, VType, TypePointer, 0, StrEmpty), FALSE, NULL);
|
||||
(*Result)->Val->Pointer.Segment = LocalLValue;
|
||||
(*Result)->Val->Pointer.Data.Offset = (void *)(*Result)->Val - (void *)(*Result)->LValueFrom;
|
||||
break;
|
||||
|
||||
case TokenIdentifier:
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
|
||||
ParseFunctionCall(Parser, Result, LexValue->Val->Identifier);
|
||||
else
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
VariableGet(Parser, LexValue->Val->Identifier, &LocalLValue);
|
||||
if (LocalLValue->Typ->Base == TypeMacro)
|
||||
{
|
||||
struct ParseState MacroParser = LocalLValue->Val->Parser;
|
||||
|
||||
if (!ParseExpression(&MacroParser, Result) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
||||
ProgramFail(&MacroParser, "expression expected");
|
||||
}
|
||||
else if (LocalLValue->Typ == TypeVoid)
|
||||
ProgramFail(Parser, "a void value isn't much use here");
|
||||
else
|
||||
{ /* it's a value variable */
|
||||
*Result = VariableAllocValueShared(Parser, LocalLValue);
|
||||
}
|
||||
}
|
||||
|
||||
/* see if there's a postfix operator */
|
||||
Token = LexGetToken(Parser, &LexValue, FALSE);
|
||||
if (Token == TokenIncrement || Token == TokenDecrement)
|
||||
{ /* it's a postincrement or postdecrement */
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (!(*Result)->IsLValue || (*Result)->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "can't %s this", (Token == TokenIncrement) ? "increment" : "decrement");
|
||||
|
||||
if (Token == TokenIncrement)
|
||||
(*Result)->Val->Integer++;
|
||||
else
|
||||
(*Result)->Val->Integer--;
|
||||
}
|
||||
}
|
||||
else if (Token == TokenLeftSquareBracket)
|
||||
{ /* array access */
|
||||
LexGetToken(Parser, &LexValue, TRUE);
|
||||
IntValue = ParseIntExpression(Parser);
|
||||
if (LexGetToken(Parser, &LexValue, TRUE) != TokenRightSquareBracket)
|
||||
ProgramFail(Parser, "expected ']'");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* look up the array element */
|
||||
if ((*Result)->Typ->Base != TypeArray)
|
||||
ProgramFail(Parser, "not an array");
|
||||
|
||||
if (IntValue < 0 || IntValue >= (*Result)->Val->Array.Size)
|
||||
ProgramFail(Parser, "illegal array index");
|
||||
|
||||
VariableStackPop(Parser, *Result);
|
||||
*Result = VariableAllocValueFromExistingData(Parser, (*Result)->Typ->FromType, (union AnyValue *)((*Result)->Val->Array.Data + TypeSize((*Result)->Typ->FromType, 0) * IntValue), (*Result)->IsLValue, (*Result)->LValueFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*Parser = PreState;
|
||||
Success = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
#ifndef NO_FP
|
||||
struct Value *ParsePushFP(struct ParseState *Parser, double NewFP)
|
||||
{
|
||||
struct Value *Val = VariableAllocValueFromType(Parser, &FPType, FALSE, NULL);
|
||||
Val->Val->FP = NewFP;
|
||||
return Val;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Value *ParsePushInt(struct ParseState *Parser, int NewInt)
|
||||
{
|
||||
struct Value *Val = VariableAllocValueFromType(Parser, &IntType, FALSE, NULL);
|
||||
Val->Val->Integer = NewInt;
|
||||
return Val;
|
||||
}
|
||||
|
||||
/* parse an expression. operator precedence is not supported */
|
||||
int ParseExpression(struct ParseState *Parser, struct Value **Result)
|
||||
{
|
||||
struct Value *CurrentValue;
|
||||
struct Value *TotalValue;
|
||||
|
||||
if (!ParseValue(Parser, &TotalValue))
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, FALSE);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
|
||||
case TokenEqual: case TokenLessThan: case TokenGreaterThan:
|
||||
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
|
||||
case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr:
|
||||
case TokenArithmeticExor:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
break;
|
||||
|
||||
case TokenDot:
|
||||
{
|
||||
struct Value *Ident;
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
if (LexGetToken(Parser, &Ident, TRUE) != TokenIdentifier)
|
||||
ProgramFail(Parser, "need an structure or union member after '.'");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
void *TotalValueData = (void *)TotalValue->Val;
|
||||
|
||||
if (TotalValue->Typ->Base != TypeStruct && TotalValue->Typ->Base != TypeUnion)
|
||||
ProgramFail(Parser, "can't use '.' on something that's not a struct or union");
|
||||
|
||||
if (!TableGet(TotalValue->Typ->Members, Ident->Val->Identifier, &CurrentValue))
|
||||
ProgramFail(Parser, "structure doesn't have a member called '%s'", Ident->Val->Identifier);
|
||||
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
TotalValue = VariableAllocValueFromExistingData(Parser, CurrentValue->Typ, TotalValueData + CurrentValue->Val->Integer, TRUE, TotalValue->LValueFrom);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case TokenAssign:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
if (!ParseExpression(Parser, &CurrentValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* do the assignment */
|
||||
if (!TotalValue->IsLValue)
|
||||
ProgramFail(Parser, "can't assign to this");
|
||||
|
||||
if (CurrentValue->Typ != TotalValue->Typ)
|
||||
ProgramFail(Parser, "can't assign incompatible types");
|
||||
|
||||
if (TotalValue->Typ->Base != TypeArray)
|
||||
memcpy(TotalValue->Val, CurrentValue->Val, TotalValue->Typ->Sizeof);
|
||||
else
|
||||
{ /* array assignment */
|
||||
if (TotalValue->Val->Array.Size != CurrentValue->Val->Array.Size)
|
||||
ProgramFail(Parser, "incompatible array sizes in assignment");
|
||||
|
||||
//memcpy(TotalValue->Val->Array.Data, CurrentValue->Val->Array.Data, CurrentValue->Typ->Sizeof * CurrentValue->Val->Array.Size);
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
*Result = TotalValue;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case TokenAddAssign: case TokenSubtractAssign:
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
if (!ParseExpression(Parser, &CurrentValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* do the assignment */
|
||||
if (!TotalValue->IsLValue)
|
||||
ProgramFail(Parser, "can't assign");
|
||||
|
||||
if (CurrentValue->Typ->Base == TypeInt && TotalValue->Typ->Base == TypeInt)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenAddAssign: TotalValue->Val->Integer += CurrentValue->Val->Integer; break;
|
||||
case TokenSubtractAssign: TotalValue->Val->Integer -= CurrentValue->Val->Integer; break;
|
||||
default: break;
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
}
|
||||
#ifndef NO_FP
|
||||
else if (CurrentValue->Typ->Base == TypeFP && TotalValue->Typ->Base == TypeFP)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenAddAssign: TotalValue->Val->FP += CurrentValue->Val->FP; break;
|
||||
case TokenSubtractAssign: TotalValue->Val->FP -= CurrentValue->Val->FP; break;
|
||||
default: break;
|
||||
}
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ProgramFail(Parser, "can't operate and assign these types");
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
default:
|
||||
if (Parser->Mode == RunModeRun)
|
||||
*Result = TotalValue;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ParseValue(Parser, &CurrentValue))
|
||||
return FALSE;
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
#ifndef NO_FP
|
||||
if (CurrentValue->Typ->Base == TypeFP || TotalValue->Typ->Base == TypeFP)
|
||||
{ /* floating point expression */
|
||||
double FPTotal, FPCurrent, FPResult;
|
||||
|
||||
if (CurrentValue->Typ->Base != TypeFP || TotalValue->Typ->Base != TypeFP)
|
||||
{ /* convert both to floating point */
|
||||
if (CurrentValue->Typ->Base == TypeInt)
|
||||
FPCurrent = (double)CurrentValue->Val->Integer;
|
||||
else if (CurrentValue->Typ->Base == TypeFP)
|
||||
FPCurrent = CurrentValue->Val->FP;
|
||||
else
|
||||
ProgramFail(Parser, "bad type for operator");
|
||||
|
||||
if (TotalValue->Typ->Base == TypeInt)
|
||||
FPTotal = (double)TotalValue->Val->Integer;
|
||||
else if (TotalValue->Typ->Base == TypeFP)
|
||||
FPTotal = TotalValue->Val->FP;
|
||||
else
|
||||
ProgramFail(Parser, "bad type for operator");
|
||||
}
|
||||
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: FPResult = FPTotal + FPCurrent; break;
|
||||
case TokenMinus: FPResult = FPTotal - FPCurrent; break;
|
||||
case TokenAsterisk: FPResult = FPTotal * FPCurrent; break;
|
||||
case TokenSlash: FPResult = FPTotal / FPCurrent; break;
|
||||
case TokenEqual: FPResult = FPTotal == FPCurrent; break;
|
||||
case TokenLessThan: FPResult = FPTotal < FPCurrent; break;
|
||||
case TokenGreaterThan: FPResult = FPTotal > FPCurrent; break;
|
||||
case TokenLessEqual: FPResult = FPTotal <= FPCurrent; break;
|
||||
case TokenGreaterEqual: FPResult = FPTotal >= FPCurrent; break;
|
||||
case TokenLogicalAnd: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenArithmeticExor: ProgramFail(Parser, "bad type for operator"); break;
|
||||
default: break;
|
||||
}
|
||||
TotalValue = ParsePushFP(Parser, FPResult);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ /* integer expression */
|
||||
int IntX, IntY, IntResult;
|
||||
|
||||
if (CurrentValue->Typ->Base != TypeInt || TotalValue->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "bad operand types");
|
||||
|
||||
IntX = TotalValue->Val->Integer;
|
||||
IntY = CurrentValue->Val->Integer;
|
||||
VariableStackPop(Parser, CurrentValue);
|
||||
VariableStackPop(Parser, TotalValue);
|
||||
|
||||
/* integer arithmetic */
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: IntResult = IntX + IntY; break;
|
||||
case TokenMinus: IntResult = IntX - IntY; break;
|
||||
case TokenAsterisk: IntResult = IntX * IntY; break;
|
||||
case TokenSlash: IntResult = IntX / IntY; break;
|
||||
case TokenEqual: IntResult = IntX == IntY; break;
|
||||
case TokenLessThan: IntResult = IntX < IntY; break;
|
||||
case TokenGreaterThan: IntResult = IntX > IntY; break;
|
||||
case TokenLessEqual: IntResult = IntX <= IntY; break;
|
||||
case TokenGreaterEqual: IntResult = IntX >= IntY; break;
|
||||
case TokenLogicalAnd: IntResult = IntX && IntY; break;
|
||||
case TokenLogicalOr: IntResult = IntX || IntY; break;
|
||||
case TokenAmpersand: IntResult = IntX & IntY; break;
|
||||
case TokenArithmeticOr: IntResult = IntX | IntY; break;
|
||||
case TokenArithmeticExor: IntResult = IntX ^ IntY; break;
|
||||
default: break;
|
||||
}
|
||||
TotalValue = ParsePushInt(Parser, IntResult);
|
||||
}
|
||||
|
||||
*Result = TotalValue;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
|
||||
/* operator precedence definitions */
|
||||
struct OpPrecedence
|
||||
{
|
||||
unsigned char PrefixPrecedence:4;
|
||||
unsigned char PostfixPrecedence:4;
|
||||
unsigned char InfixPrecedence:4;
|
||||
};
|
||||
|
||||
static struct OpPrecedence OperatorPrecedence[] =
|
||||
{
|
||||
/* TokenComma, */ { 0, 0, 1 },
|
||||
/* TokenAssign, */ { 0, 0, 2 }, /* TokenAddAssign, */ { 0, 0, 2 }, /* TokenSubtractAssign, */ { 0, 0, 2 },
|
||||
/* TokenMultiplyAssign, */ { 0, 0, 2 }, /* TokenDivideAssign, */ { 0, 0, 2 }, /* TokenModulusAssign, */ { 0, 0, 2 },
|
||||
/* TokenShiftLeftAssign, */ { 0, 0, 2 }, /* TokenShiftRightAssign, */ { 0, 0, 2 }, /* TokenArithmeticAndAssign, */ { 0, 0, 2 },
|
||||
/* TokenArithmeticOrAssign, */ { 0, 0, 2 }, /* TokenArithmeticExorAssign, */ { 0, 0, 2 },
|
||||
/* TokenQuestionMark, */ { 0, 0, 3 }, /* TokenColon, */ { 0, 0, 3 },
|
||||
/* TokenLogicalOr, */ { 0, 0, 4 },
|
||||
/* TokenLogicalAnd, */ { 0, 0, 5 },
|
||||
/* TokenArithmeticOr, */ { 0, 0, 6 },
|
||||
/* TokenTilde, */ { 0, 0, 7 },
|
||||
/* TokenAmpersand, */ { 14, 0, 8 },
|
||||
/* TokenEqual, TokenNotEqual, */ { 0, 0, 9 },
|
||||
/* TokenLessThan, */ { 0, 0, 10 }, /* TokenGreaterThan, */ { 0, 0, 10 }, /* TokenLessEqual, */ { 0, 0, 10 }, /* TokenGreaterEqual, */ { 0, 0, 10 },
|
||||
/* TokenShiftLeft, */ { 0, 0, 11 }, /* TokenShiftRight, */ { 0, 0, 11 },
|
||||
/* TokenPlus, */ { 14, 0, 12 }, /* TokenMinus, */ { 14, 0, 12 },
|
||||
/* TokenAsterisk, */ { 14, 0, 13 }, /* TokenSlash, */ { 0, 0, 13 }, /* TokenModulus, */ { 0, 0, 13 },
|
||||
/* TokenIncrement, */ { 14, 15, 0 }, /* TokenDecrement, */ { 14, 15, 0 }, /* TokenUnaryNot, */ { 14, 0, 0 }, /* TokenUnaryExor, */ { 14, 0, 0 }, /* TokenSizeof, */ { 14, 0, 0 },
|
||||
/* TokenLeftSquareBracket, */ { 15, 0, 0 }, /* TokenRightSquareBracket, */ { 0, 15, 0 }, /* TokenDot, */ { 0, 0, 15 }, /* TokenArrow, */ { 0, 0, 15 },
|
||||
/* TokenOpenBracket, */ { 15, 0, 0 }, /* TokenCloseBracket, */ { 0, 15, 0 }
|
||||
};
|
||||
|
||||
/* parse an expression with operator precedence */
|
||||
int ParseExpression(struct ParseState *Parser, struct Value **Result)
|
||||
{
|
||||
struct Value *LexValue;
|
||||
bool PrefixState = false;
|
||||
bool Done = false;
|
||||
int BracketPrecedence = 0;
|
||||
int Precedence = 0;
|
||||
|
||||
do
|
||||
{
|
||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
if ((int)Token <= (int)TokenCloseBracket)
|
||||
{ /* it's an operator with precedence */
|
||||
if (PrefixState)
|
||||
{ /* expect a prefix operator */
|
||||
if (OperatorPrecedence[(int)Token].PrefixPrecedence == 0)
|
||||
ProgramFail(Parser, "operator not expected here");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (Token == TokenOpenBracket || Token == TokenLeftSquareBracket)
|
||||
{
|
||||
/* boost the bracket operator precedence */
|
||||
BracketPrecedence += BRACKET_PREDECENCE;
|
||||
/* push the operator */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* expect an infix or postfix operator */
|
||||
if (OperatorPrecedence[(int)Token].PostfixPrecedence != 0)
|
||||
{
|
||||
switch (Token)
|
||||
{
|
||||
case TokenCloseBracket:
|
||||
if (BracketPrecedence == 0)
|
||||
{ /* assume this bracket is after the end of the expression */
|
||||
/* scan and collapse the stack to precedence 0 */
|
||||
Done = true;
|
||||
}
|
||||
else
|
||||
BracketPrecedence -= BRACKET_PRECEDENCE;
|
||||
break;
|
||||
|
||||
case TokenRightSquareBracket:
|
||||
if (BracketPrecedence == 0)
|
||||
ProgramFail(Parser, "no matching open square bracket");
|
||||
|
||||
/* scan and collapse the stack to bracket precedence */
|
||||
BracketPrecedence -= BRACKET_PRECEDENCE;
|
||||
|
||||
/* apply the array index operator */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (OperatorPrecedence[(int)Token].InfixPrecedence != 0)
|
||||
{
|
||||
/* scan and collapse the stack to the precedence of this operator */
|
||||
/* push the operator */
|
||||
PrefixState = true;
|
||||
}
|
||||
else
|
||||
ProgramFail(Parser, "operator not expected here");
|
||||
}
|
||||
}
|
||||
else if ((int)Token <= (int)TokenCharacterConstant)
|
||||
{ /* it's a value of some sort */
|
||||
if (!PrefixState)
|
||||
ProgramFail(Parser, "value not expected here");
|
||||
|
||||
PrefixState = false;
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
/* push the value */
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* it isn't a token from an expression */
|
||||
/* scan and collapse the stack to precedence 0 */
|
||||
Done = true;
|
||||
}
|
||||
|
||||
} while (!Done);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* parse an expression. operator precedence is not supported */
|
||||
int ParseIntExpression(struct ParseState *Parser)
|
||||
{
|
||||
struct Value *Val;
|
||||
int Result = 0;
|
||||
|
||||
if (!ParseExpression(Parser, &Val))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (Val->Typ->Base != TypeInt)
|
||||
ProgramFail(Parser, "integer value expected");
|
||||
|
||||
Result = Val->Val->Integer;
|
||||
VariableStackPop(Parser, Val);
|
||||
}
|
||||
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
Parser->Mode = RunModeSkip;
|
||||
int Result = ParseStatement(Parser);
|
||||
Parser->Mode = OldMode;
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* do a function call */
|
||||
void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const char *FuncName)
|
||||
{
|
||||
struct Value *FuncValue;
|
||||
struct Value *Param;
|
||||
struct Value **ParamArray;
|
||||
int ArgCount;
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* get the function definition */
|
||||
VariableGet(Parser, FuncName, &FuncValue);
|
||||
if (FuncValue->Typ->Base != TypeFunction)
|
||||
ProgramFail(Parser, "not a function - can't call");
|
||||
|
||||
*Result = VariableAllocValueFromType(Parser, FuncValue->Val->FuncDef.ReturnType, FALSE, NULL);
|
||||
HeapPushStackFrame();
|
||||
ParamArray = HeapAllocStack(sizeof(struct Value *) * FuncValue->Val->FuncDef.NumParams);
|
||||
if (ParamArray == NULL)
|
||||
ProgramFail(Parser, "out of memory");
|
||||
}
|
||||
|
||||
/* parse arguments */
|
||||
ArgCount = 0;
|
||||
do {
|
||||
if (ParseExpression(Parser, &Param))
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (ArgCount >= FuncValue->Val->FuncDef.NumParams)
|
||||
{
|
||||
if (!FuncValue->Val->FuncDef.VarArgs)
|
||||
ProgramFail(Parser, "too many arguments to %s()", FuncName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FuncValue->Val->FuncDef.ParamType[ArgCount] != Param->Typ)
|
||||
ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount+1, FuncName);
|
||||
}
|
||||
|
||||
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||
ParamArray[ArgCount] = Param;
|
||||
}
|
||||
|
||||
ArgCount++;
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token != TokenComma && Token != TokenCloseBracket)
|
||||
ProgramFail(Parser, "comma expected");
|
||||
}
|
||||
else
|
||||
{ /* end of argument list? */
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (!TokenCloseBracket)
|
||||
ProgramFail(Parser, "bad argument");
|
||||
}
|
||||
} while (Token != TokenCloseBracket);
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{ /* run the function */
|
||||
if (ArgCount < FuncValue->Val->FuncDef.NumParams)
|
||||
ProgramFail(Parser, "not enough arguments to '%s'", FuncName);
|
||||
|
||||
if (FuncValue->Val->FuncDef.Intrinsic == NULL)
|
||||
{ /* run a user-defined function */
|
||||
struct ParseState FuncParser = FuncValue->Val->FuncDef.Body;
|
||||
int Count;
|
||||
|
||||
VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0);
|
||||
TopStackFrame->NumParams = ArgCount;
|
||||
TopStackFrame->ReturnValue = *Result;
|
||||
for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++)
|
||||
VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]);
|
||||
|
||||
if (!ParseStatement(&FuncParser))
|
||||
ProgramFail(&FuncParser, "function body expected");
|
||||
|
||||
if (FuncValue->Val->FuncDef.ReturnType != (*Result)->Typ)
|
||||
ProgramFail(&FuncParser, "bad type of return value");
|
||||
|
||||
VariableStackFramePop(Parser);
|
||||
}
|
||||
else
|
||||
FuncValue->Val->FuncDef.Intrinsic(Parser, *Result, ParamArray, ArgCount);
|
||||
|
||||
HeapPopStackFrame();
|
||||
}
|
||||
return ParseStatement(Parser);
|
||||
}
|
||||
|
||||
/* parse a function definition and store it for later */
|
||||
|
@ -707,7 +118,7 @@ void ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|||
else
|
||||
{ /* we're assigning an initial value */
|
||||
LexGetToken(Parser, NULL, TRUE);
|
||||
if (!ParseExpression(Parser, &CValue))
|
||||
if (!ExpressionParse(Parser, &CValue))
|
||||
ProgramFail(Parser, "expression expected");
|
||||
|
||||
VariableDefine(Parser, Identifier, CValue);
|
||||
|
@ -768,7 +179,7 @@ void ParseFor(struct ParseState *Parser)
|
|||
ProgramFail(Parser, "';' expected");
|
||||
|
||||
ParserCopyPos(&PreConditional, Parser);
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon)
|
||||
ProgramFail(Parser, "';' expected");
|
||||
|
@ -794,7 +205,7 @@ void ParseFor(struct ParseState *Parser)
|
|||
ParseStatement(Parser);
|
||||
|
||||
ParserCopyPos(Parser, &PreConditional);
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
if (Condition)
|
||||
{
|
||||
|
@ -812,21 +223,6 @@ void ParseFor(struct ParseState *Parser)
|
|||
ParserCopyPos(Parser, &After);
|
||||
}
|
||||
|
||||
/* parse a statement, but only run it if Condition is TRUE */
|
||||
int ParseStatementMaybeRun(struct ParseState *Parser, int Condition)
|
||||
{
|
||||
if (Parser->Mode != RunModeSkip && !Condition)
|
||||
{
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
Parser->Mode = RunModeSkip;
|
||||
int Result = ParseStatement(Parser);
|
||||
Parser->Mode = OldMode;
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
return ParseStatement(Parser);
|
||||
}
|
||||
|
||||
/* parse a block of code and return what mode it returned in */
|
||||
enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition)
|
||||
{
|
||||
|
@ -868,7 +264,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
|
||||
case TokenIdentifier:
|
||||
*Parser = PreState;
|
||||
ParseExpression(Parser, &CValue);
|
||||
ExpressionParse(Parser, &CValue);
|
||||
if (Parser->Mode == RunModeRun)
|
||||
VariableStackPop(Parser, CValue);
|
||||
break;
|
||||
|
@ -881,7 +277,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
||||
ProgramFail(Parser, "'(' expected");
|
||||
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
|
@ -904,7 +300,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
do
|
||||
{
|
||||
ParserCopyPos(Parser, &PreConditional);
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
ParseBlock(Parser, TRUE, Condition);
|
||||
if (Parser->Mode == RunModeContinue)
|
||||
Parser->Mode = RunModeRun;
|
||||
|
@ -930,7 +326,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
if (LexGetToken(Parser, NULL, TRUE) != TokenWhile)
|
||||
ProgramFail(Parser, "'while' expected");
|
||||
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
} while (Condition && Parser->Mode == RunModeRun);
|
||||
|
||||
|
@ -974,7 +370,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
if (LexGetToken(Parser, NULL, TRUE) != TokenOpenBracket)
|
||||
ProgramFail(Parser, "'(' expected");
|
||||
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket)
|
||||
ProgramFail(Parser, "')' expected");
|
||||
|
@ -999,11 +395,11 @@ int ParseStatement(struct ParseState *Parser)
|
|||
if (Parser->Mode == RunModeCaseSearch)
|
||||
{
|
||||
Parser->Mode = RunModeRun;
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
Parser->Mode = RunModeCaseSearch;
|
||||
}
|
||||
else
|
||||
Condition = ParseIntExpression(Parser);
|
||||
Condition = ExpressionParseInt(Parser);
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenColon)
|
||||
ProgramFail(Parser, "':' expected");
|
||||
|
@ -1033,7 +429,7 @@ int ParseStatement(struct ParseState *Parser)
|
|||
case TokenReturn:
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (!ParseExpression(Parser, &CValue) && TopStackFrame->ReturnValue->Typ->Base != TypeVoid)
|
||||
if (!ExpressionParse(Parser, &CValue) && TopStackFrame->ReturnValue->Typ->Base != TypeVoid)
|
||||
ProgramFail(Parser, "value required in return");
|
||||
|
||||
if (CValue->Typ != TopStackFrame->ReturnValue->Typ)
|
||||
|
|
6
picoc.h
6
picoc.h
|
@ -265,13 +265,15 @@ void LexInteractiveCompleted(struct ParseState *Parser);
|
|||
void LexInteractiveStatementPrompt();
|
||||
|
||||
/* parse.c */
|
||||
int ParseExpression(struct ParseState *Parser, struct Value **Result);
|
||||
int ParseIntExpression(struct ParseState *Parser);
|
||||
int ParseStatement(struct ParseState *Parser);
|
||||
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier, int IsProtoType);
|
||||
void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt);
|
||||
void ParseInteractive();
|
||||
|
||||
/* expression.c */
|
||||
int ExpressionParse(struct ParseState *Parser, struct Value **Result);
|
||||
int ExpressionParseInt(struct ParseState *Parser);
|
||||
|
||||
/* type.c */
|
||||
void TypeInit();
|
||||
int TypeSize(struct ValueType *Typ, int ArraySize);
|
||||
|
|
2
type.c
2
type.c
|
@ -263,7 +263,7 @@ void TypeParseIdentPart(struct ParseState *Parser, struct ValueType *BasicTyp, s
|
|||
{
|
||||
enum RunMode OldMode = Parser->Mode;
|
||||
Parser->Mode = RunModeRun;
|
||||
int ArraySize = ParseIntExpression(Parser);
|
||||
int ArraySize = ExpressionParseInt(Parser);
|
||||
Parser->Mode = OldMode;
|
||||
|
||||
if (LexGetToken(Parser, NULL, TRUE) != TokenRightSquareBracket)
|
||||
|
|
Loading…
Reference in a new issue