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-08 03:56:28 -04:00
/* 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 ;
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 )
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
2009-03-11 22:21:12 -04:00
enum OperatorOrder
{
OrderPrefix ,
OrderInfix ,
OrderPostfix
} ;
/* a stack of expressions we use in evaluation */
struct ExpressionStack
{
struct ExprStack * Next ; /* the next lower item on the stack */
struct Value * Val ; /* the value for this stack node */
enum EvaluationOrder Order ; /* the evaluation order of this operator */
enum LexToken Op ; /* the operator */
short Precedence ; /* the operator precedence of this node */
short LeftToRight ; /* indicates left to right evaluation, otherwise right to left */
} ;
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 ;
} ;
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 }
} ;
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 )
{
}
/* push an operator on to the expression stack */
2009-03-11 22:21:12 -04:00
void ExpressionStackPushOperator ( struct ParseState * Parser , struct ExpressionStack * * StackTop , enum OperatorOrder Order , enum LexToken Token , int Precedence , int LeftToRight )
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 ;
StackNode - > Op = Token ;
StackNode - > Precedence = Precedence ;
StackNode - > LeftToRight = LeftToRight ;
* StackTop = StackNode ;
2009-03-08 04:40:05 -04:00
}
/* push a value on to the expression stack */
void ExpressionStackPushValue ( struct ParseState * Parser , struct ExpressionStack * * StackTop , struct Value * PushValue )
{
2009-03-11 22:21:12 -04:00
struct Value * ValueLoc = VariableAllocValueAndCopy ( Parser , PushValue , FALSE ) ;
struct ExpressionStack * StackNode = VariableAlloc ( Parser , sizeof ( struct ExpressionStack ) , FALSE ) ;
StackNode - > Next = * StackTop ;
StackNode - > Val = ValueLoc ;
* StackTop = StackNode ;
2009-03-08 04:40:05 -04:00
}
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 ;
bool PrefixState = false ;
bool Done = false ;
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-03-08 03:56:28 -04:00
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 )
{
2009-03-11 22:21:12 -04:00
LocalPrecedence = OperatorPrecedence [ ( int ) Token ] . PrefixPrecedence ;
Precedence = BracketPrecedence + LocalPrecedence ;
2009-03-08 03:56:28 -04:00
if ( Token = = TokenOpenBracket | | Token = = TokenLeftSquareBracket )
2009-03-08 04:40:05 -04:00
{ /* boost the bracket operator precedence, then push */
2009-03-08 03:56:28 -04:00
BracketPrecedence + = BRACKET_PREDECENCE ;
2009-03-11 22:21:12 -04:00
ExpressionStackPushOperator ( Parser , & StackTop , OrderPrefix , Token , Precedence , IS_LEFT_TO_RIGHT ( LocalPrecedence ) ) ;
2009-03-08 03:56:28 -04:00
}
else
2009-03-08 04:40:05 -04:00
{ /* scan and collapse the stack to the precedence of this operator, then push */
ExpressionStackCollapse ( Parser , & StackTop , Precedence ) ;
ExpressionStackPushOperator ( Parser , & StackTop , OrderPrefix , Token , Precedence ) ;
2009-03-08 03:56:28 -04:00
}
}
}
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 */
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 */
2009-03-08 04:40:05 -04:00
ExpressionStackCollapse ( Parser , & StackTop , BracketPrecedence ) ;
2009-03-08 03:56:28 -04:00
BracketPrecedence - = BRACKET_PRECEDENCE ;
/* apply the array index operator */
2009-03-08 04:40:05 -04:00
// XXX
2009-03-08 03:56:28 -04:00
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-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 ] . InfixPrecedence ;
ExpressionStackCollapse ( Parser , & StackTop , Precedence ) ;
ExpressionStackPushOperator ( Parser , & StackTop , OrderInfix , Token , Precedence ) ;
2009-03-08 03:56:28 -04:00
PrefixState = true ;
}
else
ProgramFail ( Parser , " operator not expected here " ) ;
}
}
else if ( ( int ) Token < = ( int ) TokenCharacterConstant )
2009-03-08 04:40:05 -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 " ) ;
PrefixState = false ;
2009-03-08 04:40:05 -04:00
ExpressionStackPushValue ( Parser , & StackTop , LexValue ) ;
2009-03-08 03:56:28 -04:00
}
else
{ /* it isn't a token from an expression */
Done = true ;
}
} while ( ! Done ) ;
2009-03-08 04:40:05 -04:00
/* scan and collapse the stack to precedence 0 */
ExpressionStackCollapse ( Parser , & StackTop , 0 ) ;
2009-03-08 20:07:44 -04:00
//XXX - fix up the stack and return the result if we're in run mode
2009-03-08 03:56:28 -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 ;
}
/* 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 ( ) ;
}
}