2008-10-12 20:53:28 -04:00
# include "picoc.h"
2008-12-18 19:22:52 -05:00
/* local prototypes */
2009-02-01 06:31:18 -05:00
int ParseArguments ( struct ParseState * Parser , int RunIt ) ;
2009-02-18 03:19:06 -05:00
int ParseStatementMaybeRun ( struct ParseState * Parser , int Condition ) ;
2009-03-03 05:53:45 -05:00
void ParseFunctionCall ( struct ParseState * Parser , struct Value * * Result , const char * FuncName ) ;
2008-10-14 00:51:34 -04:00
2009-03-03 05:53:45 -05:00
# if 1
2008-12-18 19:22:52 -05:00
/* parse a single value */
2009-02-19 18:29:35 -05:00
int ParseValue ( struct ParseState * Parser , struct Value * * Result )
2008-10-16 03:04:23 -04:00
{
2009-02-01 06:31:18 -05:00
struct ParseState PreState = * Parser ;
2009-01-26 03:57:32 -05:00
struct Value * LexValue ;
int IntValue ;
2009-02-01 06:31:18 -05:00
enum LexToken Token = LexGetToken ( Parser , & LexValue , TRUE ) ;
2009-02-03 19:17:30 -05:00
struct Value * LocalLValue = NULL ;
2009-02-11 01:42:30 -05:00
struct ValueType * VType ;
2009-02-03 19:17:30 -05:00
int Success = TRUE ;
2008-10-16 03:04:23 -04:00
2008-11-21 21:56:08 -05:00
switch ( Token )
{
2009-01-26 03:57:32 -05:00
case TokenIntegerConstant : case TokenCharacterConstant : case TokenFPConstant : case TokenStringConstant :
2009-02-19 18:29:35 -05:00
* Result = VariableAllocValueAndCopy ( Parser , LexValue , FALSE ) ;
2009-01-26 03:57:32 -05:00
break ;
2008-11-21 21:56:08 -05:00
case TokenMinus : case TokenUnaryExor : case TokenUnaryNot :
2009-02-18 03:19:06 -05:00
IntValue = ParseIntExpression ( Parser ) ;
if ( Parser - > Mode = = RunModeRun )
2008-11-21 21:56:08 -05:00
{
2009-02-26 04:56:22 -05:00
* Result = VariableAllocValueFromType ( Parser , & IntType , FALSE , NULL ) ;
2008-12-20 22:46:32 -05:00
switch ( Token )
{
2009-01-26 03:57:32 -05:00
case TokenMinus : ( * Result ) - > Val - > Integer = - IntValue ; break ;
case TokenUnaryExor : ( * Result ) - > Val - > Integer = ~ IntValue ; break ;
case TokenUnaryNot : ( * Result ) - > Val - > Integer = ! IntValue ; break ;
2008-12-20 22:46:32 -05:00
default : break ;
}
2008-11-21 21:56:08 -05:00
}
break ;
case TokenOpenBracket :
2009-02-19 18:29:35 -05:00
if ( ! ParseExpression ( Parser , Result ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " invalid expression " ) ;
2008-11-21 21:56:08 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenCloseBracket )
ProgramFail ( Parser , " ')' expected " ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenAsterisk :
2009-02-19 18:29:35 -05:00
if ( ! ParseExpression ( Parser , Result ) )
2009-02-11 01:42:30 -05:00
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 ) ;
2009-03-03 05:53:45 -05:00
#if 0
2009-02-26 05:44:06 -05:00
* 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 ) ;
2009-03-03 05:53:45 -05:00
# endif
2009-02-19 18:29:35 -05:00
* Result = VariableAllocValueShared ( Parser , LocalLValue ) ;
2009-02-11 01:42:30 -05:00
break ;
2008-11-21 21:56:08 -05:00
2009-02-10 06:19:48 -05:00
case TokenAmpersand :
2009-02-19 18:29:35 -05:00
if ( ! ParseValue ( Parser , Result ) | | ! ( * Result ) - > IsLValue )
2009-02-10 06:19:48 -05:00
ProgramFail ( Parser , " can't get the address of this " ) ;
2009-02-11 01:42:30 -05:00
VType = ( * Result ) - > Typ ;
2009-02-26 05:16:49 -05:00
LocalLValue = ( * Result ) - > LValueFrom ;
2009-02-10 06:19:48 -05:00
VariableStackPop ( Parser , * Result ) ;
2009-02-26 04:56:22 -05:00
* Result = VariableAllocValueFromType ( Parser , TypeGetMatching ( Parser , VType , TypePointer , 0 , StrEmpty ) , FALSE , NULL ) ;
2009-02-10 06:19:48 -05:00
( * Result ) - > Val - > Pointer . Segment = LocalLValue ;
2009-02-26 05:44:06 -05:00
( * Result ) - > Val - > Pointer . Data . Offset = ( void * ) ( * Result ) - > Val - ( void * ) ( * Result ) - > LValueFrom ;
2009-02-10 06:19:48 -05:00
break ;
2008-11-21 21:56:08 -05:00
case TokenIdentifier :
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , FALSE ) = = TokenOpenBracket )
2009-02-20 21:35:52 -05:00
ParseFunctionCall ( Parser , Result , LexValue - > Val - > Identifier ) ;
2008-12-23 21:30:29 -05:00
else
{
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-01-03 23:08:49 -05:00
{
2009-02-20 21:35:52 -05:00
VariableGet ( Parser , LexValue - > Val - > Identifier , & LocalLValue ) ;
2009-02-03 19:17:30 -05:00
if ( LocalLValue - > Typ - > Base = = TypeMacro )
2009-01-04 23:28:54 -05:00
{
2009-03-06 02:27:45 -05:00
struct ParseState MacroParser = LocalLValue - > Val - > Parser ;
2009-01-04 23:28:54 -05:00
2009-03-06 02:27:45 -05:00
if ( ! ParseExpression ( & MacroParser , Result ) | | LexGetToken ( & MacroParser , NULL , FALSE ) ! = TokenEOF )
ProgramFail ( & MacroParser , " expression expected " ) ;
2009-01-04 23:28:54 -05:00
}
2009-02-10 03:42:09 -05:00
else if ( LocalLValue - > Typ = = TypeVoid )
ProgramFail ( Parser , " a void value isn't much use here " ) ;
2009-02-03 19:17:30 -05:00
else
2009-02-12 07:15:25 -05:00
{ /* it's a value variable */
2009-02-19 18:29:35 -05:00
* Result = VariableAllocValueShared ( Parser , LocalLValue ) ;
2009-02-12 07:15:25 -05:00
}
}
/* 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 ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-02-12 07:15:25 -05:00
{
2009-02-15 00:52:03 -05:00
if ( ! ( * Result ) - > IsLValue | | ( * Result ) - > Typ - > Base ! = TypeInt )
2009-02-12 07:15:25 -05:00
ProgramFail ( Parser , " can't %s this " , ( Token = = TokenIncrement ) ? " increment " : " decrement " ) ;
if ( Token = = TokenIncrement )
2009-02-15 00:52:03 -05:00
( * Result ) - > Val - > Integer + + ;
2009-02-12 07:15:25 -05:00
else
2009-02-15 00:52:03 -05:00
( * Result ) - > Val - > Integer - - ;
2009-02-12 07:15:25 -05:00
}
2009-01-03 23:08:49 -05:00
}
2009-02-15 01:46:37 -05:00
else if ( Token = = TokenLeftSquareBracket )
{ /* array access */
LexGetToken ( Parser , & LexValue , TRUE ) ;
2009-02-18 03:19:06 -05:00
IntValue = ParseIntExpression ( Parser ) ;
2009-02-15 01:46:37 -05:00
if ( LexGetToken ( Parser , & LexValue , TRUE ) ! = TokenRightSquareBracket )
ProgramFail ( Parser , " expected ']' " ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-02-15 01:46:37 -05:00
{ /* look up the array element */
if ( ( * Result ) - > Typ - > Base ! = TypeArray )
ProgramFail ( Parser , " not an array " ) ;
2009-02-20 21:35:52 -05:00
if ( IntValue < 0 | | IntValue > = ( * Result ) - > Val - > Array . Size )
2009-02-15 01:46:37 -05:00
ProgramFail ( Parser , " illegal array index " ) ;
VariableStackPop ( Parser , * Result ) ;
2009-02-26 04:56:22 -05:00
* Result = VariableAllocValueFromExistingData ( Parser , ( * Result ) - > Typ - > FromType , ( union AnyValue * ) ( ( * Result ) - > Val - > Array . Data + TypeSize ( ( * Result ) - > Typ - > FromType , 0 ) * IntValue ) , ( * Result ) - > IsLValue , ( * Result ) - > LValueFrom ) ;
2009-02-15 01:46:37 -05:00
}
}
2008-12-23 21:30:29 -05:00
}
2008-11-21 21:56:08 -05:00
break ;
default :
2009-02-01 06:31:18 -05:00
* Parser = PreState ;
2009-02-03 19:17:30 -05:00
Success = FALSE ;
break ;
2008-11-21 21:56:08 -05:00
}
2008-10-16 03:04:23 -04:00
2009-02-03 19:17:30 -05:00
return Success ;
2008-11-21 21:56:08 -05:00
}
2009-02-23 19:21:17 -05:00
# ifndef NO_FP
2009-02-19 18:29:35 -05:00
struct Value * ParsePushFP ( struct ParseState * Parser , double NewFP )
2009-01-26 03:57:32 -05:00
{
2009-02-26 04:56:22 -05:00
struct Value * Val = VariableAllocValueFromType ( Parser , & FPType , FALSE , NULL ) ;
2009-01-26 03:57:32 -05:00
Val - > Val - > FP = NewFP ;
return Val ;
}
2009-02-23 19:21:17 -05:00
# endif
2009-01-26 03:57:32 -05:00
2009-02-19 18:29:35 -05:00
struct Value * ParsePushInt ( struct ParseState * Parser , int NewInt )
2009-01-26 03:57:32 -05:00
{
2009-02-26 04:56:22 -05:00
struct Value * Val = VariableAllocValueFromType ( Parser , & IntType , FALSE , NULL ) ;
2009-01-26 03:57:32 -05:00
Val - > Val - > Integer = NewInt ;
return Val ;
}
2008-12-18 19:22:52 -05:00
/* parse an expression. operator precedence is not supported */
2009-02-19 18:29:35 -05:00
int ParseExpression ( struct ParseState * Parser , struct Value * * Result )
2008-11-21 21:56:08 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * CurrentValue ;
struct Value * TotalValue ;
2008-11-21 21:56:08 -05:00
2009-02-19 18:29:35 -05:00
if ( ! ParseValue ( Parser , & TotalValue ) )
2008-11-21 21:56:08 -05:00
return FALSE ;
while ( TRUE )
2008-10-16 03:04:23 -04:00
{
2009-02-01 06:31:18 -05:00
enum LexToken Token = LexGetToken ( Parser , NULL , FALSE ) ;
2008-11-21 21:56:08 -05:00
switch ( Token )
{
case TokenPlus : case TokenMinus : case TokenAsterisk : case TokenSlash :
2009-03-03 05:53:45 -05:00
case TokenEqual : case TokenLessThan : case TokenGreaterThan :
2008-11-21 21:56:08 -05:00
case TokenLessEqual : case TokenGreaterEqual : case TokenLogicalAnd :
2008-12-20 05:24:34 -05:00
case TokenLogicalOr : case TokenAmpersand : case TokenArithmeticOr :
2009-02-09 06:40:56 -05:00
case TokenArithmeticExor :
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ;
2008-11-21 21:56:08 -05:00
break ;
2009-02-09 06:40:56 -05:00
case TokenDot :
{
struct Value * Ident ;
LexGetToken ( Parser , NULL , TRUE ) ;
if ( LexGetToken ( Parser , & Ident , TRUE ) ! = TokenIdentifier )
ProgramFail ( Parser , " need an structure or union member after '.' " ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-02-09 06:40:56 -05:00
{
void * TotalValueData = ( void * ) TotalValue - > Val ;
2009-02-10 03:42:09 -05:00
if ( TotalValue - > Typ - > Base ! = TypeStruct & & TotalValue - > Typ - > Base ! = TypeUnion )
2009-02-09 06:40:56 -05:00
ProgramFail ( Parser , " can't use '.' on something that's not a struct or union " ) ;
2008-12-20 05:24:34 -05:00
2009-02-20 21:35:52 -05:00
if ( ! TableGet ( TotalValue - > Typ - > Members , Ident - > Val - > Identifier , & CurrentValue ) )
ProgramFail ( Parser , " structure doesn't have a member called '%s' " , Ident - > Val - > Identifier ) ;
2009-02-09 06:40:56 -05:00
VariableStackPop ( Parser , TotalValue ) ;
2009-02-26 05:44:06 -05:00
TotalValue = VariableAllocValueFromExistingData ( Parser , CurrentValue - > Typ , TotalValueData + CurrentValue - > Val - > Integer , TRUE , TotalValue - > LValueFrom ) ;
2009-02-09 06:40:56 -05:00
}
2009-02-10 03:42:09 -05:00
continue ;
2009-02-09 06:40:56 -05:00
}
2009-02-25 06:14:46 -05:00
case TokenAssign :
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ;
2009-02-25 06:14:46 -05:00
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 ) ;
2009-02-19 18:29:35 -05:00
if ( ! ParseExpression ( Parser , & CurrentValue ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " expression expected " ) ;
2008-12-20 05:24:34 -05:00
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-02-25 06:14:46 -05:00
{ /* do the assignment */
if ( ! TotalValue - > IsLValue )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " can't assign " ) ;
2008-12-20 22:46:32 -05:00
2009-02-25 06:14:46 -05:00
if ( CurrentValue - > Typ - > Base = = TypeInt & & TotalValue - > Typ - > Base = = TypeInt )
2008-12-20 22:46:32 -05:00
{
2009-02-25 06:14:46 -05:00
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 ) ;
2008-12-20 22:46:32 -05:00
}
2009-02-25 06:14:46 -05:00
# 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 " ) ;
2008-12-20 05:24:34 -05:00
}
// fallthrough
2008-11-21 21:56:08 -05:00
default :
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2008-12-20 22:46:32 -05:00
* Result = TotalValue ;
2008-11-21 21:56:08 -05:00
return TRUE ;
}
2009-02-19 18:29:35 -05:00
if ( ! ParseValue ( Parser , & CurrentValue ) )
2008-11-21 21:56:08 -05:00
return FALSE ;
2008-12-20 05:24:34 -05:00
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2008-10-16 03:04:23 -04:00
{
2009-02-23 19:21:17 -05:00
# ifndef NO_FP
2009-01-26 03:57:32 -05:00
if ( CurrentValue - > Typ - > Base = = TypeFP | | TotalValue - > Typ - > Base = = TypeFP )
2009-02-15 01:46:37 -05:00
{ /* floating point expression */
2009-02-15 01:16:54 -05:00
double FPTotal , FPCurrent , FPResult ;
2008-12-26 21:25:49 -05:00
2009-01-26 03:57:32 -05:00
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
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad type for operator " ) ;
2009-01-26 03:57:32 -05:00
if ( TotalValue - > Typ - > Base = = TypeInt )
FPTotal = ( double ) TotalValue - > Val - > Integer ;
else if ( TotalValue - > Typ - > Base = = TypeFP )
FPTotal = TotalValue - > Val - > FP ;
else
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad type for operator " ) ;
2009-01-26 03:57:32 -05:00
}
2009-02-01 06:31:18 -05:00
VariableStackPop ( Parser , CurrentValue ) ;
VariableStackPop ( Parser , TotalValue ) ;
2009-01-26 03:57:32 -05:00
2008-12-26 21:25:49 -05:00
switch ( Token )
{
2009-02-15 01:16:54 -05:00
case TokenPlus : FPResult = FPTotal + FPCurrent ; break ;
case TokenMinus : FPResult = FPTotal - FPCurrent ; break ;
case TokenAsterisk : FPResult = FPTotal * FPCurrent ; break ;
case TokenSlash : FPResult = FPTotal / FPCurrent ; break ;
2009-03-03 05:53:45 -05:00
case TokenEqual : FPResult = FPTotal = = FPCurrent ; break ;
2009-02-15 01:16:54 -05:00
case TokenLessThan : FPResult = FPTotal < FPCurrent ; break ;
case TokenGreaterThan : FPResult = FPTotal > FPCurrent ; break ;
case TokenLessEqual : FPResult = FPTotal < = FPCurrent ; break ;
case TokenGreaterEqual : FPResult = FPTotal > = FPCurrent ; break ;
2009-02-01 06:31:18 -05:00
case TokenLogicalAnd : case TokenLogicalOr : case TokenAmpersand : case TokenArithmeticOr : case TokenArithmeticExor : ProgramFail ( Parser , " bad type for operator " ) ; break ;
2008-12-26 21:25:49 -05:00
default : break ;
}
2009-02-19 18:29:35 -05:00
TotalValue = ParsePushFP ( Parser , FPResult ) ;
2008-12-26 21:25:49 -05:00
}
else
2009-02-23 19:21:17 -05:00
# endif
2009-02-15 01:46:37 -05:00
{ /* integer expression */
2009-02-15 01:16:54 -05:00
int IntX , IntY , IntResult ;
2009-01-26 03:57:32 -05:00
if ( CurrentValue - > Typ - > Base ! = TypeInt | | TotalValue - > Typ - > Base ! = TypeInt )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad operand types " ) ;
2008-12-26 21:25:49 -05:00
2009-02-15 01:16:54 -05:00
IntX = TotalValue - > Val - > Integer ;
IntY = CurrentValue - > Val - > Integer ;
VariableStackPop ( Parser , CurrentValue ) ;
VariableStackPop ( Parser , TotalValue ) ;
2008-12-26 21:25:49 -05:00
/* integer arithmetic */
switch ( Token )
{
2009-02-15 01:16:54 -05:00
case TokenPlus : IntResult = IntX + IntY ; break ;
case TokenMinus : IntResult = IntX - IntY ; break ;
case TokenAsterisk : IntResult = IntX * IntY ; break ;
case TokenSlash : IntResult = IntX / IntY ; break ;
2009-03-03 05:53:45 -05:00
case TokenEqual : IntResult = IntX = = IntY ; break ;
2009-02-15 01:16:54 -05:00
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 ;
2008-12-26 21:25:49 -05:00
default : break ;
}
2009-02-19 18:29:35 -05:00
TotalValue = ParsePushInt ( Parser , IntResult ) ;
2008-12-20 22:46:32 -05:00
}
2009-02-15 01:16:54 -05:00
2009-01-26 03:57:32 -05:00
* Result = TotalValue ;
2008-11-21 21:56:08 -05:00
}
}
return TRUE ;
}
2009-03-03 05:53:45 -05:00
# else
/* operator precedence definitions */
struct OpPrecedence
{
2009-03-04 05:09:56 -05:00
unsigned char PrefixPrecedence : 4 ;
unsigned char PostfixPrecedence : 4 ;
unsigned char InfixPrecedence : 4 ;
2009-03-03 05:53:45 -05:00
} ;
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 } ,
2009-03-04 23:05:15 -05:00
/* TokenQuestionMark, */ { 0 , 0 , 3 } , /* TokenColon, */ { 0 , 0 , 3 } ,
2009-03-03 05:53:45 -05:00
/* 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 } ,
2009-03-04 23:05:15 -05:00
/* 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-03 05:53:45 -05:00
} ;
/* parse an expression with operator precedence */
int ParseExpression ( struct ParseState * Parser , struct Value * * Result )
{
2009-03-04 05:09:56 -05:00
struct Value * LexValue ;
bool PrefixState = false ;
bool Done = false ;
int BracketPrecedence = 0 ;
int Precedence = 0 ;
2009-03-03 05:53:45 -05:00
2009-03-04 05:09:56 -05: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-04 23:05:15 -05:00
{
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 */
}
2009-03-04 05:09:56 -05:00
}
}
else
{ /* expect an infix or postfix operator */
if ( OperatorPrecedence [ ( int ) Token ] . PostfixPrecedence ! = 0 )
{
2009-03-04 23:05:15 -05:00
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 ;
}
2009-03-04 05:09:56 -05:00
}
else if ( OperatorPrecedence [ ( int ) Token ] . InfixPrecedence ! = 0 )
{
2009-03-04 23:05:15 -05:00
/* scan and collapse the stack to the precedence of this operator */
/* push the operator */
2009-03-04 05:09:56 -05:00
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 ;
2009-03-04 23:05:15 -05:00
if ( Parser - > Mode = = RunModeRun )
{
/* push the value */
}
2009-03-04 05:09:56 -05:00
}
else
{ /* it isn't a token from an expression */
2009-03-04 23:05:15 -05:00
/* scan and collapse the stack to precedence 0 */
2009-03-04 05:09:56 -05:00
Done = true ;
}
} while ( ! Done ) ;
2009-03-03 05:53:45 -05:00
}
# endif
2008-11-21 21:56:08 -05:00
2008-12-18 19:22:52 -05:00
/* parse an expression. operator precedence is not supported */
2009-02-18 03:19:06 -05:00
int ParseIntExpression ( struct ParseState * Parser )
2008-12-18 19:22:52 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * Val ;
int Result = 0 ;
2009-02-19 18:29:35 -05:00
if ( ! ParseExpression ( Parser , & Val ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " expression expected " ) ;
2008-12-18 19:22:52 -05:00
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-01-26 03:57:32 -05:00
{
if ( Val - > Typ - > Base ! = TypeInt )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " integer value expected " ) ;
2009-01-26 03:57:32 -05:00
Result = Val - > Val - > Integer ;
2009-02-01 06:31:18 -05:00
VariableStackPop ( Parser , Val ) ;
2009-01-26 03:57:32 -05:00
}
return Result ;
2008-12-18 19:22:52 -05:00
}
2008-11-21 21:56:08 -05:00
2009-03-03 05:53:45 -05:00
/* 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 ( ) ;
}
}
2008-12-20 20:36:09 -05:00
/* parse a function definition and store it for later */
2009-02-20 21:35:52 -05:00
struct Value * ParseFunctionDefinition ( struct ParseState * Parser , struct ValueType * ReturnType , char * Identifier , int IsPrototype )
2008-12-20 06:46:21 -05:00
{
2009-02-02 06:08:36 -05:00
struct ValueType * ParamType ;
2009-02-20 21:35:52 -05:00
char * ParamIdentifier ;
2009-02-01 06:31:18 -05:00
enum LexToken Token ;
struct Value * FuncValue ;
struct ParseState ParamParser ;
2009-03-07 01:17:11 -05:00
struct ParseState FuncBody ;
2009-02-01 06:31:18 -05:00
int ParamCount = 0 ;
2008-12-20 20:36:09 -05:00
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ; /* open bracket */
ParamParser = * Parser ;
Token = LexGetToken ( Parser , NULL , TRUE ) ;
if ( Token ! = TokenCloseBracket & & Token ! = TokenEOF )
{ /* count the number of parameters */
ParamCount + + ;
while ( ( Token = LexGetToken ( Parser , NULL , TRUE ) ) ! = TokenCloseBracket & & Token ! = TokenEOF )
{
if ( Token = = TokenComma )
ParamCount + + ;
}
}
2009-02-02 06:08:36 -05:00
if ( ParamCount > PARAMETER_MAX )
ProgramFail ( Parser , " too many parameters " ) ;
2008-12-20 20:36:09 -05:00
2009-02-26 04:56:22 -05:00
FuncValue = VariableAllocValueAndData ( Parser , sizeof ( struct FuncDef ) + sizeof ( struct ValueType * ) * ParamCount + sizeof ( const char * ) * ParamCount , FALSE , NULL , TRUE ) ;
2009-01-21 04:02:05 -05:00
FuncValue - > Typ = & FunctionType ;
2009-02-01 06:31:18 -05:00
FuncValue - > Val - > FuncDef . ReturnType = ReturnType ;
FuncValue - > Val - > FuncDef . NumParams = ParamCount ;
2009-02-20 04:04:45 -05:00
FuncValue - > Val - > FuncDef . VarArgs = FALSE ;
2009-02-01 06:31:18 -05:00
FuncValue - > Val - > FuncDef . ParamType = ( void * ) FuncValue - > Val + sizeof ( struct FuncDef ) ;
FuncValue - > Val - > FuncDef . ParamName = ( void * ) FuncValue - > Val - > FuncDef . ParamType + sizeof ( struct ValueType * ) * ParamCount ;
for ( ParamCount = 0 ; ParamCount < FuncValue - > Val - > FuncDef . NumParams ; ParamCount + + )
{ /* harvest the parameters into the function definition */
2009-02-20 04:04:45 -05:00
if ( ParamCount = = FuncValue - > Val - > FuncDef . NumParams - 1 & & LexGetToken ( & ParamParser , NULL , FALSE ) = = TokenEllipsis )
{ /* ellipsis at end */
FuncValue - > Val - > FuncDef . NumParams - - ;
FuncValue - > Val - > FuncDef . VarArgs = TRUE ;
break ;
}
else
{ /* add a parameter */
TypeParse ( & ParamParser , & ParamType , & ParamIdentifier ) ;
FuncValue - > Val - > FuncDef . ParamType [ ParamCount ] = ParamType ;
FuncValue - > Val - > FuncDef . ParamName [ ParamCount ] = ParamIdentifier ;
}
2009-02-01 06:31:18 -05:00
2009-02-02 06:08:36 -05:00
Token = LexGetToken ( & ParamParser , NULL , TRUE ) ;
2009-02-20 04:04:45 -05:00
if ( Token ! = TokenComma & & ParamCount < FuncValue - > Val - > FuncDef . NumParams - 1 )
2009-02-02 06:08:36 -05:00
ProgramFail ( & ParamParser , " comma expected " ) ;
2009-02-01 06:31:18 -05:00
}
2009-02-01 22:27:05 -05:00
if ( ! IsPrototype )
{
if ( LexGetToken ( Parser , NULL , FALSE ) ! = TokenLeftBrace )
ProgramFail ( Parser , " bad function definition " ) ;
2009-03-07 01:17:11 -05:00
FuncBody = * Parser ;
2009-02-18 03:19:06 -05:00
if ( ! ParseStatementMaybeRun ( Parser , FALSE ) )
2009-02-01 22:27:05 -05:00
ProgramFail ( Parser , " function definition expected " ) ;
2009-03-07 01:17:11 -05:00
FuncValue - > Val - > FuncDef . Body = FuncBody ;
FuncValue - > Val - > FuncDef . Body . Pos = LexCopyTokens ( & FuncBody , Parser ) ;
2009-02-01 22:27:05 -05:00
}
2009-01-21 04:02:05 -05:00
if ( ! TableSet ( & GlobalTable , Identifier , FuncValue ) )
2009-02-02 06:08:36 -05:00
ProgramFail ( Parser , " '%s' is already defined " , Identifier ) ;
2009-02-01 22:27:05 -05:00
return FuncValue ;
2008-12-20 06:46:21 -05:00
}
2009-03-05 23:55:11 -05:00
/* declare a variable or function */
void ParseDeclaration ( struct ParseState * Parser , enum LexToken Token )
{
char * Identifier ;
2009-03-06 01:00:51 -05:00
struct ValueType * BasicType ;
2009-03-05 23:55:11 -05:00
struct ValueType * Typ ;
struct Value * CValue ;
2009-03-06 01:00:51 -05:00
TypeParseFront ( Parser , & BasicType ) ;
do
2009-03-05 23:55:11 -05:00
{
2009-03-06 01:00:51 -05:00
TypeParseIdentPart ( Parser , BasicType , & Typ , & Identifier ) ;
if ( Token = = TokenVoidType & & Identifier ! = StrEmpty )
ProgramFail ( Parser , " can't define a void variable " ) ;
if ( ( Token ! = TokenVoidType & & Token ! = TokenStructType & & Token ! = TokenUnionType ) & & Identifier = = StrEmpty )
ProgramFail ( Parser , " identifier expected " ) ;
if ( Identifier ! = StrEmpty )
2009-03-05 23:55:11 -05:00
{
2009-03-06 01:00:51 -05:00
/* handle function definitions */
if ( LexGetToken ( Parser , NULL , FALSE ) = = TokenOpenBracket )
ParseFunctionDefinition ( Parser , Typ , Identifier , FALSE ) ;
2009-03-05 23:55:11 -05:00
else
2009-03-06 01:00:51 -05:00
{
if ( LexGetToken ( Parser , NULL , FALSE ) ! = TokenAssign )
VariableDefine ( Parser , Identifier , VariableAllocValueFromType ( Parser , Typ , TRUE , NULL ) ) ;
else
{ /* we're assigning an initial value */
LexGetToken ( Parser , NULL , TRUE ) ;
if ( ! ParseExpression ( Parser , & CValue ) )
ProgramFail ( Parser , " expression expected " ) ;
VariableDefine ( Parser , Identifier , CValue ) ;
if ( Parser - > Mode = = RunModeRun )
VariableStackPop ( Parser , CValue ) ;
}
2009-03-05 23:55:11 -05:00
}
}
2009-03-06 01:00:51 -05:00
Token = LexGetToken ( Parser , NULL , FALSE ) ;
if ( Token = = TokenComma )
LexGetToken ( Parser , NULL , TRUE ) ;
} while ( Token = = TokenComma ) ;
2009-03-05 23:55:11 -05:00
}
2009-01-04 23:28:54 -05:00
/* parse a #define macro definition and store it for later */
2009-02-01 06:31:18 -05:00
void ParseMacroDefinition ( struct ParseState * Parser )
2009-01-04 23:28:54 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * MacroName ;
2009-02-26 04:56:22 -05:00
struct Value * MacroValue = VariableAllocValueAndData ( Parser , sizeof ( struct ParseState ) , FALSE , NULL , TRUE ) ;
2009-01-04 23:28:54 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , & MacroName , TRUE ) ! = TokenIdentifier )
ProgramFail ( Parser , " identifier expected " ) ;
2009-01-04 23:28:54 -05:00
2009-02-01 06:31:18 -05:00
MacroValue - > Val - > Parser = * Parser ;
2009-01-21 04:02:05 -05:00
MacroValue - > Typ = & MacroType ;
2009-03-07 01:17:11 -05:00
LexToEndOfLine ( Parser ) ;
MacroValue - > Val - > Parser . Pos = LexCopyTokens ( & MacroValue - > Val - > Parser , Parser ) ;
2009-01-04 23:28:54 -05:00
2009-02-20 21:35:52 -05:00
if ( ! TableSet ( & GlobalTable , MacroName - > Val - > Identifier , MacroValue ) )
ProgramFail ( Parser , " '%s' is already defined " , & MacroName - > Val - > Identifier ) ;
2009-01-04 23:28:54 -05:00
}
2009-02-19 04:07:00 -05:00
/* copy where we're at in the parsing */
void ParserCopyPos ( struct ParseState * To , struct ParseState * From )
{
To - > Pos = From - > Pos ;
To - > Line = From - > Line ;
}
2009-02-12 07:15:25 -05:00
/* parse a "for" statement */
2009-02-18 03:19:06 -05:00
void ParseFor ( struct ParseState * Parser )
2009-01-03 23:08:49 -05:00
{
2009-01-26 03:57:32 -05:00
int Condition ;
2009-02-01 06:31:18 -05:00
struct ParseState PreConditional ;
struct ParseState PreIncrement ;
struct ParseState PreStatement ;
struct ParseState After ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenOpenBracket )
ProgramFail ( Parser , " '(' expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-18 03:19:06 -05:00
if ( ! ParseStatement ( Parser ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " statement expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-12 07:15:25 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenSemicolon )
ProgramFail ( Parser , " ';' expected " ) ;
2009-02-19 04:07:00 -05:00
ParserCopyPos ( & PreConditional , Parser ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenSemicolon )
ProgramFail ( Parser , " ';' expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-19 04:07:00 -05:00
ParserCopyPos ( & PreIncrement , Parser ) ;
2009-02-18 03:19:06 -05:00
ParseStatementMaybeRun ( Parser , FALSE ) ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenCloseBracket )
ProgramFail ( Parser , " ')' expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-19 04:07:00 -05:00
ParserCopyPos ( & PreStatement , Parser ) ;
2009-02-18 03:19:06 -05:00
if ( ! ParseStatementMaybeRun ( Parser , Condition ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " statement expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeContinue )
Parser - > Mode = RunModeRun ;
ParserCopyPos ( & After , Parser ) ;
2009-02-18 03:19:06 -05:00
while ( Condition & & Parser - > Mode = = RunModeRun )
2009-01-03 23:08:49 -05:00
{
2009-02-19 04:07:00 -05:00
ParserCopyPos ( Parser , & PreIncrement ) ;
2009-02-18 03:19:06 -05:00
ParseStatement ( Parser ) ;
2009-01-03 23:08:49 -05:00
2009-02-19 04:07:00 -05:00
ParserCopyPos ( Parser , & PreConditional ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2009-01-03 23:08:49 -05:00
2009-01-26 03:57:32 -05:00
if ( Condition )
2009-01-03 23:08:49 -05:00
{
2009-02-19 04:07:00 -05:00
ParserCopyPos ( Parser , & PreStatement ) ;
2009-02-18 03:19:06 -05:00
ParseStatement ( Parser ) ;
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeContinue )
Parser - > Mode = RunModeRun ;
2009-01-03 23:08:49 -05:00
}
}
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeBreak )
Parser - > Mode = RunModeRun ;
ParserCopyPos ( Parser , & After ) ;
2009-01-03 23:08:49 -05:00
}
2009-02-18 03:19:06 -05:00
/* 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 ) ;
}
2009-02-19 04:07:00 -05:00
/* parse a block of code and return what mode it returned in */
enum RunMode ParseBlock ( struct ParseState * Parser , int AbsorbOpenBrace , int Condition )
{
if ( AbsorbOpenBrace & & LexGetToken ( Parser , NULL , TRUE ) ! = TokenLeftBrace )
ProgramFail ( Parser , " '{' expected " ) ;
if ( Parser - > Mode ! = RunModeSkip & & ! Condition )
{ /* condition failed - skip this block instead */
enum RunMode OldMode = Parser - > Mode ;
Parser - > Mode = RunModeSkip ;
while ( ParseStatement ( Parser ) )
{ }
Parser - > Mode = OldMode ;
}
else
{ /* just run it in its current mode */
while ( ParseStatement ( Parser ) )
{ }
}
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenRightBrace )
ProgramFail ( Parser , " '}' expected " ) ;
return Parser - > Mode ;
}
2008-12-18 19:22:52 -05:00
/* parse a statement */
2009-02-18 03:19:06 -05:00
int ParseStatement ( struct ParseState * Parser )
2008-11-21 21:56:08 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * CValue ;
int Condition ;
2009-02-01 06:31:18 -05:00
struct ParseState PreState = * Parser ;
enum LexToken Token = LexGetToken ( Parser , NULL , TRUE ) ;
2008-11-21 21:56:08 -05:00
switch ( Token )
{
2008-12-20 05:24:34 -05:00
case TokenEOF :
return FALSE ;
2008-11-21 21:56:08 -05:00
case TokenIdentifier :
2009-02-01 06:31:18 -05:00
* Parser = PreState ;
2009-02-19 18:29:35 -05:00
ParseExpression ( Parser , & CValue ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
2009-02-12 07:15:25 -05:00
VariableStackPop ( Parser , CValue ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenLeftBrace :
2009-02-19 04:07:00 -05:00
ParseBlock ( Parser , FALSE , TRUE ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenIf :
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenOpenBracket )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " '(' expected " ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2008-11-21 21:56:08 -05:00
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenCloseBracket )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " ')' expected " ) ;
2009-02-18 03:19:06 -05:00
if ( ! ParseStatementMaybeRun ( Parser , Condition ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " statement expected " ) ;
2008-11-21 21:56:08 -05:00
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , FALSE ) = = TokenElse )
2008-11-21 21:56:08 -05:00
{
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ;
2009-02-18 03:19:06 -05:00
if ( ! ParseStatementMaybeRun ( Parser , ! Condition ) )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " statement expected " ) ;
2008-11-21 21:56:08 -05:00
}
2008-10-16 03:04:23 -04:00
break ;
2008-11-21 21:56:08 -05:00
case TokenWhile :
2008-10-16 03:04:23 -04:00
{
2009-02-19 04:07:00 -05:00
struct ParseState PreConditional ;
ParserCopyPos ( & PreConditional , Parser ) ;
2008-11-21 21:56:08 -05:00
do
{
2009-02-19 04:07:00 -05:00
ParserCopyPos ( Parser , & PreConditional ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2009-02-19 04:07:00 -05:00
ParseBlock ( Parser , TRUE , Condition ) ;
if ( Parser - > Mode = = RunModeContinue )
Parser - > Mode = RunModeRun ;
} while ( Parser - > Mode = = RunModeRun & & Condition ) ;
2008-11-21 21:56:08 -05:00
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeBreak )
Parser - > Mode = RunModeRun ;
2008-11-21 21:56:08 -05:00
}
break ;
case TokenDo :
{
2009-02-19 04:07:00 -05:00
struct ParseState PreStatement ;
ParserCopyPos ( & PreStatement , Parser ) ;
2008-11-21 21:56:08 -05:00
do
{
2009-02-19 04:07:00 -05:00
ParserCopyPos ( Parser , & PreStatement ) ;
ParseBlock ( Parser , TRUE , TRUE ) ;
if ( Parser - > Mode = = RunModeContinue )
Parser - > Mode = RunModeRun ;
2009-02-19 06:01:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenWhile )
ProgramFail ( Parser , " 'while' expected " ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2008-11-21 21:56:08 -05:00
2009-02-18 03:19:06 -05:00
} while ( Condition & & Parser - > Mode = = RunModeRun ) ;
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeBreak )
Parser - > Mode = RunModeRun ;
2008-11-21 21:56:08 -05:00
}
break ;
case TokenFor :
2009-02-18 03:19:06 -05:00
ParseFor ( Parser ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenSemicolon : break ;
case TokenIntType :
case TokenCharType :
2008-12-26 21:25:49 -05:00
case TokenFloatType :
case TokenDoubleType :
2008-11-21 21:56:08 -05:00
case TokenVoidType :
2009-02-10 03:42:09 -05:00
case TokenStructType :
case TokenUnionType :
2009-02-01 06:31:18 -05:00
* Parser = PreState ;
2009-03-05 23:55:11 -05:00
ParseDeclaration ( Parser , Token ) ;
2008-11-21 21:56:08 -05:00
break ;
2008-12-23 22:27:53 -05:00
2009-01-03 23:08:49 -05:00
case TokenHashDefine :
2009-02-01 06:31:18 -05:00
ParseMacroDefinition ( Parser ) ;
2009-01-03 23:08:49 -05:00
break ;
case TokenHashInclude :
2009-01-26 03:57:32 -05:00
{
struct Value * LexerValue ;
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , & LexerValue , TRUE ) ! = TokenStringConstant )
ProgramFail ( Parser , " \" filename.h \" expected " ) ;
2009-01-04 23:38:19 -05:00
2009-02-20 21:35:52 -05:00
//ScanFile(LexerValue->Val->String); // XXX - need to dereference char * here
2009-01-04 23:38:19 -05:00
break ;
2009-01-26 03:57:32 -05:00
}
2009-01-04 23:38:19 -05:00
2009-01-04 23:28:54 -05:00
case TokenSwitch :
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenOpenBracket )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " '(' expected " ) ;
2009-02-18 03:19:06 -05:00
Condition = ParseIntExpression ( Parser ) ;
2009-02-17 18:36:09 -05:00
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenCloseBracket )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " ')' expected " ) ;
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , FALSE ) ! = TokenLeftBrace )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " '{' expected " ) ;
2009-02-18 06:03:14 -05:00
{ /* new block so we can store parser state */
2009-02-18 03:19:06 -05:00
enum RunMode OldMode = Parser - > Mode ;
int OldSearchLabel = Parser - > SearchLabel ;
Parser - > Mode = RunModeCaseSearch ;
Parser - > SearchLabel = Condition ;
2009-02-19 04:07:00 -05:00
ParseBlock ( Parser , TRUE , TRUE ) ;
2009-02-18 03:19:06 -05:00
Parser - > Mode = OldMode ;
Parser - > SearchLabel = OldSearchLabel ;
}
2009-02-17 18:36:09 -05:00
break ;
2009-01-04 23:28:54 -05:00
case TokenCase :
2009-02-19 04:07:00 -05:00
if ( Parser - > Mode = = RunModeCaseSearch )
{
Parser - > Mode = RunModeRun ;
Condition = ParseIntExpression ( Parser ) ;
Parser - > Mode = RunModeCaseSearch ;
}
else
Condition = ParseIntExpression ( Parser ) ;
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenColon )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " ':' expected " ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeCaseSearch & & Condition = = Parser - > SearchLabel )
Parser - > Mode = RunModeRun ;
2009-02-17 18:36:09 -05:00
break ;
case TokenDefault :
2009-02-18 06:03:14 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenColon )
2009-02-17 18:36:09 -05:00
ProgramFail ( Parser , " ':' expected " ) ;
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeCaseSearch )
Parser - > Mode = RunModeRun ;
2009-02-17 18:36:09 -05:00
break ;
2009-01-05 00:50:04 -05:00
case TokenBreak :
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
Parser - > Mode = RunModeBreak ;
2009-02-17 18:36:09 -05:00
break ;
case TokenContinue :
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
Parser - > Mode = RunModeContinue ;
2009-02-17 18:36:09 -05:00
break ;
2009-01-04 23:28:54 -05:00
case TokenReturn :
2009-02-18 03:19:06 -05:00
if ( Parser - > Mode = = RunModeRun )
{
2009-02-19 19:12:58 -05:00
if ( ! ParseExpression ( Parser , & CValue ) & & TopStackFrame - > ReturnValue - > Typ - > Base ! = TypeVoid )
ProgramFail ( Parser , " value required in return " ) ;
if ( CValue - > Typ ! = TopStackFrame - > ReturnValue - > Typ )
ProgramFail ( Parser , " wrong return type " ) ;
// XXX - make assignment a separate function
2009-02-23 21:28:35 -05:00
// XXX - also arrays need cleverer assignment
2009-02-20 21:35:52 -05:00
memcpy ( TopStackFrame - > ReturnValue - > Val , CValue - > Val , TypeSizeValue ( CValue ) ) ;
2009-02-19 19:12:58 -05:00
Parser - > Mode = RunModeReturn ;
2009-02-18 03:19:06 -05:00
}
2008-12-23 22:27:53 -05:00
break ;
2008-11-21 21:56:08 -05:00
default :
2009-02-01 06:31:18 -05:00
* Parser = PreState ;
2008-11-21 21:56:08 -05:00
return FALSE ;
2008-10-16 03:04:23 -04:00
}
2008-11-21 21:56:08 -05:00
return TRUE ;
}
2008-10-12 20:53:28 -04:00
/* quick scan a source file for definitions */
2009-02-02 06:08:36 -05:00
void Parse ( const char * FileName , const char * Source , int SourceLen , int RunIt )
2008-10-12 20:53:28 -04:00
{
2009-02-01 06:31:18 -05:00
struct ParseState Parser ;
2008-10-12 20:53:28 -04:00
2009-02-02 06:50:55 -05:00
void * Tokens = LexAnalyse ( FileName , Source , SourceLen ) ; // XXX - some better way of storing tokenised input?
2009-02-18 03:19:06 -05:00
LexInitParser ( & Parser , Tokens , FileName , 1 , RunIt ) ;
2009-02-02 06:50:55 -05:00
2009-02-18 03:19:06 -05:00
while ( ParseStatement ( & Parser ) )
2008-12-20 05:24:34 -05:00
{ }
2009-02-02 06:08:36 -05:00
if ( LexGetToken ( & Parser , NULL , FALSE ) ! = TokenEOF )
2009-02-01 06:31:18 -05:00
ProgramFail ( & Parser , " parse error " ) ;
2008-10-12 20:53:28 -04:00
}