2009-03-08 03:56:28 -04:00
# include "picoc.h"
2009-03-11 22:21:12 -04:00
/* whether evaluation is left to right for a given precedence level */
# define IS_LEFT_TO_RIGHT(p) ((p) != 2 && (p) != 3 && (p) != 14)
2009-03-28 07:10:34 -04:00
# ifndef NO_FP
# define IS_INTEGER_COERCIBLE(v) ((v)->Typ->Base == TypeInt || (v)->Typ->Base == TypeFP || (v)->Typ->Base == TypeChar)
# define COERCE_INTEGER(v) (((v)->Typ->Base == TypeFP) ? (int)(v)->Val->FP : (v)->Val->Integer)
# else
# define IS_INTEGER_COERCIBLE(v) ((v)->Typ->Base == TypeInt || (v)->Typ->Base == TypeChar)
# define COERCE_INTEGER(v) ((v)->Val->Integer)
# endif
2009-04-13 23:18:40 -04:00
/* helper macros for assignment */
2009-04-13 02:57:32 -04:00
# define ASSIGN_INT(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultInt = (s); (d)->Val->Integer = ResultInt; }
2009-04-13 05:02:45 -04:00
# define ASSIGN_INT_AFTER(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultInt = (d)->Val->Integer; (d)->Val->Integer = (s); }
2009-04-13 23:18:40 -04:00
# define ASSIGN_FP(d,s) { if (!(d)->IsLValue) ProgramFail(Parser, "can't assign to this"); ResultFP = (s); (d)->Val->FP = ResultFP; }
2009-04-13 02:57:32 -04:00
2009-03-28 07:10:34 -04:00
# define BRACKET_PRECEDENCE 20
2009-03-11 22:21:12 -04:00
2009-04-13 02:57:32 -04:00
# ifdef DEBUG_EXPRESSIONS
# define debugf printf
# else
void debugf ( char * Format , . . . )
{
}
# endif
2009-03-11 22:21:12 -04:00
2009-04-14 02:55:00 -04:00
# ifndef NEW_EXPRESSION_SYSTEM
2009-03-08 03:56:28 -04:00
/* local prototypes */
void ExpressionParseFunctionCall ( struct ParseState * Parser , struct Value * * Result , const char * FuncName ) ;
/* 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 ;
2009-03-16 00:25:58 -04:00
char * Identifier ;
2009-03-08 03:56:28 -04:00
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 ) ;
* 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 ;
2009-03-15 03:07:21 -04:00
( * Result ) - > Val - > Pointer . Offset = ( void * ) ( * Result ) - > Val - ( void * ) ( * Result ) - > LValueFrom ;
2009-03-08 03:56:28 -04:00
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 ;
2009-03-16 00:25:58 -04:00
case TokenNew :
TypeParse ( Parser , & VType , & Identifier ) ;
if ( Identifier ! = StrEmpty )
ProgramFail ( Parser , " identifier not expected here " ) ;
if ( Parser - > Mode = = RunModeRun )
{ /* create an object of this type on the heap and a pointer to it on the stack */
LocalLValue = VariableAllocValueFromType ( Parser , VType , TRUE , NULL ) ;
* Result = VariableAllocValueFromType ( Parser , TypeGetMatching ( Parser , VType , TypePointer , 0 , StrEmpty ) , FALSE , NULL ) ;
( * Result ) - > Val - > Pointer . Segment = LocalLValue ;
( * Result ) - > Val - > Pointer . Offset = 0 ;
}
break ;
2009-03-08 03:56:28 -04:00
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 ;
2009-03-09 19:18:04 -04:00
struct Value * TotalLValueFrom = TotalValue - > LValueFrom ;
2009-03-08 03:56:28 -04:00
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 ) ;
2009-03-09 19:18:04 -04:00
TotalValue = VariableAllocValueFromExistingData ( Parser , CurrentValue - > Typ , TotalValueData + CurrentValue - > Val - > Integer , TRUE , TotalLValueFrom ) ;
}
continue ;
}
case TokenArrow :
{
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 ;
struct Value * DerefValue ;
if ( TotalValue - > Typ - > Base ! = TypePointer )
ProgramFail ( Parser , " can't dereference this non-pointer " ) ;
DerefValue = TotalValue - > Val - > Pointer . Segment ;
TotalValueData = ( void * ) DerefValue - > Val ;
if ( DerefValue - > Typ - > Base ! = TypeStruct & & DerefValue - > Typ - > Base ! = TypeUnion )
ProgramFail ( Parser , " can't use '->' on something that's not a struct or union " ) ;
if ( ! TableGet ( DerefValue - > 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 , DerefValue ) ;
2009-03-08 03:56:28 -04:00
}
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 )
2009-04-03 23:11:12 -04:00
memcpy ( ( void * ) TotalValue - > Val , ( void * ) CurrentValue - > Val , TotalValue - > Typ - > Sizeof ) ;
2009-03-08 03:56:28 -04:00
else
{ /* array assignment */
if ( TotalValue - > Val - > Array . Size ! = CurrentValue - > Val - > Array . Size )
ProgramFail ( Parser , " incompatible array sizes in assignment " ) ;
2009-04-13 02:57:32 -04:00
// XXX - fix this memcpy(TotalValue->Val->Array.Data, CurrentValue->Val->Array.Data, CurrentValue->Typ->Sizeof * CurrentValue->Val->Array.Size);
2009-03-08 03:56:28 -04:00
}
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 ;
2009-04-03 23:11:12 -04:00
default : IntResult = 0 ; break ;
2009-03-08 03:56:28 -04:00
}
TotalValue = ParsePushInt ( Parser , IntResult ) ;
}
* Result = TotalValue ;
}
}
return TRUE ;
}
2009-04-04 22:24:00 -04:00
/* do a function call */
void ExpressionParseFunctionCall ( struct ParseState * Parser , struct Value * * Result , const char * FuncName )
{
struct Value * FuncValue ;
struct Value * Param ;
struct Value * * ParamArray = NULL ;
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 ( ) ;
}
}
2009-03-08 03:56:28 -04:00
# else
2009-04-04 22:24:00 -04:00
/* local prototypes */
2009-03-11 22:21:12 -04:00
enum OperatorOrder
{
2009-03-29 07:08:03 -04:00
OrderNone ,
2009-03-11 22:21:12 -04:00
OrderPrefix ,
OrderInfix ,
OrderPostfix
} ;
/* a stack of expressions we use in evaluation */
struct ExpressionStack
{
2009-04-13 02:57:32 -04:00
struct ExpressionStack * Next ; /* the next lower item on the stack */
union
{
struct Value * Val ; /* the value for this stack node */
enum LexToken Op ; /* the operator */
} p ;
short unsigned int Precedence ; /* the operator precedence of this node */
unsigned char Order ; /* the evaluation order of this operator */
2009-03-11 22:21:12 -04:00
} ;
2009-03-08 03:56:28 -04:00
/* operator precedence definitions */
struct OpPrecedence
{
unsigned char PrefixPrecedence : 4 ;
unsigned char PostfixPrecedence : 4 ;
unsigned char InfixPrecedence : 4 ;
2009-04-13 02:57:32 -04:00
char * Name ;
2009-03-08 03:56:28 -04:00
} ;
static struct OpPrecedence OperatorPrecedence [ ] =
{
2009-04-13 02:57:32 -04:00
/* TokenNone, */ { 0 , 0 , 0 , " none " } ,
/* TokenComma, */ { 0 , 0 , 0 , " , " } ,
/* 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 , " | " } ,
/* TokenArithmeticExor, */ { 0 , 0 , 7 , " ^ " } ,
/* TokenAmpersand, */ { 14 , 0 , 8 , " & " } ,
/* TokenEqual, */ { 0 , 0 , 9 , " == " } , /* 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 , " sizeof " } ,
2009-04-14 02:55:00 -04:00
/* TokenLeftSquareBracket, */ { 0 , 0 , 15 , " [ " } , /* TokenRightSquareBracket, */ { 0 , 15 , 0 , " ] " } , /* TokenDot, */ { 0 , 0 , 15 , " . " } , /* TokenArrow, */ { 0 , 0 , 15 , " -> " } ,
2009-04-13 02:57:32 -04:00
/* TokenOpenBracket, */ { 15 , 0 , 0 , " ( " } , /* TokenCloseBracket, */ { 0 , 15 , 0 , " ) " }
2009-03-08 03:56:28 -04:00
} ;
2009-04-04 22:24:00 -04:00
void ExpressionParseFunctionCall ( struct ParseState * Parser , struct ExpressionStack * * StackTop , const char * FuncName ) ;
2009-04-13 02:57:32 -04:00
# ifdef DEBUG_EXPRESSIONS
/* show the contents of the expression stack */
void ExpressionStackShow ( struct ExpressionStack * StackTop )
{
printf ( " Expression stack: " ) ;
while ( StackTop ! = NULL )
{
if ( StackTop - > Order = = OrderNone )
2009-04-14 02:55:00 -04:00
{
/* it's a value */
2009-04-13 02:57:32 -04:00
if ( StackTop - > p . Val - > IsLValue )
printf ( " lvalue= " ) ;
else
printf ( " value= " ) ;
switch ( StackTop - > p . Val - > Typ - > Base )
{
2009-04-13 23:18:40 -04:00
case TypeVoid : printf ( " void " ) ; break ;
2009-04-13 02:57:32 -04:00
case TypeInt : case TypeChar : printf ( " %d:int " , StackTop - > p . Val - > Val - > Integer ) ; break ;
case TypeFP : printf ( " %f:fp " , StackTop - > p . Val - > Val - > FP ) ; break ;
case TypeFunction : printf ( " %s:function " , StackTop - > p . Val - > Val - > Identifier ) ; break ;
case TypeMacro : printf ( " %s:macro " , StackTop - > p . Val - > Val - > Identifier ) ; break ;
case TypePointer :
if ( StackTop - > p . Val - > Typ - > FromType - > Base = = TypeChar )
printf ( " \" %s \" :string " , ( char * ) StackTop - > p . Val - > Val - > Pointer . Segment - > Val - > Array . Data ) ;
else
printf ( " ptr(0x%lx,%d) " , ( long ) StackTop - > p . Val - > Val - > Pointer . Segment , StackTop - > p . Val - > Val - > Pointer . Offset ) ;
break ;
case TypeArray : printf ( " array " ) ; break ;
case TypeStruct : printf ( " %s:struct " , StackTop - > p . Val - > Val - > Identifier ) ; break ;
case TypeUnion : printf ( " %s:union " , StackTop - > p . Val - > Val - > Identifier ) ; break ;
case TypeEnum : printf ( " %s:enum " , StackTop - > p . Val - > Val - > Identifier ) ; break ;
default : printf ( " unknown " ) ; break ;
}
}
else
{ /* it's an operator */
printf ( " op='%s' %s %d " , OperatorPrecedence [ ( int ) StackTop - > p . Op ] . Name ,
( StackTop - > Order = = OrderPrefix ) ? " prefix " : ( ( StackTop - > Order = = OrderPostfix ) ? " postfix " : " infix " ) ,
StackTop - > Precedence ) ;
}
StackTop = StackTop - > Next ;
if ( StackTop ! = NULL )
printf ( " , " ) ;
}
printf ( " \n " ) ;
}
# endif
2009-03-28 07:10:34 -04:00
/* push a node on to the expression stack */
void ExpressionStackPushValueNode ( struct ParseState * Parser , struct ExpressionStack * * StackTop , struct Value * ValueLoc )
{
struct ExpressionStack * StackNode = VariableAlloc ( Parser , sizeof ( struct ExpressionStack ) , FALSE ) ;
StackNode - > Next = * StackTop ;
2009-04-13 02:57:32 -04:00
StackNode - > p . Val = ValueLoc ;
2009-03-28 07:10:34 -04:00
* StackTop = StackNode ;
2009-04-13 02:57:32 -04:00
# ifdef DEBUG_EXPRESSIONS
ExpressionStackShow ( * StackTop ) ;
# endif
2009-03-28 07:10:34 -04:00
}
2009-04-04 22:24:00 -04:00
/* push a blank value on to the expression stack by type */
void ExpressionStackPushValueByType ( struct ParseState * Parser , struct ExpressionStack * * StackTop , struct ValueType * PushType )
{
struct Value * ValueLoc = VariableAllocValueFromType ( Parser , PushType , FALSE , NULL ) ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionStackPushValueByType() \n " ) ;
2009-04-04 22:24:00 -04:00
ExpressionStackPushValueNode ( Parser , StackTop , ValueLoc ) ;
}
2009-03-28 07:10:34 -04:00
/* push a value on to the expression stack */
void ExpressionStackPushValue ( struct ParseState * Parser , struct ExpressionStack * * StackTop , struct Value * PushValue )
{
struct Value * ValueLoc = VariableAllocValueAndCopy ( Parser , PushValue , FALSE ) ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionStackPushValue() \n " ) ;
ExpressionStackPushValueNode ( Parser , StackTop , ValueLoc ) ;
}
void ExpressionStackPushLValue ( struct ParseState * Parser , struct ExpressionStack * * StackTop , struct Value * PushValue )
{
struct Value * ValueLoc = VariableAllocValueShared ( Parser , PushValue ) ;
debugf ( " ExpressionStackPushLValue() \n " ) ;
2009-03-28 07:10:34 -04:00
ExpressionStackPushValueNode ( Parser , StackTop , ValueLoc ) ;
}
void ExpressionPushInt ( struct ParseState * Parser , struct ExpressionStack * * StackTop , int IntValue )
{
struct Value * ValueLoc = VariableAllocValueFromType ( Parser , & IntType , FALSE , NULL ) ;
ValueLoc - > Val - > Integer = IntValue ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionPushInt() \n " ) ;
2009-03-28 07:10:34 -04:00
ExpressionStackPushValueNode ( Parser , StackTop , ValueLoc ) ;
}
void ExpressionPushFP ( struct ParseState * Parser , struct ExpressionStack * * StackTop , double FPValue )
{
2009-04-04 22:24:00 -04:00
struct Value * ValueLoc = VariableAllocValueFromType ( Parser , & FPType , FALSE , NULL ) ;
2009-03-28 07:10:34 -04:00
ValueLoc - > Val - > FP = FPValue ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionPushFP() \n " ) ;
2009-03-28 07:10:34 -04:00
ExpressionStackPushValueNode ( Parser , StackTop , ValueLoc ) ;
}
2009-03-12 06:49:57 -04:00
/* evaluate a prefix operator */
2009-03-28 07:10:34 -04:00
void ExpressionPrefixOperator ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum LexToken Op , struct Value * TopValue )
2009-03-12 06:49:57 -04:00
{
2009-03-28 07:10:34 -04:00
struct Value * TempLValue ;
struct Value * Result ;
2009-04-13 05:02:45 -04:00
if ( Parser - > Mode ! = RunModeRun )
{
/* we're not running it so just return 0 */
ExpressionPushInt ( Parser , StackTop , 0 ) ;
return ;
}
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionPrefixOperator() \n " ) ;
2009-03-28 07:10:34 -04:00
switch ( Op )
2009-03-12 06:49:57 -04:00
{
case TokenAmpersand :
if ( ! TopValue - > IsLValue )
ProgramFail ( Parser , " can't get the address of this " ) ;
TempLValue = TopValue - > LValueFrom ;
Result = VariableAllocValueFromType ( Parser , TypeGetMatching ( Parser , TopValue - > Typ , TypePointer , 0 , StrEmpty ) , FALSE , NULL ) ;
Result - > Val - > Pointer . Segment = TempLValue ;
2009-03-28 07:10:34 -04:00
Result - > Val - > Pointer . Offset = ( void * ) Result - > Val - ( void * ) Result - > LValueFrom ;
2009-03-12 06:49:57 -04:00
ExpressionStackPushValueNode ( Parser , StackTop , Result ) ;
break ;
2009-03-28 07:10:34 -04:00
2009-03-12 06:49:57 -04:00
case TokenAsterisk :
if ( TopValue - > Typ - > Base ! = TypePointer )
ProgramFail ( Parser , " can't dereference this non-pointer " ) ;
2009-04-13 02:57:32 -04:00
ExpressionStackPushLValue ( Parser , StackTop , TopValue - > Val - > Pointer . Segment ) ;
2009-03-12 06:49:57 -04:00
break ;
case TokenSizeof :
// XXX
break ;
case TokenLeftSquareBracket :
// XXX
break ;
case TokenOpenBracket :
2009-04-14 02:55:00 -04:00
// XXX - cast
2009-03-12 06:49:57 -04:00
break ;
default :
/* an arithmetic operator */
if ( IS_INTEGER_COERCIBLE ( TopValue ) )
{
/* integer prefix arithmetic */
2009-03-28 07:10:34 -04:00
int ResultInt ;
2009-03-12 06:49:57 -04:00
int TopInt = COERCE_INTEGER ( TopValue ) ;
2009-03-28 07:10:34 -04:00
switch ( Op )
2009-03-12 06:49:57 -04:00
{
case TokenPlus : ResultInt = TopInt ; break ;
case TokenMinus : ResultInt = - TopInt ; break ;
2009-04-13 05:02:45 -04:00
case TokenIncrement : ASSIGN_INT ( TopValue , TopInt + 1 ) ; break ;
case TokenDecrement : ASSIGN_INT ( TopValue , TopInt - 1 ) ; break ;
2009-03-12 06:49:57 -04:00
case TokenUnaryNot : ResultInt = ! TopInt ; break ;
case TokenUnaryExor : ResultInt = ~ TopInt ; break ;
2009-03-28 07:10:34 -04:00
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
2009-03-12 06:49:57 -04:00
}
ExpressionPushInt ( Parser , StackTop , ResultInt ) ;
}
# ifndef NO_FP
else if ( TopValue - > Typ = = & FPType )
{
/* floating point prefix arithmetic */
2009-03-28 07:10:34 -04:00
double ResultFP ;
switch ( Op )
2009-03-12 06:49:57 -04:00
{
case TokenPlus : ResultFP = TopValue - > Val - > FP ; break ;
case TokenMinus : ResultFP = - TopValue - > Val - > FP ; break ;
2009-03-28 07:10:34 -04:00
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
2009-03-12 06:49:57 -04:00
}
}
# endif
2009-03-28 07:10:34 -04:00
#if 0
XXX - finish this
2009-03-12 06:49:57 -04:00
else
{
/* pointer prefix arithmetic */
int TopInt = COERCE_INTEGER ( TopValue ) ;
}
2009-03-28 07:10:34 -04:00
# endif
2009-03-12 06:49:57 -04:00
break ;
}
}
/* evaluate a postfix operator */
2009-03-28 07:10:34 -04:00
void ExpressionPostfixOperator ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum LexToken Op , struct Value * TopValue )
2009-03-12 06:49:57 -04:00
{
2009-04-13 05:02:45 -04:00
if ( Parser - > Mode ! = RunModeRun )
{
/* we're not running it so just return 0 */
ExpressionPushInt ( Parser , StackTop , 0 ) ;
return ;
}
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionPostfixOperator() \n " ) ;
2009-03-12 06:49:57 -04:00
if ( IS_INTEGER_COERCIBLE ( TopValue ) )
{
2009-03-28 07:10:34 -04:00
int ResultInt ;
2009-03-12 06:49:57 -04:00
int TopInt = COERCE_INTEGER ( TopValue ) ;
2009-03-28 07:10:34 -04:00
switch ( Op )
2009-03-12 06:49:57 -04:00
{
2009-04-13 05:02:45 -04:00
case TokenIncrement : ASSIGN_INT_AFTER ( TopValue , TopInt + 1 ) ; break ;
case TokenDecrement : ASSIGN_INT_AFTER ( TopValue , TopInt + 1 ) ; break ;
2009-03-12 06:49:57 -04:00
case TokenRightSquareBracket : break ; // XXX
case TokenCloseBracket : break ; // XXX
2009-03-28 07:10:34 -04:00
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
2009-03-12 06:49:57 -04:00
}
2009-03-28 07:10:34 -04:00
ExpressionPushInt ( Parser , StackTop , ResultInt ) ;
}
2009-03-12 06:49:57 -04:00
}
/* evaluate an infix operator */
2009-03-28 07:10:34 -04:00
void ExpressionInfixOperator ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum LexToken Op , struct Value * BottomValue , struct Value * TopValue )
2009-03-12 06:49:57 -04:00
{
2009-03-28 07:10:34 -04:00
int ResultIsInt = FALSE ;
int ResultInt ;
2009-04-13 05:02:45 -04:00
if ( Parser - > Mode ! = RunModeRun )
{
/* we're not running it so just return 0 */
ExpressionPushInt ( Parser , StackTop , 0 ) ;
return ;
}
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionInfixOperator() \n " ) ;
2009-04-14 02:55:00 -04:00
if ( Op = = TokenLeftSquareBracket )
{
/* array index */
int ArrayIndex ;
struct Value * Result ;
if ( BottomValue - > Typ - > Base ! = TypeArray )
ProgramFail ( Parser , " not an array " ) ;
if ( ! IS_INTEGER_COERCIBLE ( TopValue ) )
ProgramFail ( Parser , " array index must be an integer " ) ;
ArrayIndex = COERCE_INTEGER ( TopValue ) ;
if ( ArrayIndex < 0 | | ArrayIndex > = BottomValue - > Val - > Array . Size )
ProgramFail ( Parser , " illegal array index %d [0..%d] " , ArrayIndex , BottomValue - > Val - > Array . Size - 1 ) ;
/* make the array element result */
Result = VariableAllocValueFromExistingData ( Parser , BottomValue - > Typ - > FromType , ( union AnyValue * ) ( BottomValue - > Val - > Array . Data + TypeSize ( BottomValue - > Typ - > FromType , 0 ) * ArrayIndex ) , BottomValue - > IsLValue , BottomValue - > LValueFrom ) ;
ExpressionStackPushValueNode ( Parser , StackTop , Result ) ;
}
else if ( IS_INTEGER_COERCIBLE ( TopValue ) & & IS_INTEGER_COERCIBLE ( BottomValue ) )
{
/* integer operation */
2009-04-13 23:18:40 -04:00
int TopInt = COERCE_INTEGER ( TopValue ) ;
int BottomInt = COERCE_INTEGER ( BottomValue ) ;
switch ( Op )
{
case TokenAssign : ASSIGN_INT ( BottomValue , TopInt ) ; break ;
case TokenAddAssign : ASSIGN_INT ( BottomValue , BottomInt + TopInt ) ; break ;
case TokenSubtractAssign : ASSIGN_INT ( BottomValue , BottomInt - TopInt ) ; break ;
case TokenMultiplyAssign : ASSIGN_INT ( BottomValue , BottomInt * TopInt ) ; break ;
case TokenDivideAssign : ASSIGN_INT ( BottomValue , BottomInt / TopInt ) ; break ;
case TokenModulusAssign : ASSIGN_INT ( BottomValue , BottomInt % TopInt ) ; break ;
case TokenShiftLeftAssign : ASSIGN_INT ( BottomValue , BottomInt < < TopInt ) ; break ;
case TokenShiftRightAssign : ASSIGN_INT ( BottomValue , BottomInt > > TopInt ) ; break ;
case TokenArithmeticAndAssign : ASSIGN_INT ( BottomValue , BottomInt & TopInt ) ; break ;
case TokenArithmeticOrAssign : ASSIGN_INT ( BottomValue , BottomInt | TopInt ) ; break ;
case TokenArithmeticExorAssign : ASSIGN_INT ( BottomValue , BottomInt ^ TopInt ) ; break ;
case TokenQuestionMark : break ; // XXX
case TokenColon : break ; // XXX
case TokenLogicalOr : ResultInt = BottomInt | | TopInt ; break ;
case TokenLogicalAnd : ResultInt = BottomInt & & TopInt ; break ;
case TokenArithmeticOr : ResultInt = BottomInt | TopInt ; break ;
case TokenArithmeticExor : ResultInt = BottomInt ^ TopInt ; break ;
case TokenAmpersand : ResultInt = BottomInt & TopInt ; break ;
case TokenEqual : ResultInt = BottomInt = = TopInt ; break ;
case TokenNotEqual : ResultInt = BottomInt ! = TopInt ; break ;
case TokenLessThan : ResultInt = BottomInt < TopInt ; break ;
case TokenGreaterThan : ResultInt = BottomInt > TopInt ; break ;
case TokenLessEqual : ResultInt = BottomInt < = TopInt ; break ;
case TokenGreaterEqual : ResultInt = BottomInt > = TopInt ; break ;
case TokenShiftLeft : ResultInt = BottomInt < < TopInt ; break ;
case TokenShiftRight : ResultInt = BottomInt < < TopInt ; break ;
case TokenPlus : ResultInt = BottomInt + TopInt ; break ;
case TokenMinus : ResultInt = BottomInt - TopInt ; break ;
case TokenAsterisk : ResultInt = BottomInt * TopInt ; break ;
case TokenSlash : ResultInt = BottomInt / TopInt ; break ;
case TokenModulus : ResultInt = BottomInt % TopInt ; break ;
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
}
ExpressionPushInt ( Parser , StackTop , ResultInt ) ;
}
2009-03-12 06:49:57 -04:00
# ifndef NO_FP
2009-04-13 23:18:40 -04:00
else if ( ( TopValue - > Typ = = & FPType & & BottomValue - > Typ = = & FPType ) | |
( TopValue - > Typ = = & FPType & & IS_INTEGER_COERCIBLE ( BottomValue ) ) | |
( IS_INTEGER_COERCIBLE ( TopValue ) & & BottomValue - > Typ = = & FPType ) )
{
/* floating point infix arithmetic */
double ResultFP ;
double TopFP = ( TopValue - > Typ = = & FPType ) ? TopValue - > Val - > FP : ( double ) COERCE_INTEGER ( TopValue ) ;
double BottomFP = ( BottomValue - > Typ = = & FPType ) ? BottomValue - > Val - > FP : ( double ) COERCE_INTEGER ( BottomValue ) ;
2009-03-12 06:49:57 -04:00
2009-04-13 23:18:40 -04:00
switch ( Op )
{
case TokenAssign : ASSIGN_FP ( BottomValue , TopFP ) ; break ;
case TokenAddAssign : ASSIGN_FP ( BottomValue , BottomFP + TopFP ) ; break ;
case TokenSubtractAssign : ASSIGN_FP ( BottomValue , BottomFP - TopFP ) ; break ;
case TokenMultiplyAssign : ASSIGN_FP ( BottomValue , BottomFP * TopFP ) ; break ;
case TokenDivideAssign : ASSIGN_FP ( BottomValue , BottomFP / TopFP ) ; break ;
case TokenEqual : ResultInt = BottomFP = = TopFP ; ResultIsInt = TRUE ; break ;
case TokenNotEqual : ResultInt = BottomFP ! = TopFP ; ResultIsInt = TRUE ; break ;
case TokenLessThan : ResultInt = BottomFP < TopFP ; ResultIsInt = TRUE ; break ;
case TokenGreaterThan : ResultInt = BottomFP > TopFP ; ResultIsInt = TRUE ; break ;
case TokenLessEqual : ResultInt = BottomFP < = TopFP ; ResultIsInt = TRUE ; break ;
case TokenGreaterEqual : ResultInt = BottomFP > = TopFP ; ResultIsInt = TRUE ; break ;
case TokenPlus : ResultFP = BottomFP + TopFP ; break ;
case TokenMinus : ResultFP = BottomFP - TopFP ; break ;
case TokenAsterisk : ResultFP = BottomFP * TopFP ; break ;
case TokenSlash : ResultFP = BottomFP / TopFP ; break ;
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
}
2009-03-12 06:49:57 -04:00
2009-04-13 23:18:40 -04:00
if ( ResultIsInt )
ExpressionPushInt ( Parser , StackTop , ResultInt ) ;
else
ExpressionPushFP ( Parser , StackTop , ResultFP ) ;
}
2009-03-12 06:49:57 -04:00
# endif
2009-03-28 07:10:34 -04:00
#if 0
XXX - finish this
2009-04-13 23:18:40 -04:00
else if ( ( TopValue - > Typ - > Base = = TypePointer & & IS_INTEGER_COERCIBLE ( BottomValue ) ) | |
( IS_INTEGER_COERCIBLE ( TopValue ) & & BottomValue - > Typ - > Base = = TypePointer ) )
{
/* pointer infix arithmetic */
switch ( TopOperatorNode - > Op )
{
case TokenEqual : ResultInt = BottomInt = = TopInt ; ResultIsInt = TRUE ; break ;
case TokenNotEqual : ResultInt = BottomInt ! = TopInt ; ResultIsInt = TRUE ; break ;
case TokenLessThan : ResultInt = BottomInt < TopInt ; ResultIsInt = TRUE ; break ;
case TokenGreaterThan : ResultInt = BottomInt > TopInt ; ResultIsInt = TRUE ; break ;
case TokenLessEqual : ResultInt = BottomInt < = TopInt ; ResultIsInt = TRUE ; break ;
case TokenGreaterEqual : ResultInt = BottomInt > = TopInt ; ResultIsInt = TRUE ; break ;
case TokenPlus : Result = BottomInt + TopInt ; break ;
case TokenMinus : Result = BottomInt - TopInt ; break ;
default : ProgramFail ( Parser , " invalid operation " ) ; break ;
}
if ( ResultIsInt )
ExpressionPushInt ( Parser , StackTop , ResultInt ) ;
else
ExpressionPushPointer ( Parser , StackTop , ResultInt ) ;
2009-03-12 06:49:57 -04:00
}
2009-04-13 23:18:40 -04:00
# endif
else
ProgramFail ( Parser , " invalid operation " ) ;
2009-03-12 06:49:57 -04:00
}
2009-03-08 04:40:05 -04:00
/* take the contents of the expression stack and compute the top until there's nothing greater than the given precedence */
void ExpressionStackCollapse ( struct ParseState * Parser , struct ExpressionStack * * StackTop , int Precedence )
{
2009-03-12 06:49:57 -04:00
int FoundPrecedence = Precedence ;
struct Value * TopValue ;
struct Value * BottomValue ;
struct ExpressionStack * TopStackNode = * StackTop ;
struct ExpressionStack * TopOperatorNode ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionStackCollapse(): \n " ) ;
# ifdef DEBUG_EXPRESSIONS
ExpressionStackShow ( * StackTop ) ;
# endif
2009-03-29 07:08:03 -04:00
while ( TopStackNode ! = NULL & & TopStackNode - > Next ! = NULL & & FoundPrecedence > = Precedence )
2009-03-12 06:49:57 -04:00
{
/* find the top operator on the stack */
2009-04-13 05:02:45 -04:00
if ( TopStackNode - > Order = = OrderNone )
2009-03-12 06:49:57 -04:00
TopOperatorNode = TopStackNode - > Next ;
else
TopOperatorNode = TopStackNode ;
2009-04-13 02:57:32 -04:00
FoundPrecedence = TopOperatorNode - > Precedence ;
2009-03-12 06:49:57 -04:00
/* does it have a high enough precedence? */
2009-03-29 07:08:03 -04:00
if ( FoundPrecedence > = Precedence & & TopOperatorNode ! = NULL )
2009-03-12 06:49:57 -04:00
{
/* execute this operator */
switch ( TopOperatorNode - > Order )
{
case OrderPrefix :
/* prefix evaluation */
2009-04-13 02:57:32 -04:00
debugf ( " prefix evaluation \n " ) ;
TopValue = TopStackNode - > p . Val ;
2009-03-12 06:49:57 -04:00
/* pop the value and then the prefix operator - assume they'll still be there until we're done */
2009-04-13 02:57:32 -04:00
HeapPopStack ( TopOperatorNode , sizeof ( struct ExpressionStack ) * 2 + sizeof ( struct Value ) + TypeStackSizeValue ( TopValue ) ) ;
2009-04-13 05:02:45 -04:00
* StackTop = TopOperatorNode - > Next ;
2009-03-12 06:49:57 -04:00
/* do the prefix operation */
2009-04-13 02:57:32 -04:00
ExpressionPrefixOperator ( Parser , StackTop , TopOperatorNode - > p . Op , TopValue ) ;
2009-03-12 06:49:57 -04:00
break ;
case OrderPostfix :
/* postfix evaluation */
2009-04-13 02:57:32 -04:00
debugf ( " postfix evaluation \n " ) ;
TopValue = TopStackNode - > Next - > p . Val ;
2009-03-12 06:49:57 -04:00
2009-04-13 05:02:45 -04:00
/* pop the postfix operator and then the value - assume they'll still be there until we're done */
HeapPopStack ( TopValue , sizeof ( struct ExpressionStack ) * 2 + sizeof ( struct Value ) + TypeStackSizeValue ( TopValue ) ) ;
2009-03-28 07:10:34 -04:00
* StackTop = TopStackNode - > Next - > Next ;
2009-03-12 06:49:57 -04:00
/* do the postfix operation */
2009-04-13 02:57:32 -04:00
ExpressionPostfixOperator ( Parser , StackTop , TopOperatorNode - > p . Op , TopValue ) ;
2009-03-12 06:49:57 -04:00
break ;
case OrderInfix :
/* infix evaluation */
2009-04-13 02:57:32 -04:00
debugf ( " infix evaluation \n " ) ;
TopValue = TopStackNode - > p . Val ;
BottomValue = TopOperatorNode - > Next - > p . Val ;
/* pop a value, the operator and another value - assume they'll still be there until we're done */
HeapPopStack ( BottomValue , sizeof ( struct ExpressionStack ) * 3 + sizeof ( struct Value ) * 2 + TypeStackSizeValue ( TopValue ) + TypeStackSizeValue ( BottomValue ) ) ;
* StackTop = TopOperatorNode - > Next - > Next ;
2009-03-12 06:49:57 -04:00
/* do the infix operation */
2009-04-13 02:57:32 -04:00
ExpressionInfixOperator ( Parser , StackTop , TopOperatorNode - > p . Op , BottomValue , TopValue ) ;
2009-03-12 06:49:57 -04:00
break ;
2009-03-29 07:08:03 -04:00
case OrderNone :
break ;
2009-03-12 06:49:57 -04:00
}
}
2009-04-13 02:57:32 -04:00
# ifdef DEBUG_EXPRESSIONS
ExpressionStackShow ( * StackTop ) ;
# endif
TopStackNode = * StackTop ;
2009-03-12 06:49:57 -04:00
}
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionStackCollapse() finished \n " ) ;
2009-03-08 04:40:05 -04:00
}
/* push an operator on to the expression stack */
2009-03-12 06:49:57 -04:00
void ExpressionStackPushOperator ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum OperatorOrder Order , enum LexToken Token , int Precedence )
2009-03-08 04:40:05 -04:00
{
2009-03-11 22:21:12 -04:00
struct ExpressionStack * StackNode = VariableAlloc ( Parser , sizeof ( struct ExpressionStack ) , FALSE ) ;
StackNode - > Next = * StackTop ;
StackNode - > Order = Order ;
2009-04-13 02:57:32 -04:00
StackNode - > p . Op = Token ;
2009-03-11 22:21:12 -04:00
StackNode - > Precedence = Precedence ;
* StackTop = StackNode ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionStackPushOperator() \n " ) ;
# ifdef DEBUG_EXPRESSIONS
ExpressionStackShow ( * StackTop ) ;
# endif
2009-03-08 04:40:05 -04:00
}
2009-04-13 23:18:40 -04:00
/* do the '.' and '->' operators */
void ExpressionGetStructElement ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum LexToken Token )
{
struct Value * Ident ;
/* get the identifier following the '.' or '->' */
if ( LexGetToken ( Parser , & Ident , TRUE ) ! = TokenIdentifier )
ProgramFail ( Parser , " need an structure or union member after '%s' " , ( Token = = TokenDot ) ? " . " : " -> " ) ;
if ( Parser - > Mode = = RunModeRun )
2009-04-14 02:55:00 -04:00
{
/* look up the struct element */
2009-04-13 23:18:40 -04:00
struct Value * StructVal = ( * StackTop ) - > p . Val ;
struct Value * MemberValue ;
struct Value * Result ;
if ( Token = = TokenArrow )
ProgramFail ( Parser , " '->' not implemented yet " ) ;
if ( StructVal - > Typ - > Base ! = TypeStruct & & StructVal - > Typ - > Base ! = TypeUnion )
ProgramFail ( Parser , " can't use '%s' on something that's not a struct or union %s " , ( Token = = TokenDot ) ? " . " : " -> " , ( Token = = TokenArrow ) ? " pointer " : " " ) ;
if ( ! TableGet ( StructVal - > Typ - > Members , Ident - > Val - > Identifier , & MemberValue ) )
ProgramFail ( Parser , " doesn't have a member called '%s' " , Ident - > Val - > Identifier ) ;
/* pop the value - assume it'll still be there until we're done */
HeapPopStack ( StructVal , sizeof ( struct ExpressionStack ) + sizeof ( struct Value ) + TypeStackSizeValue ( StructVal ) ) ;
* StackTop = ( * StackTop ) - > Next ;
/* make the result value for this member only */
Result = VariableAllocValueFromExistingData ( Parser , MemberValue - > Typ , ( void * ) StructVal - > Val + MemberValue - > Val - > Integer , TRUE , StructVal - > LValueFrom ) ;
ExpressionStackPushValueNode ( Parser , StackTop , Result ) ;
}
}
2009-03-08 03:56:28 -04:00
/* parse an expression with operator precedence */
int ExpressionParse ( struct ParseState * Parser , struct Value * * Result )
{
struct Value * LexValue ;
2009-03-29 07:08:03 -04:00
int PrefixState = TRUE ;
2009-03-28 07:10:34 -04:00
int Done = FALSE ;
2009-03-08 03:56:28 -04:00
int BracketPrecedence = 0 ;
2009-03-11 22:21:12 -04:00
int LocalPrecedence ;
2009-03-08 03:56:28 -04:00
int Precedence = 0 ;
2009-03-08 04:40:05 -04:00
struct ExpressionStack * StackTop = NULL ;
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionParse(): \n " ) ;
2009-03-08 03:56:28 -04:00
do
{
2009-03-30 07:16:40 -04:00
struct ParseState PreState = * Parser ;
2009-03-08 03:56:28 -04:00
enum LexToken Token = LexGetToken ( Parser , & LexValue , TRUE ) ;
2009-04-13 02:57:32 -04:00
if ( ( int ) Token > TokenComma & & ( int ) Token < = ( int ) TokenCloseBracket )
2009-04-14 02:55:00 -04:00
{
/* it's an operator with precedence */
2009-03-08 03:56:28 -04:00
if ( PrefixState )
2009-04-14 02:55:00 -04:00
{
/* expect a prefix operator */
2009-03-08 03:56:28 -04:00
if ( OperatorPrecedence [ ( int ) Token ] . PrefixPrecedence = = 0 )
ProgramFail ( Parser , " operator not expected here " ) ;
2009-04-13 05:02:45 -04:00
LocalPrecedence = OperatorPrecedence [ ( int ) Token ] . PrefixPrecedence ;
Precedence = BracketPrecedence + LocalPrecedence ;
2009-04-14 02:55:00 -04:00
if ( Token = = TokenOpenBracket )
{
/* boost the bracket operator precedence, then push */
2009-04-13 05:02:45 -04:00
BracketPrecedence + = BRACKET_PRECEDENCE ;
2009-04-14 02:55:00 -04:00
// XXX ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
2009-04-13 05:02:45 -04:00
}
else
2009-04-14 02:55:00 -04:00
{
/* scan and collapse the stack to the precedence of this operator, then push */
2009-04-13 05:02:45 -04:00
ExpressionStackCollapse ( Parser , & StackTop , Precedence ) ;
ExpressionStackPushOperator ( Parser , & StackTop , OrderPrefix , Token , Precedence ) ;
2009-03-08 03:56:28 -04:00
}
}
else
2009-04-14 02:55:00 -04:00
{
/* expect an infix or postfix operator */
2009-03-08 03:56:28 -04:00
if ( OperatorPrecedence [ ( int ) Token ] . PostfixPrecedence ! = 0 )
{
switch ( Token )
{
case TokenCloseBracket :
2009-04-14 02:55:00 -04:00
case TokenRightSquareBracket :
2009-03-08 03:56:28 -04:00
if ( BracketPrecedence = = 0 )
2009-04-14 02:55:00 -04:00
{
/* assume this bracket is after the end of the expression */
2009-04-13 02:57:32 -04:00
* Parser = PreState ;
2009-03-28 07:10:34 -04:00
Done = TRUE ;
2009-03-08 03:56:28 -04:00
}
else
BracketPrecedence - = BRACKET_PRECEDENCE ;
break ;
default :
2009-03-08 04:40:05 -04:00
/* scan and collapse the stack to the precedence of this operator, then push */
Precedence = BracketPrecedence + OperatorPrecedence [ ( int ) Token ] . PostfixPrecedence ;
ExpressionStackCollapse ( Parser , & StackTop , Precedence ) ;
ExpressionStackPushOperator ( Parser , & StackTop , OrderPostfix , Token , Precedence ) ;
2009-03-08 03:56:28 -04:00
break ;
}
}
else if ( OperatorPrecedence [ ( int ) Token ] . InfixPrecedence ! = 0 )
2009-04-14 02:55:00 -04:00
{
/* scan and collapse the stack, then push */
2009-04-13 23:18:40 -04:00
if ( Token = = TokenDot | | Token = = TokenArrow )
ExpressionGetStructElement ( Parser , & StackTop , Token ) ; /* this operator is followed by a struct element so handle it as a special case */
2009-03-12 06:49:57 -04:00
else
2009-04-14 02:55:00 -04:00
{
/* a standard infix operator */
2009-04-13 23:18:40 -04:00
Precedence = BracketPrecedence + OperatorPrecedence [ ( int ) Token ] . InfixPrecedence ;
/* for right to left order, only go down to the next higher precedence so we evaluate it in reverse order */
/* for left to right order, collapse down to this precedence so we evaluate it in forward order */
if ( IS_LEFT_TO_RIGHT ( OperatorPrecedence [ ( int ) Token ] . InfixPrecedence ) )
ExpressionStackCollapse ( Parser , & StackTop , Precedence ) ;
else
ExpressionStackCollapse ( Parser , & StackTop , Precedence + 1 ) ;
2009-03-12 06:49:57 -04:00
2009-04-13 23:18:40 -04:00
ExpressionStackPushOperator ( Parser , & StackTop , OrderInfix , Token , Precedence ) ;
PrefixState = TRUE ;
}
2009-04-14 02:55:00 -04:00
/* treat an open square bracket as an infix array index operator followed by an open bracket */
if ( Token = = TokenLeftSquareBracket )
{
/* boost the bracket operator precedence, then push */
BracketPrecedence + = BRACKET_PRECEDENCE ;
// XXX ExpressionStackPushOperator(Parser, &StackTop, OrderPrefix, Token, Precedence);
}
2009-03-08 03:56:28 -04:00
}
else
ProgramFail ( Parser , " operator not expected here " ) ;
}
}
2009-04-04 22:24:00 -04:00
else if ( Token = = TokenIdentifier )
2009-04-14 02:55:00 -04:00
{
/* it's a variable, function or a macro */
2009-04-04 22:24:00 -04:00
if ( LexGetToken ( Parser , NULL , FALSE ) = = TokenOpenBracket )
ExpressionParseFunctionCall ( Parser , & StackTop , LexValue - > Val - > Identifier ) ;
else
{
if ( Parser - > Mode = = RunModeRun )
{
struct Value * VariableValue = NULL ;
VariableGet ( Parser , LexValue - > Val - > Identifier , & VariableValue ) ;
if ( VariableValue - > Typ - > Base = = TypeMacro )
{
ProgramFail ( Parser , " XXX macros unimplemented " ) ;
#if 0
struct ParseState MacroParser = VariableValue - > Val - > Parser ;
if ( ! ExpressionParse ( & MacroParser , Result ) | | LexGetToken ( & MacroParser , NULL , FALSE ) ! = TokenEndOfFunction )
ProgramFail ( & MacroParser , " expression expected " ) ;
# endif
}
else if ( VariableValue - > Typ = = TypeVoid )
ProgramFail ( Parser , " a void value isn't much use here " ) ;
else
2009-04-14 02:55:00 -04:00
ExpressionStackPushLValue ( Parser , & StackTop , VariableValue ) ; /* it's a value variable */
2009-04-04 22:24:00 -04:00
}
else /* push a dummy value */
2009-04-13 05:02:45 -04:00
ExpressionPushInt ( Parser , & StackTop , 0 ) ;
2009-04-13 02:57:32 -04:00
PrefixState = FALSE ;
2009-04-04 22:24:00 -04:00
}
}
2009-04-13 02:57:32 -04:00
else if ( ( int ) Token > TokenComma & & ( int ) Token < = ( int ) TokenCharacterConstant )
2009-04-14 02:55:00 -04:00
{
/* it's a value of some sort, push it */
2009-03-08 03:56:28 -04:00
if ( ! PrefixState )
ProgramFail ( Parser , " value not expected here " ) ;
2009-03-28 07:10:34 -04:00
PrefixState = FALSE ;
2009-03-08 04:40:05 -04:00
ExpressionStackPushValue ( Parser , & StackTop , LexValue ) ;
2009-03-08 03:56:28 -04:00
}
else
2009-04-14 02:55:00 -04:00
{
/* it isn't a token from an expression */
2009-03-30 07:16:40 -04:00
* Parser = PreState ;
2009-03-28 07:10:34 -04:00
Done = TRUE ;
2009-03-08 03:56:28 -04:00
}
} while ( ! Done ) ;
2009-03-08 04:40:05 -04:00
/* scan and collapse the stack to precedence 0 */
ExpressionStackCollapse ( Parser , & StackTop , 0 ) ;
2009-03-29 07:08:03 -04:00
/* fix up the stack and return the result if we're in run mode */
if ( StackTop ! = NULL )
{
/* all that should be left is a single value on the stack */
2009-03-30 07:16:40 -04:00
if ( Parser - > Mode = = RunModeRun )
2009-04-13 02:57:32 -04:00
* Result = StackTop - > p . Val ;
2009-03-30 07:16:40 -04:00
HeapPopStack ( StackTop , sizeof ( struct ExpressionStack ) ) ;
2009-03-29 07:08:03 -04:00
}
2009-03-28 07:10:34 -04:00
2009-04-13 02:57:32 -04:00
debugf ( " ExpressionParse() done \n " ) ;
2009-04-13 05:02:45 -04:00
return StackTop ! = NULL ;
2009-03-08 03:56:28 -04:00
}
/* do a function call */
2009-04-04 22:24:00 -04:00
void ExpressionParseFunctionCall ( struct ParseState * Parser , struct ExpressionStack * * StackTop , const char * FuncName )
2009-03-08 03:56:28 -04:00
{
2009-04-04 22:24:00 -04:00
struct Value * ReturnValue ;
2009-03-08 03:56:28 -04:00
struct Value * FuncValue ;
struct Value * Param ;
2009-04-03 23:11:12 -04:00
struct Value * * ParamArray = NULL ;
2009-03-08 03:56:28 -04:00
int ArgCount ;
enum LexToken Token = LexGetToken ( Parser , NULL , TRUE ) ; /* open bracket */
if ( Parser - > Mode = = RunModeRun )
2009-04-14 02:55:00 -04:00
{
/* get the function definition */
2009-03-08 03:56:28 -04:00
VariableGet ( Parser , FuncName , & FuncValue ) ;
if ( FuncValue - > Typ - > Base ! = TypeFunction )
ProgramFail ( Parser , " not a function - can't call " ) ;
2009-04-04 22:24:00 -04:00
ExpressionStackPushValueByType ( Parser , StackTop , FuncValue - > Val - > FuncDef . ReturnType ) ;
2009-04-13 02:57:32 -04:00
ReturnValue = ( * StackTop ) - > p . Val ;
2009-03-08 03:56:28 -04:00
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
2009-04-14 02:55:00 -04:00
{
/* end of argument list? */
2009-03-08 03:56:28 -04:00
Token = LexGetToken ( Parser , NULL , TRUE ) ;
if ( ! TokenCloseBracket )
ProgramFail ( Parser , " bad argument " ) ;
}
} while ( Token ! = TokenCloseBracket ) ;
if ( Parser - > Mode = = RunModeRun )
2009-04-14 02:55:00 -04:00
{
/* run the function */
2009-03-08 03:56:28 -04:00
if ( ArgCount < FuncValue - > Val - > FuncDef . NumParams )
ProgramFail ( Parser , " not enough arguments to '%s' " , FuncName ) ;
if ( FuncValue - > Val - > FuncDef . Intrinsic = = NULL )
2009-04-14 02:55:00 -04:00
{
/* run a user-defined function */
2009-03-08 03:56:28 -04:00
struct ParseState FuncParser = FuncValue - > Val - > FuncDef . Body ;
int Count ;
VariableStackFrameAdd ( Parser , FuncValue - > Val - > FuncDef . Intrinsic ? FuncValue - > Val - > FuncDef . NumParams : 0 ) ;
TopStackFrame - > NumParams = ArgCount ;
2009-04-04 22:24:00 -04:00
TopStackFrame - > ReturnValue = ReturnValue ;
2009-03-08 03:56:28 -04:00
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 " ) ;
2009-04-04 22:24:00 -04:00
if ( FuncValue - > Val - > FuncDef . ReturnType ! = ReturnValue - > Typ )
2009-03-08 03:56:28 -04:00
ProgramFail ( & FuncParser , " bad type of return value " ) ;
VariableStackFramePop ( Parser ) ;
}
else
2009-04-04 22:24:00 -04:00
FuncValue - > Val - > FuncDef . Intrinsic ( Parser , ReturnValue , ParamArray , ArgCount ) ;
2009-03-08 03:56:28 -04:00
HeapPopStackFrame ( ) ;
}
}
2009-04-04 22:24:00 -04:00
# 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 ;
}