Implemented the ternary operator
git-svn-id: http://picoc.googlecode.com/svn/trunk@458 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
d51b1d9726
commit
8021fed051
54
expression.c
54
expression.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
/* whether evaluation is left to right for a given precedence level */
|
||||
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 3 && (p) != 14)
|
||||
#define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 14)
|
||||
#define BRACKET_PRECEDENCE 20
|
||||
#define IS_TYPE_TOKEN(t) ((t) >= TokenIntType && (t) <= TokenUnsignedType)
|
||||
|
||||
|
@ -403,6 +403,39 @@ void ExpressionAssign(struct ParseState *Parser, struct Value *DestValue, struct
|
|||
}
|
||||
}
|
||||
|
||||
/* evaluate the first half of a ternary operator x ? y : z */
|
||||
void ExpressionQuestionMarkOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue)
|
||||
{
|
||||
if (!IS_NUMERIC_COERCIBLE(TopValue))
|
||||
ProgramFail(Parser, "first argument to '?' should be a number");
|
||||
|
||||
if (ExpressionCoerceInteger(TopValue))
|
||||
{
|
||||
/* the condition's true, return the BottomValue */
|
||||
ExpressionStackPushValue(Parser, StackTop, BottomValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the condition's false, return void */
|
||||
ExpressionStackPushValueByType(Parser, StackTop, &VoidType);
|
||||
}
|
||||
}
|
||||
|
||||
/* evaluate the second half of a ternary operator x ? y : z */
|
||||
void ExpressionColonOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, struct Value *BottomValue, struct Value *TopValue)
|
||||
{
|
||||
if (TopValue->Typ->Base == TypeVoid)
|
||||
{
|
||||
/* invoke the "else" part - return the BottomValue */
|
||||
ExpressionStackPushValue(Parser, StackTop, BottomValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* it was a "then" - return the TopValue */
|
||||
ExpressionStackPushValue(Parser, StackTop, TopValue);
|
||||
}
|
||||
}
|
||||
|
||||
/* evaluate a prefix operator */
|
||||
void ExpressionPrefixOperator(struct ParseState *Parser, struct ExpressionStack **StackTop, enum LexToken Op, struct Value *TopValue)
|
||||
{
|
||||
|
@ -610,6 +643,12 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
|
|||
|
||||
ExpressionStackPushValueNode(Parser, StackTop, Result);
|
||||
}
|
||||
else if (Op == TokenQuestionMark)
|
||||
ExpressionQuestionMarkOperator(Parser, StackTop, TopValue, BottomValue);
|
||||
|
||||
else if (Op == TokenColon)
|
||||
ExpressionColonOperator(Parser, StackTop, TopValue, BottomValue);
|
||||
|
||||
#ifndef NO_FP
|
||||
else if ( (TopValue->Typ == &FPType && BottomValue->Typ == &FPType) ||
|
||||
(TopValue->Typ == &FPType && IS_NUMERIC_COERCIBLE(BottomValue)) ||
|
||||
|
@ -667,8 +706,6 @@ void ExpressionInfixOperator(struct ParseState *Parser, struct ExpressionStack *
|
|||
case TokenArithmeticAndAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt & TopInt, FALSE); break;
|
||||
case TokenArithmeticOrAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt | TopInt, FALSE); break;
|
||||
case TokenArithmeticExorAssign: ResultInt = ExpressionAssignInt(Parser, BottomValue, BottomInt ^ TopInt, FALSE); break;
|
||||
case TokenQuestionMark: ProgramFail(Parser, "not supported"); break; /* XXX */
|
||||
case TokenColon: ProgramFail(Parser, "not supported"); break; /* XXX */
|
||||
case TokenLogicalOr: ResultInt = BottomInt || TopInt; break;
|
||||
case TokenLogicalAnd: ResultInt = BottomInt && TopInt; break;
|
||||
case TokenArithmeticOr: ResultInt = BottomInt | TopInt; break;
|
||||
|
@ -939,8 +976,8 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
struct ParseState PreState = *Parser;
|
||||
enum LexToken Token = LexGetToken(Parser, &LexValue, TRUE);
|
||||
if ( ( ( (int)Token > TokenComma && (int)Token <= (int)TokenOpenBracket) ||
|
||||
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
||||
(Token != TokenColon || TernaryDepth != 0) )
|
||||
(Token == TokenCloseBracket && BracketPrecedence != 0)) &&
|
||||
(Token != TokenColon || TernaryDepth > 0) )
|
||||
{
|
||||
/* it's an operator with precedence */
|
||||
if (PrefixState)
|
||||
|
@ -1035,6 +1072,13 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
|
||||
ExpressionStackPushOperator(Parser, &StackTop, OrderInfix, Token, Precedence);
|
||||
PrefixState = TRUE;
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenQuestionMark: TernaryDepth++; break;
|
||||
case TokenColon: TernaryDepth--; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* treat an open square bracket as an infix array index operator followed by an open bracket */
|
||||
|
|
|
@ -29,6 +29,7 @@ TESTS= 00_assignment.test \
|
|||
29_array_address.test \
|
||||
30_hanoi.test \
|
||||
31_args.test \
|
||||
33_ternary_op.test \
|
||||
34_array_assignment.test \
|
||||
35_sizeof.test \
|
||||
36_array_initialisers.test \
|
||||
|
|
17
variable.c
17
variable.c
|
@ -1,5 +1,8 @@
|
|||
#include "picoc.h"
|
||||
|
||||
/* maximum size of a value to temporarily copy while we create a variable */
|
||||
#define MAX_TMP_COPY_BUF 256
|
||||
|
||||
/* the table of global definitions */
|
||||
struct Table GlobalTable;
|
||||
struct TableEntry *GlobalHashTable[GLOBAL_TABLE_SIZE];
|
||||
|
@ -109,13 +112,19 @@ struct Value *VariableAllocValueFromType(struct ParseState *Parser, struct Value
|
|||
return NewValue;
|
||||
}
|
||||
|
||||
/* allocate a value either on the heap or the stack and copy its value */
|
||||
/* allocate a value either on the heap or the stack and copy its value. handles overlapping data */
|
||||
struct Value *VariableAllocValueAndCopy(struct ParseState *Parser, struct Value *FromValue, int OnHeap)
|
||||
{
|
||||
struct ValueType *DType = FromValue->Typ;
|
||||
struct Value *NewValue;
|
||||
char TmpBuf[MAX_TMP_COPY_BUF];
|
||||
int CopySize = TypeSizeValue(FromValue);
|
||||
struct Value *NewValue = VariableAllocValueAndData(Parser, CopySize, FromValue->IsLValue, FromValue->LValueFrom, OnHeap);
|
||||
NewValue->Typ = FromValue->Typ;
|
||||
memcpy((void *)NewValue->Val, (void *)FromValue->Val, CopySize);
|
||||
|
||||
assert(CopySize <= MAX_TMP_COPY_BUF);
|
||||
memcpy((void *)&TmpBuf[0], (void *)FromValue->Val, CopySize);
|
||||
NewValue = VariableAllocValueAndData(Parser, CopySize, FromValue->IsLValue, FromValue->LValueFrom, OnHeap);
|
||||
NewValue->Typ = DType;
|
||||
memcpy((void *)NewValue->Val, (void *)&TmpBuf[0], CopySize);
|
||||
|
||||
return NewValue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue