2008-10-12 20:53:28 -04:00
# include <stdio.h>
# include "picoc.h"
2008-12-23 21:30:29 -05:00
/* parameter passing area */
2009-01-24 21:09:44 -05:00
struct Value * Parameter [ PARAMETER_MAX ] ;
2008-12-23 21:30:29 -05:00
int ParameterUsed = 0 ;
2009-01-24 21:09:44 -05:00
struct Value * ReturnValue ;
2008-12-23 21:30:29 -05:00
2008-12-18 19:22:52 -05:00
/* local prototypes */
2009-01-26 03:57:32 -05:00
int ParseIntExpression ( struct LexState * Lexer , int RunIt ) ;
2008-12-20 20:36:09 -05:00
int ParseStatement ( struct LexState * Lexer , int RunIt ) ;
2008-12-23 21:30:29 -05:00
int ParseArguments ( struct LexState * Lexer , int RunIt ) ;
2008-10-14 00:51:34 -04:00
2008-12-18 19:22:52 -05:00
/* initialise the parser */
2008-10-12 20:53:28 -04:00
void ParseInit ( )
{
2009-01-23 06:34:12 -05:00
VariableInit ( ) ;
2008-12-26 23:36:45 -05:00
IntrinsicInit ( & GlobalTable ) ;
2009-01-23 06:34:12 -05:00
TypeInit ( ) ;
2008-12-23 21:30:29 -05:00
}
/* parse a parameter list, defining parameters as local variables in the current scope */
void ParseParameterList ( struct LexState * CallLexer , struct LexState * FuncLexer , int RunIt )
{
2009-01-21 04:02:05 -05:00
struct ValueType * Typ ;
2009-01-23 22:15:02 -05:00
Str Identifier ;
2008-12-23 22:27:53 -05:00
enum LexToken Token = LexGetPlainToken ( FuncLexer ) ; /* open bracket */
2008-12-23 21:30:29 -05:00
int ParamCount ;
2008-12-23 22:27:53 -05:00
for ( ParamCount = 0 ; ParamCount < ParameterUsed ; ParamCount + + )
2008-12-23 21:30:29 -05:00
{
2009-01-23 22:15:02 -05:00
TypeParse ( FuncLexer , & Typ , & Identifier ) ;
2009-01-24 21:09:44 -05:00
if ( Identifier . Len ! = 0 )
2009-01-05 00:50:04 -05:00
{ /* there's an identifier */
if ( RunIt )
{
2009-01-24 21:09:44 -05:00
if ( Parameter [ ParamCount ] - > Typ ! = Typ )
2009-01-05 00:50:04 -05:00
ProgramFail ( CallLexer , " parameter %d has the wrong type " , ParamCount + 1 ) ;
2009-01-24 21:09:44 -05:00
VariableDefine ( FuncLexer , & Identifier , Parameter [ ParamCount ] ) ;
2009-01-05 00:50:04 -05:00
}
2009-01-23 22:15:02 -05:00
}
2009-01-05 00:50:04 -05:00
2009-01-23 22:15:02 -05:00
Token = LexGetPlainToken ( FuncLexer ) ;
if ( ParamCount < ParameterUsed - 1 & & Token ! = TokenComma )
2009-01-05 00:50:04 -05:00
ProgramFail ( FuncLexer , " comma expected " ) ;
2009-01-23 22:15:02 -05:00
}
if ( Token ! = TokenCloseBracket )
ProgramFail ( FuncLexer , " ')' expected " ) ;
2008-12-23 22:27:53 -05:00
if ( ParameterUsed = = 0 )
Token = LexGetPlainToken ( FuncLexer ) ;
2008-12-23 21:30:29 -05:00
2008-12-23 22:27:53 -05:00
if ( Token ! = TokenCloseBracket )
2008-12-23 21:30:29 -05:00
ProgramFail ( CallLexer , " wrong number of arguments " ) ;
}
/* do a function call */
2009-01-26 03:57:32 -05:00
void ParseFunctionCall ( struct LexState * Lexer , struct Value * * Result , int ResultOnHeap , Str * FuncName , int RunIt )
2008-12-23 21:30:29 -05:00
{
enum LexToken Token = LexGetPlainToken ( Lexer ) ; /* open bracket */
/* parse arguments */
ParameterUsed = 0 ;
do {
2009-01-26 03:57:32 -05:00
if ( ParseExpression ( Lexer , & Parameter [ ParameterUsed ] , FALSE , RunIt ) )
2008-12-23 21:30:29 -05:00
{
if ( RunIt & & ParameterUsed > = PARAMETER_MAX )
ProgramFail ( Lexer , " too many arguments " ) ;
ParameterUsed + + ;
Token = LexGetPlainToken ( Lexer ) ;
if ( Token ! = TokenComma & & Token ! = TokenCloseBracket )
ProgramFail ( Lexer , " comma expected " ) ;
}
else
{
Token = LexGetPlainToken ( Lexer ) ;
2008-12-23 22:27:53 -05:00
if ( ! TokenCloseBracket )
2008-12-23 21:30:29 -05:00
ProgramFail ( Lexer , " bad argument " ) ;
}
} while ( Token ! = TokenCloseBracket ) ;
if ( RunIt )
{
struct LexState FuncLexer ;
2009-01-21 04:02:05 -05:00
struct ValueType * ReturnType ;
2009-01-26 03:57:32 -05:00
struct Value * FuncValue ;
Str FuncName ;
2009-01-24 21:09:44 -05:00
int Count ;
2008-12-23 21:30:29 -05:00
2009-01-26 03:57:32 -05:00
VariableGet ( Lexer , & FuncName , & FuncValue ) ;
if ( ( * Result ) - > Typ - > Base ! = TypeFunction )
2008-12-23 21:30:29 -05:00
ProgramFail ( Lexer , " not a function - can't call " ) ;
2009-01-03 23:08:49 -05:00
2009-01-23 06:34:12 -05:00
VariableStackFrameAdd ( Lexer ) ;
2009-01-26 03:57:32 -05:00
if ( FuncValue - > Val - > Integer > = 0 )
FuncLexer = FunctionStore [ FuncValue - > Val - > Integer ] ;
2008-12-26 23:36:45 -05:00
else
2009-01-26 03:57:32 -05:00
IntrinsicGetLexer ( & FuncLexer , FuncValue - > Val - > Integer ) ;
2008-12-26 23:36:45 -05:00
2009-01-26 03:57:32 -05:00
TypeParse ( & FuncLexer , & ReturnType , & FuncName ) ; /* get the return type */
* Result = VariableAllocValueFromType ( Lexer , ReturnType , ResultOnHeap ) ;
2008-12-23 21:30:29 -05:00
ParseParameterList ( Lexer , & FuncLexer , TRUE ) ; /* parameters */
2009-01-26 03:57:32 -05:00
if ( FuncValue - > Val - > Integer > = 0 )
{ /* run a user-defined function */
2008-12-26 23:36:45 -05:00
if ( LexPeekPlainToken ( & FuncLexer ) ! = TokenLeftBrace | | ! ParseStatement ( & FuncLexer , TRUE ) )
ProgramFail ( & FuncLexer , " function body expected " ) ;
2008-12-23 21:30:29 -05:00
2009-01-26 03:57:32 -05:00
if ( ReturnType ! = ( * Result ) - > Typ )
2008-12-26 23:36:45 -05:00
ProgramFail ( & FuncLexer , " bad return value " ) ;
}
else
2009-01-26 03:57:32 -05:00
IntrinsicCall ( Lexer , * Result , ReturnType , ( * Result ) - > Val - > Integer ) ;
2009-01-24 21:09:44 -05:00
2009-01-26 03:57:32 -05:00
VariableStackFramePop ( Lexer ) ;
for ( Count = ParameterUsed - 1 ; Count > = 0 ; Count - - ) /* free stack space used by parameters */
VariableStackPop ( Lexer , Parameter [ Count ] ) ;
2008-12-23 21:30:29 -05:00
}
}
2008-12-18 19:22:52 -05:00
/* parse a single value */
2009-01-26 03:57:32 -05:00
int ParseValue ( struct LexState * Lexer , struct Value * * Result , int ResultOnHeap , int RunIt )
2008-10-16 03:04:23 -04:00
{
2008-11-21 21:56:08 -05:00
struct LexState PreState = * Lexer ;
2009-01-26 03:57:32 -05:00
struct Value * LexValue ;
int IntValue ;
enum LexToken Token = LexGetToken ( Lexer , & LexValue ) ;
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 :
* Result = VariableAllocValueAndCopy ( Lexer , LexValue , ResultOnHeap ) ;
break ;
2008-11-21 21:56:08 -05:00
case TokenMinus : case TokenUnaryExor : case TokenUnaryNot :
2009-01-26 03:57:32 -05:00
IntValue = ParseIntExpression ( Lexer , RunIt ) ;
2008-12-20 22:46:32 -05:00
if ( RunIt )
2008-11-21 21:56:08 -05:00
{
2009-01-26 03:57:32 -05:00
* Result = VariableAllocValueFromType ( Lexer , & IntType , ResultOnHeap ) ;
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-01-26 03:57:32 -05:00
if ( ! ParseExpression ( Lexer , Result , ResultOnHeap , RunIt ) )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " invalid expression " ) ;
2008-12-22 06:52:31 -05:00
if ( LexGetPlainToken ( Lexer ) ! = TokenCloseBracket )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " ')' expected " ) ;
break ;
case TokenAsterisk :
case TokenAmpersand :
ProgramFail ( Lexer , " not implemented " ) ;
case TokenIdentifier :
2008-12-23 21:30:29 -05:00
if ( LexPeekPlainToken ( Lexer ) = = TokenOpenBracket )
2009-01-26 03:57:32 -05:00
ParseFunctionCall ( Lexer , Result , ResultOnHeap , & LexValue - > Val - > String , RunIt ) ;
2008-12-23 21:30:29 -05:00
else
{
if ( RunIt )
2009-01-03 23:08:49 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * IdentValue ;
VariableGet ( Lexer , & LexValue - > Val - > String , & IdentValue ) ;
if ( IdentValue - > Typ - > Base = = TypeMacro )
2009-01-04 23:28:54 -05:00
{
2009-01-26 03:57:32 -05:00
struct LexState MacroLexer = FunctionStore [ IdentValue - > Val - > Integer ] ;
2009-01-04 23:28:54 -05:00
2009-01-26 03:57:32 -05:00
if ( ! ParseExpression ( & MacroLexer , Result , ResultOnHeap , TRUE ) )
2009-01-04 23:28:54 -05:00
ProgramFail ( & MacroLexer , " expression expected " ) ;
}
2009-01-26 03:57:32 -05:00
else if ( ! ISVALUETYPE ( IdentValue - > Typ ) )
2009-01-03 23:08:49 -05:00
ProgramFail ( Lexer , " bad variable type " ) ;
}
2008-12-23 21:30:29 -05:00
}
2008-11-21 21:56:08 -05:00
break ;
default :
* Lexer = PreState ;
2008-12-20 05:24:34 -05:00
return FALSE ;
2008-11-21 21:56:08 -05:00
}
2008-10-16 03:04:23 -04:00
2008-11-21 21:56:08 -05:00
return TRUE ;
}
2009-01-26 03:57:32 -05:00
struct Value * ParsePushFP ( struct LexState * Lexer , int ResultOnHeap , double NewFP )
{
struct Value * Val = VariableAllocValueFromType ( Lexer , & FPType , ResultOnHeap ) ;
Val - > Val - > FP = NewFP ;
return Val ;
}
struct Value * ParsePushInt ( struct LexState * Lexer , int ResultOnHeap , int NewInt )
{
struct Value * Val = VariableAllocValueFromType ( Lexer , & IntType , ResultOnHeap ) ;
Val - > Val - > Integer = NewInt ;
return Val ;
}
2008-12-18 19:22:52 -05:00
/* parse an expression. operator precedence is not supported */
2009-01-26 03:57:32 -05:00
int ParseExpression ( struct LexState * Lexer , struct Value * * Result , int ResultOnHeap , int RunIt )
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-01-26 03:57:32 -05:00
if ( ! ParseValue ( Lexer , & TotalValue , ResultOnHeap , RunIt ) )
2008-11-21 21:56:08 -05:00
return FALSE ;
while ( TRUE )
2008-10-16 03:04:23 -04:00
{
2009-01-26 03:57:32 -05:00
enum LexToken Token = LexPeekPlainToken ( Lexer ) ;
2008-11-21 21:56:08 -05:00
switch ( Token )
{
case TokenPlus : case TokenMinus : case TokenAsterisk : case TokenSlash :
case TokenEquality : case TokenLessThan : case TokenGreaterThan :
case TokenLessEqual : case TokenGreaterEqual : case TokenLogicalAnd :
2008-12-20 05:24:34 -05:00
case TokenLogicalOr : case TokenAmpersand : case TokenArithmeticOr :
case TokenArithmeticExor : case TokenDot :
2008-12-22 06:52:31 -05:00
LexGetPlainToken ( Lexer ) ;
2008-11-21 21:56:08 -05:00
break ;
2008-12-20 05:24:34 -05:00
case TokenAssign : case TokenAddAssign : case TokenSubtractAssign :
2008-12-22 06:52:31 -05:00
LexGetPlainToken ( Lexer ) ;
2009-01-26 03:57:32 -05:00
if ( ! ParseExpression ( Lexer , & CurrentValue , ResultOnHeap , RunIt ) )
2008-12-20 05:24:34 -05:00
ProgramFail ( Lexer , " expression expected " ) ;
2008-12-20 22:46:32 -05:00
if ( RunIt )
2008-12-20 05:24:34 -05:00
{
2009-01-26 03:57:32 -05:00
if ( CurrentValue - > Typ - > Base ! = TypeInt | | TotalValue - > Typ - > Base ! = TypeInt )
2008-12-20 22:46:32 -05:00
ProgramFail ( Lexer , " can't assign " ) ;
switch ( Token )
{
2009-01-26 03:57:32 -05:00
case TokenAddAssign : TotalValue - > Val - > Integer + = CurrentValue - > Val - > Integer ; break ;
case TokenSubtractAssign : TotalValue - > Val - > Integer - = CurrentValue - > Val - > Integer ; break ;
default : TotalValue - > Val - > Integer = CurrentValue - > Val - > Integer ; break ;
2008-12-20 22:46:32 -05:00
}
2009-01-26 03:57:32 -05:00
VariableStackPop ( Lexer , CurrentValue ) ;
2008-12-20 05:24:34 -05:00
}
// fallthrough
2008-11-21 21:56:08 -05:00
default :
2008-12-20 22:46:32 -05:00
if ( RunIt )
* Result = TotalValue ;
2008-11-21 21:56:08 -05:00
return TRUE ;
}
2009-01-26 03:57:32 -05:00
if ( ! ParseValue ( Lexer , & CurrentValue , ResultOnHeap , RunIt ) )
2008-11-21 21:56:08 -05:00
return FALSE ;
2008-12-20 05:24:34 -05:00
2008-12-20 22:46:32 -05:00
if ( RunIt )
2008-10-16 03:04:23 -04:00
{
2009-01-26 03:57:32 -05:00
if ( CurrentValue - > Typ - > Base = = TypeFP | | TotalValue - > Typ - > Base = = TypeFP )
{
double FPTotal , FPCurrent ;
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
ProgramFail ( Lexer , " 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 ( Lexer , " bad type for operator " ) ;
}
VariableStackPop ( Lexer , CurrentValue ) ;
VariableStackPop ( Lexer , TotalValue ) ;
2008-12-26 21:25:49 -05:00
switch ( Token )
{
2009-01-26 03:57:32 -05:00
case TokenPlus : TotalValue = ParsePushFP ( Lexer , ResultOnHeap , FPTotal + FPCurrent ) ; break ;
case TokenMinus : TotalValue = ParsePushFP ( Lexer , ResultOnHeap , FPTotal - FPCurrent ) ; break ;
case TokenAsterisk : TotalValue = ParsePushFP ( Lexer , ResultOnHeap , FPTotal * FPCurrent ) ; break ;
case TokenSlash : TotalValue = ParsePushFP ( Lexer , ResultOnHeap , FPTotal / FPCurrent ) ; break ;
case TokenEquality : TotalValue = ParsePushInt ( Lexer , ResultOnHeap , FPTotal = = FPCurrent ) ; break ;
case TokenLessThan : TotalValue = ParsePushInt ( Lexer , ResultOnHeap , FPTotal < FPCurrent ) ; break ;
case TokenGreaterThan : TotalValue = ParsePushInt ( Lexer , ResultOnHeap , FPTotal > FPCurrent ) ; break ;
case TokenLessEqual : TotalValue = ParsePushInt ( Lexer , ResultOnHeap , FPTotal < = FPCurrent ) ; break ;
case TokenGreaterEqual : TotalValue = ParsePushInt ( Lexer , ResultOnHeap , FPTotal > = FPCurrent ) ; break ;
2008-12-26 21:25:49 -05:00
case TokenLogicalAnd : case TokenLogicalOr : case TokenAmpersand : case TokenArithmeticOr : case TokenArithmeticExor : ProgramFail ( Lexer , " bad type for operator " ) ; break ;
case TokenDot : ProgramFail ( Lexer , " operator not supported " ) ; break ;
default : break ;
}
}
else
2008-12-20 22:46:32 -05:00
{
2009-01-26 03:57:32 -05:00
if ( CurrentValue - > Typ - > Base ! = TypeInt | | TotalValue - > Typ - > Base ! = TypeInt )
2008-12-26 21:25:49 -05:00
ProgramFail ( Lexer , " bad operand types " ) ;
/* integer arithmetic */
switch ( Token )
{
2009-01-26 03:57:32 -05:00
case TokenPlus : TotalValue - > Val - > Integer + = CurrentValue - > Val - > Integer ; break ;
case TokenMinus : TotalValue - > Val - > Integer - = CurrentValue - > Val - > Integer ; break ;
case TokenAsterisk : TotalValue - > Val - > Integer * = CurrentValue - > Val - > Integer ; break ;
case TokenSlash : TotalValue - > Val - > Integer / = CurrentValue - > Val - > Integer ; break ;
case TokenEquality : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer = = CurrentValue - > Val - > Integer ; break ;
case TokenLessThan : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer < CurrentValue - > Val - > Integer ; break ;
case TokenGreaterThan : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer > CurrentValue - > Val - > Integer ; break ;
case TokenLessEqual : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer < = CurrentValue - > Val - > Integer ; break ;
case TokenGreaterEqual : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer > = CurrentValue - > Val - > Integer ; break ;
case TokenLogicalAnd : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer & & CurrentValue - > Val - > Integer ; break ;
case TokenLogicalOr : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer | | CurrentValue - > Val - > Integer ; break ;
case TokenAmpersand : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer & CurrentValue - > Val - > Integer ; break ;
case TokenArithmeticOr : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer | CurrentValue - > Val - > Integer ; break ;
case TokenArithmeticExor : TotalValue - > Val - > Integer = TotalValue - > Val - > Integer ^ CurrentValue - > Val - > Integer ; break ;
2008-12-26 21:25:49 -05:00
case TokenDot : ProgramFail ( Lexer , " operator not supported " ) ; break ;
default : break ;
}
2008-12-20 22:46:32 -05:00
}
2009-01-26 03:57:32 -05:00
VariableStackPop ( Lexer , CurrentValue ) ;
* Result = TotalValue ;
2008-11-21 21:56:08 -05:00
}
}
return TRUE ;
}
2008-12-18 19:22:52 -05:00
/* parse an expression. operator precedence is not supported */
2009-01-26 03:57:32 -05:00
int ParseIntExpression ( struct LexState * Lexer , int RunIt )
2008-12-18 19:22:52 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * Val ;
int Result = 0 ;
if ( ! ParseExpression ( Lexer , & Val , FALSE , RunIt ) )
2008-12-18 19:22:52 -05:00
ProgramFail ( Lexer , " expression expected " ) ;
2009-01-26 03:57:32 -05:00
if ( RunIt )
{
if ( Val - > Typ - > Base ! = TypeInt )
ProgramFail ( Lexer , " integer value expected " ) ;
Result = Val - > Val - > Integer ;
VariableStackPop ( Lexer , Val ) ;
}
return Result ;
2008-12-18 19:22:52 -05:00
}
2008-11-21 21:56:08 -05:00
2008-12-20 20:36:09 -05:00
/* parse a function definition and store it for later */
void ParseFunctionDefinition ( struct LexState * Lexer , Str * Identifier , struct LexState * PreState )
2008-12-20 06:46:21 -05:00
{
2009-01-21 04:02:05 -05:00
struct Value * FuncValue ;
2008-12-20 20:36:09 -05:00
if ( FunctionStoreUsed > = FUNCTION_STORE_MAX )
2009-01-04 23:28:54 -05:00
ProgramFail ( Lexer , " too many functions/macros defined " ) ;
2008-12-20 20:36:09 -05:00
FunctionStore [ FunctionStoreUsed ] = * PreState ;
2008-12-22 06:52:31 -05:00
LexGetPlainToken ( Lexer ) ;
2009-01-26 03:57:32 -05:00
if ( LexGetPlainToken ( Lexer ) ! = TokenCloseBracket | | LexPeekPlainToken ( Lexer ) ! = TokenLeftBrace )
2008-12-20 20:36:09 -05:00
ProgramFail ( Lexer , " bad function definition " ) ;
if ( ! ParseStatement ( Lexer , FALSE ) )
ProgramFail ( Lexer , " function definition expected " ) ;
FunctionStore [ FunctionStoreUsed ] . End = Lexer - > Pos ;
2009-01-26 03:57:32 -05:00
FuncValue = VariableAllocValueAndData ( Lexer , sizeof ( int ) , TRUE ) ;
2009-01-21 04:02:05 -05:00
FuncValue - > Typ = & FunctionType ;
FuncValue - > Val - > Integer = FunctionStoreUsed ;
2008-12-20 20:36:09 -05:00
FunctionStoreUsed + + ;
2009-01-21 04:02:05 -05:00
if ( ! TableSet ( & GlobalTable , Identifier , FuncValue ) )
2008-12-20 20:36:09 -05:00
ProgramFail ( Lexer , " '%S' is already defined " , Identifier ) ;
2008-12-20 06:46:21 -05:00
}
2009-01-04 23:28:54 -05:00
/* parse a #define macro definition and store it for later */
void ParseMacroDefinition ( struct LexState * Lexer )
{
2009-01-26 03:57:32 -05:00
struct Value * MacroName ;
2009-01-21 04:02:05 -05:00
struct Value * MacroValue ;
2009-01-04 23:28:54 -05:00
if ( LexGetToken ( Lexer , & MacroName ) ! = TokenIdentifier )
ProgramFail ( Lexer , " identifier expected " ) ;
if ( FunctionStoreUsed > = FUNCTION_STORE_MAX )
ProgramFail ( Lexer , " too many functions/macros defined " ) ;
FunctionStore [ FunctionStoreUsed ] = * Lexer ;
LexToEndOfLine ( Lexer ) ;
FunctionStore [ FunctionStoreUsed ] . End = Lexer - > Pos ;
2009-01-26 03:57:32 -05:00
MacroValue = VariableAllocValueAndData ( Lexer , sizeof ( int ) , TRUE ) ;
2009-01-21 04:02:05 -05:00
MacroValue - > Typ = & MacroType ;
MacroValue - > Val - > Integer = FunctionStoreUsed ;
2009-01-04 23:28:54 -05:00
FunctionStoreUsed + + ;
2009-01-26 03:57:32 -05:00
if ( ! TableSet ( & GlobalTable , & MacroName - > Val - > String , MacroValue ) )
ProgramFail ( Lexer , " '%S' is already defined " , & MacroName - > Val - > String ) ;
2009-01-04 23:28:54 -05:00
}
2009-01-23 22:15:02 -05:00
void ParseFor ( struct LexState * Lexer , int RunIt )
2009-01-03 23:08:49 -05:00
{
2009-01-26 03:57:32 -05:00
int Condition ;
2009-01-03 23:08:49 -05:00
struct LexState PreConditional ;
struct LexState PreIncrement ;
struct LexState PreStatement ;
struct LexState After ;
if ( LexGetPlainToken ( Lexer ) ! = TokenOpenBracket )
ProgramFail ( Lexer , " '(' expected " ) ;
if ( ! ParseStatement ( Lexer , RunIt ) )
ProgramFail ( Lexer , " statement expected " ) ;
PreConditional = * Lexer ;
2009-01-26 03:57:32 -05:00
Condition = ParseIntExpression ( Lexer , RunIt ) ;
2009-01-03 23:08:49 -05:00
if ( LexGetPlainToken ( Lexer ) ! = TokenSemicolon )
ProgramFail ( Lexer , " ';' expected " ) ;
PreIncrement = * Lexer ;
ParseStatement ( Lexer , FALSE ) ;
if ( LexGetPlainToken ( Lexer ) ! = TokenCloseBracket )
ProgramFail ( Lexer , " ')' expected " ) ;
PreStatement = * Lexer ;
2009-01-26 03:57:32 -05:00
if ( ! ParseStatement ( Lexer , RunIt & & Condition ) )
2009-01-03 23:08:49 -05:00
ProgramFail ( Lexer , " statement expected " ) ;
After = * Lexer ;
2009-01-26 03:57:32 -05:00
while ( Condition & & RunIt )
2009-01-03 23:08:49 -05:00
{
* Lexer = PreIncrement ;
ParseStatement ( Lexer , TRUE ) ;
* Lexer = PreConditional ;
2009-01-26 03:57:32 -05:00
Condition = ParseIntExpression ( Lexer , RunIt ) ;
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
{
* Lexer = PreStatement ;
ParseStatement ( Lexer , TRUE ) ;
}
}
* Lexer = After ;
}
2008-12-18 19:22:52 -05:00
/* parse a statement */
2008-11-21 21:56:08 -05:00
int ParseStatement ( struct LexState * Lexer , int RunIt )
{
2009-01-26 03:57:32 -05:00
struct Value * CValue ;
int Condition ;
2008-11-21 21:56:08 -05:00
struct LexState PreState = * Lexer ;
2009-01-26 03:57:32 -05:00
Str Identifier ;
2009-01-21 04:02:05 -05:00
struct ValueType * Typ ;
2009-01-26 03:57:32 -05:00
enum LexToken Token = LexGetPlainToken ( Lexer ) ;
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 :
2008-12-20 06:46:21 -05:00
* Lexer = PreState ;
2009-01-26 03:57:32 -05:00
ParseExpression ( Lexer , & CValue , FALSE , RunIt ) ;
if ( RunIt ) VariableStackPop ( Lexer , CValue ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenLeftBrace :
while ( ParseStatement ( Lexer , RunIt ) )
{ }
2008-12-22 06:52:31 -05:00
if ( LexGetPlainToken ( Lexer ) ! = TokenRightBrace )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " '}' expected " ) ;
break ;
case TokenIf :
2009-01-26 03:57:32 -05:00
Condition = ParseIntExpression ( Lexer , RunIt ) ;
2008-11-21 21:56:08 -05:00
2009-01-26 03:57:32 -05:00
if ( ! ParseStatement ( Lexer , RunIt & & Condition ) )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " statement expected " ) ;
2009-01-26 03:57:32 -05:00
if ( LexPeekPlainToken ( Lexer ) = = TokenElse )
2008-11-21 21:56:08 -05:00
{
2009-01-26 03:57:32 -05:00
LexGetPlainToken ( Lexer ) ;
if ( ! ParseStatement ( Lexer , RunIt & & ! Condition ) )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " statement expected " ) ;
}
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
{
2008-11-21 21:56:08 -05:00
struct LexState PreConditional = * Lexer ;
do
{
* Lexer = PreConditional ;
2009-01-26 03:57:32 -05:00
Condition = ParseIntExpression ( Lexer , RunIt ) ;
2008-11-21 21:56:08 -05:00
2009-01-26 03:57:32 -05:00
if ( ! ParseStatement ( Lexer , RunIt & & Condition ) )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " statement expected " ) ;
2009-01-26 03:57:32 -05:00
} while ( RunIt & & Condition ) ;
2008-11-21 21:56:08 -05:00
}
break ;
case TokenDo :
{
struct LexState PreStatement = * Lexer ;
do
{
* Lexer = PreStatement ;
if ( ! ParseStatement ( Lexer , RunIt ) )
ProgramFail ( Lexer , " statement expected " ) ;
2009-01-26 03:57:32 -05:00
Condition = ParseIntExpression ( Lexer , RunIt ) ;
2008-11-21 21:56:08 -05:00
2009-01-26 03:57:32 -05:00
} while ( Condition & & RunIt ) ;
2008-11-21 21:56:08 -05:00
}
break ;
case TokenFor :
2009-01-23 22:15:02 -05:00
ParseFor ( Lexer , RunIt ) ;
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 :
2008-12-22 06:52:31 -05:00
* Lexer = PreState ;
2009-01-26 03:57:32 -05:00
TypeParse ( Lexer , & Typ , & Identifier ) ;
if ( Identifier . Len = = 0 )
2008-11-21 21:56:08 -05:00
ProgramFail ( Lexer , " identifier expected " ) ;
2008-12-20 06:46:21 -05:00
/* handle function definitions */
2008-12-22 06:52:31 -05:00
if ( LexPeekPlainToken ( Lexer ) = = TokenOpenBracket )
2009-01-26 03:57:32 -05:00
ParseFunctionDefinition ( Lexer , & Identifier , & PreState ) ;
2008-12-20 06:46:21 -05:00
else
2009-01-26 03:57:32 -05:00
VariableDefine ( Lexer , & Identifier , VariableAllocValueFromType ( Lexer , Typ , FALSE ) ) ;
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-01-04 23:28:54 -05:00
ParseMacroDefinition ( Lexer ) ;
2009-01-03 23:08:49 -05:00
break ;
case TokenHashInclude :
2009-01-26 03:57:32 -05:00
{
struct Value * LexerValue ;
2009-01-04 23:38:19 -05:00
if ( LexGetToken ( Lexer , & LexerValue ) ! = TokenStringConstant )
ProgramFail ( Lexer , " \" filename.h \" expected " ) ;
2009-01-26 03:57:32 -05:00
ScanFile ( & LexerValue - > Val - > String ) ;
2009-01-04 23:38:19 -05:00
LexToEndOfLine ( Lexer ) ;
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 :
case TokenCase :
2009-01-05 00:50:04 -05:00
case TokenBreak :
2009-01-04 23:28:54 -05:00
case TokenReturn :
2008-12-23 22:27:53 -05:00
case TokenDefault :
2009-01-04 23:28:54 -05:00
ProgramFail ( Lexer , " not implemented yet " ) ;
2008-12-23 22:27:53 -05:00
break ;
2008-11-21 21:56:08 -05:00
default :
* Lexer = PreState ;
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 */
2008-12-20 05:24:34 -05:00
void Parse ( const Str * FileName , const Str * Source , int RunIt )
2008-10-12 20:53:28 -04:00
{
2008-10-14 00:51:34 -04:00
struct LexState Lexer ;
2008-10-12 20:53:28 -04:00
2008-10-14 00:51:34 -04:00
LexInit ( & Lexer , Source , FileName , 1 ) ;
2008-10-12 20:53:28 -04:00
2008-12-20 05:24:34 -05:00
while ( ParseStatement ( & Lexer , RunIt ) )
{ }
if ( Lexer . Pos ! = Lexer . End )
ProgramFail ( & Lexer , " parse error " ) ;
2008-10-12 20:53:28 -04:00
}