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-02-01 06:31:18 -05:00
int ParseIntExpression ( struct ParseState * Parser , int RunIt ) ;
int ParseStatement ( struct ParseState * Parser , int RunIt ) ;
int ParseArguments ( struct ParseState * Parser , 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
}
/* do a function call */
2009-02-02 06:08:36 -05:00
void ParseFunctionCall ( struct ParseState * Parser , struct Value * * Result , int ResultOnHeap , const char * FuncName , int RunIt )
2008-12-23 21:30:29 -05:00
{
2009-02-02 06:08:36 -05:00
struct Value * FuncValue ;
2009-02-01 06:31:18 -05:00
enum LexToken Token = LexGetToken ( Parser , NULL , TRUE ) ; /* open bracket */
2008-12-23 21:30:29 -05:00
2009-02-02 06:08:36 -05:00
if ( RunIt )
{ /* get the function definition */
VariableGet ( Parser , FuncName , & FuncValue ) ;
if ( FuncValue - > Typ - > Base ! = TypeFunction )
ProgramFail ( Parser , " not a function - can't call " ) ;
}
2008-12-23 21:30:29 -05:00
/* parse arguments */
ParameterUsed = 0 ;
do {
2009-02-01 06:31:18 -05:00
if ( ParseExpression ( Parser , & Parameter [ ParameterUsed ] , FALSE , RunIt ) )
2008-12-23 21:30:29 -05:00
{
2009-02-02 06:08:36 -05:00
if ( RunIt & & FuncValue - > Val - > FuncDef . ParamType [ ParameterUsed ] ! = Parameter [ ParameterUsed ] - > Typ )
ProgramFail ( Parser , " parameter %d to %s is the wrong type " , ParameterUsed , FuncName ) ;
2008-12-23 21:30:29 -05:00
ParameterUsed + + ;
2009-02-02 06:08:36 -05:00
if ( RunIt & & ParameterUsed > = FuncValue - > Val - > FuncDef . NumParams )
ProgramFail ( Parser , " too many arguments " ) ;
2009-02-01 06:31:18 -05:00
Token = LexGetToken ( Parser , NULL , TRUE ) ;
2008-12-23 21:30:29 -05:00
if ( Token ! = TokenComma & & Token ! = TokenCloseBracket )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " comma expected " ) ;
2008-12-23 21:30:29 -05:00
}
else
{
2009-02-01 06:31:18 -05:00
Token = LexGetToken ( Parser , NULL , TRUE ) ;
2008-12-23 22:27:53 -05:00
if ( ! TokenCloseBracket )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad argument " ) ;
2008-12-23 21:30:29 -05:00
}
} while ( Token ! = TokenCloseBracket ) ;
if ( RunIt )
2009-02-02 06:08:36 -05:00
{ /* run the function */
2009-01-24 21:09:44 -05:00
int Count ;
2008-12-23 21:30:29 -05:00
2009-02-01 06:31:18 -05:00
VariableStackFrameAdd ( Parser ) ;
2008-12-26 23:36:45 -05:00
2009-02-02 06:08:36 -05:00
* Result = VariableAllocValueFromType ( Parser , FuncValue - > Val - > FuncDef . ReturnType , ResultOnHeap ) ;
if ( FuncValue - > Val - > FuncDef . Intrinsic = = NULL )
2009-01-26 03:57:32 -05:00
{ /* run a user-defined function */
2009-02-02 06:08:36 -05:00
struct ParseState FuncParser = FuncValue - > Val - > FuncDef . Body ;
for ( Count = 0 ; Count < ParameterUsed ; Count + + )
VariableDefine ( Parser , FuncValue - > Val - > FuncDef . ParamName [ Count ] , Parameter [ Count ] ) ;
if ( ! ParseStatement ( & FuncParser , TRUE ) )
ProgramFail ( & FuncParser , " function body expected " ) ;
2008-12-23 21:30:29 -05:00
2009-02-02 06:08:36 -05:00
if ( FuncValue - > Val - > FuncDef . ReturnType ! = ( * Result ) - > Typ )
ProgramFail ( & FuncParser , " bad type of return value " ) ;
2008-12-26 23:36:45 -05:00
}
else
2009-02-02 06:08:36 -05:00
FuncValue - > Val - > FuncDef . Intrinsic ( ) ;
2009-01-24 21:09:44 -05:00
2009-02-01 06:31:18 -05:00
VariableStackFramePop ( Parser ) ;
2009-01-26 03:57:32 -05:00
for ( Count = ParameterUsed - 1 ; Count > = 0 ; Count - - ) /* free stack space used by parameters */
2009-02-01 06:31:18 -05:00
VariableStackPop ( Parser , Parameter [ Count ] ) ;
2008-12-23 21:30:29 -05:00
}
}
2008-12-18 19:22:52 -05:00
/* parse a single value */
2009-02-01 06:31:18 -05:00
int ParseValue ( struct ParseState * Parser , struct Value * * Result , int ResultOnHeap , int RunIt )
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 ) ;
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-01 06:31:18 -05:00
* Result = VariableAllocValueAndCopy ( Parser , LexValue , ResultOnHeap ) ;
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-01 06:31:18 -05:00
IntValue = ParseIntExpression ( Parser , RunIt ) ;
2008-12-20 22:46:32 -05:00
if ( RunIt )
2008-11-21 21:56:08 -05:00
{
2009-02-01 06:31:18 -05:00
* Result = VariableAllocValueFromType ( Parser , & 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-02-01 06:31:18 -05:00
if ( ! ParseExpression ( Parser , Result , ResultOnHeap , RunIt ) )
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 :
case TokenAmpersand :
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " not implemented " ) ;
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-02 06:08:36 -05:00
ParseFunctionCall ( Parser , 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 ;
2009-02-02 06:08:36 -05:00
VariableGet ( Parser , LexValue - > Val - > String , & IdentValue ) ;
2009-01-26 03:57:32 -05:00
if ( IdentValue - > Typ - > Base = = TypeMacro )
2009-01-04 23:28:54 -05:00
{
2009-02-01 06:31:18 -05:00
struct ParseState MacroLexer = IdentValue - > Val - > Parser ;
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-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad variable type " ) ;
2009-01-03 23:08:49 -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 ;
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-02-01 06:31:18 -05:00
struct Value * ParsePushFP ( struct ParseState * Parser , int ResultOnHeap , double NewFP )
2009-01-26 03:57:32 -05:00
{
2009-02-01 06:31:18 -05:00
struct Value * Val = VariableAllocValueFromType ( Parser , & FPType , ResultOnHeap ) ;
2009-01-26 03:57:32 -05:00
Val - > Val - > FP = NewFP ;
return Val ;
}
2009-02-01 06:31:18 -05:00
struct Value * ParsePushInt ( struct ParseState * Parser , int ResultOnHeap , int NewInt )
2009-01-26 03:57:32 -05:00
{
2009-02-01 06:31:18 -05:00
struct Value * Val = VariableAllocValueFromType ( Parser , & IntType , ResultOnHeap ) ;
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-01 06:31:18 -05:00
int ParseExpression ( struct ParseState * Parser , 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-02-01 06:31:18 -05:00
if ( ! ParseValue ( Parser , & TotalValue , ResultOnHeap , RunIt ) )
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 :
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 :
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ;
2008-11-21 21:56:08 -05:00
break ;
2008-12-20 05:24:34 -05:00
case TokenAssign : case TokenAddAssign : case TokenSubtractAssign :
2009-02-01 06:31:18 -05:00
LexGetToken ( Parser , NULL , TRUE ) ;
if ( ! ParseExpression ( Parser , & CurrentValue , ResultOnHeap , RunIt ) )
ProgramFail ( Parser , " expression expected " ) ;
2008-12-20 05:24:34 -05:00
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 )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " can't assign " ) ;
2008-12-20 22:46:32 -05:00
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-02-01 06:31:18 -05:00
VariableStackPop ( Parser , 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-02-01 06:31:18 -05:00
if ( ! ParseValue ( Parser , & 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
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-01 06:31:18 -05:00
case TokenPlus : TotalValue = ParsePushFP ( Parser , ResultOnHeap , FPTotal + FPCurrent ) ; break ;
case TokenMinus : TotalValue = ParsePushFP ( Parser , ResultOnHeap , FPTotal - FPCurrent ) ; break ;
case TokenAsterisk : TotalValue = ParsePushFP ( Parser , ResultOnHeap , FPTotal * FPCurrent ) ; break ;
case TokenSlash : TotalValue = ParsePushFP ( Parser , ResultOnHeap , FPTotal / FPCurrent ) ; break ;
case TokenEquality : TotalValue = ParsePushInt ( Parser , ResultOnHeap , FPTotal = = FPCurrent ) ; break ;
case TokenLessThan : TotalValue = ParsePushInt ( Parser , ResultOnHeap , FPTotal < FPCurrent ) ; break ;
case TokenGreaterThan : TotalValue = ParsePushInt ( Parser , ResultOnHeap , FPTotal > FPCurrent ) ; break ;
case TokenLessEqual : TotalValue = ParsePushInt ( Parser , ResultOnHeap , FPTotal < = FPCurrent ) ; break ;
case TokenGreaterEqual : TotalValue = ParsePushInt ( Parser , ResultOnHeap , FPTotal > = FPCurrent ) ; break ;
case TokenLogicalAnd : case TokenLogicalOr : case TokenAmpersand : case TokenArithmeticOr : case TokenArithmeticExor : ProgramFail ( Parser , " bad type for operator " ) ; break ;
case TokenDot : ProgramFail ( Parser , " operator not supported " ) ; break ;
2008-12-26 21:25:49 -05:00
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 )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " bad operand types " ) ;
2008-12-26 21:25:49 -05:00
/* 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 ;
2009-02-01 06:31:18 -05:00
case TokenDot : ProgramFail ( Parser , " operator not supported " ) ; break ;
2008-12-26 21:25:49 -05:00
default : break ;
}
2008-12-20 22:46:32 -05:00
}
2009-02-01 06:31:18 -05:00
VariableStackPop ( Parser , CurrentValue ) ;
2009-01-26 03:57:32 -05:00
* 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-02-01 06:31:18 -05:00
int ParseIntExpression ( struct ParseState * Parser , int RunIt )
2008-12-18 19:22:52 -05:00
{
2009-01-26 03:57:32 -05:00
struct Value * Val ;
int Result = 0 ;
2009-02-01 06:31:18 -05:00
if ( ! ParseExpression ( Parser , & Val , FALSE , RunIt ) )
ProgramFail ( Parser , " expression expected " ) ;
2008-12-18 19:22:52 -05:00
2009-01-26 03:57:32 -05:00
if ( RunIt )
{
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
2008-12-20 20:36:09 -05:00
/* parse a function definition and store it for later */
2009-02-02 06:08:36 -05:00
struct Value * ParseFunctionDefinition ( struct ParseState * Parser , struct ValueType * ReturnType , const char * Identifier , int IsPrototype )
2008-12-20 06:46:21 -05:00
{
2009-02-02 06:08:36 -05:00
struct ValueType * ParamType ;
const char * ParamIdentifier ;
2009-02-01 06:31:18 -05:00
enum LexToken Token ;
struct Value * FuncValue ;
struct ParseState ParamParser ;
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-02 06:08:36 -05:00
FuncValue = VariableAllocValueAndData ( Parser , sizeof ( struct FuncDef ) + sizeof ( struct ValueType * ) * ParamCount + sizeof ( const char * ) * ParamCount , 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 ;
FuncValue - > Val - > FuncDef . ParamType = ( void * ) FuncValue - > Val + sizeof ( struct FuncDef ) ;
FuncValue - > Val - > FuncDef . ParamName = ( void * ) FuncValue - > Val - > FuncDef . ParamType + sizeof ( struct ValueType * ) * ParamCount ;
FuncValue - > Val - > FuncDef . Body = * Parser ;
for ( ParamCount = 0 ; ParamCount < FuncValue - > Val - > FuncDef . NumParams ; ParamCount + + )
{ /* harvest the parameters into the function definition */
2009-02-02 06:08:36 -05:00
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-03 05:39:48 -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 " ) ;
if ( ! ParseStatement ( Parser , FALSE ) )
ProgramFail ( Parser , " function definition expected " ) ;
}
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-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-01 06:31:18 -05:00
struct Value * MacroValue = VariableAllocValueAndData ( Parser , sizeof ( struct ParseState ) , 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-01-04 23:28:54 -05:00
2009-02-02 06:08:36 -05:00
if ( ! TableSet ( & GlobalTable , MacroName - > Val - > String , MacroValue ) )
ProgramFail ( Parser , " '%s' is already defined " , & MacroName - > Val - > String ) ;
2009-01-04 23:28:54 -05:00
}
2009-02-01 06:31:18 -05:00
void ParseFor ( struct ParseState * Parser , int RunIt )
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-01 06:31:18 -05:00
if ( ! ParseStatement ( Parser , RunIt ) )
ProgramFail ( Parser , " statement expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
PreConditional = * Parser ;
Condition = ParseIntExpression ( Parser , RunIt ) ;
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-01 06:31:18 -05:00
PreIncrement = * Parser ;
ParseStatement ( 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-01 06:31:18 -05:00
PreStatement = * Parser ;
if ( ! ParseStatement ( Parser , RunIt & & Condition ) )
ProgramFail ( Parser , " statement expected " ) ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
After = * Parser ;
2009-01-03 23:08:49 -05:00
2009-01-26 03:57:32 -05:00
while ( Condition & & RunIt )
2009-01-03 23:08:49 -05:00
{
2009-02-01 06:31:18 -05:00
* Parser = PreIncrement ;
ParseStatement ( Parser , TRUE ) ;
2009-01-03 23:08:49 -05:00
2009-02-01 06:31:18 -05:00
* Parser = PreConditional ;
Condition = ParseIntExpression ( Parser , 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
{
2009-02-01 06:31:18 -05:00
* Parser = PreStatement ;
ParseStatement ( Parser , TRUE ) ;
2009-01-03 23:08:49 -05:00
}
}
2009-02-01 06:31:18 -05:00
* Parser = After ;
2009-01-03 23:08:49 -05:00
}
2008-12-18 19:22:52 -05:00
/* parse a statement */
2009-02-01 06:31:18 -05:00
int ParseStatement ( struct ParseState * Parser , int RunIt )
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 ;
2009-02-02 06:08:36 -05:00
const char * Identifier ;
2009-01-21 04:02:05 -05:00
struct ValueType * Typ ;
2009-02-01 06:31:18 -05:00
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 ;
ParseExpression ( Parser , & CValue , FALSE , RunIt ) ;
if ( RunIt ) VariableStackPop ( Parser , CValue ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenLeftBrace :
2009-02-01 06:31:18 -05:00
while ( ParseStatement ( Parser , RunIt ) )
2008-11-21 21:56:08 -05:00
{ }
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , TRUE ) ! = TokenRightBrace )
ProgramFail ( Parser , " '}' expected " ) ;
2008-11-21 21:56:08 -05:00
break ;
case TokenIf :
2009-02-01 06:31:18 -05:00
Condition = ParseIntExpression ( Parser , RunIt ) ;
2008-11-21 21:56:08 -05:00
2009-02-01 06:31:18 -05:00
if ( ! ParseStatement ( Parser , RunIt & & Condition ) )
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 ) ;
if ( ! ParseStatement ( Parser , RunIt & & ! Condition ) )
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-01 06:31:18 -05:00
struct ParseState PreConditional = * Parser ;
2008-11-21 21:56:08 -05:00
do
{
2009-02-01 06:31:18 -05:00
* Parser = PreConditional ;
Condition = ParseIntExpression ( Parser , RunIt ) ;
2008-11-21 21:56:08 -05:00
2009-02-01 06:31:18 -05:00
if ( ! ParseStatement ( Parser , RunIt & & Condition ) )
ProgramFail ( Parser , " statement expected " ) ;
2008-11-21 21:56:08 -05:00
2009-01-26 03:57:32 -05:00
} while ( RunIt & & Condition ) ;
2008-11-21 21:56:08 -05:00
}
break ;
case TokenDo :
{
2009-02-01 06:31:18 -05:00
struct ParseState PreStatement = * Parser ;
2008-11-21 21:56:08 -05:00
do
{
2009-02-01 06:31:18 -05:00
* Parser = PreStatement ;
if ( ! ParseStatement ( Parser , RunIt ) )
ProgramFail ( Parser , " statement expected " ) ;
2008-11-21 21:56:08 -05:00
2009-02-01 06:31:18 -05:00
Condition = ParseIntExpression ( Parser , 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-02-01 06:31:18 -05:00
ParseFor ( Parser , 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 :
2009-02-01 06:31:18 -05:00
* Parser = PreState ;
TypeParse ( Parser , & Typ , & Identifier ) ;
2009-02-02 06:08:36 -05:00
if ( Identifier = = StrEmpty )
2009-02-01 06:31:18 -05:00
ProgramFail ( Parser , " identifier expected " ) ;
2008-11-21 21:56:08 -05:00
2008-12-20 06:46:21 -05:00
/* handle function definitions */
2009-02-01 06:31:18 -05:00
if ( LexGetToken ( Parser , NULL , FALSE ) = = TokenOpenBracket )
2009-02-02 06:08:36 -05:00
ParseFunctionDefinition ( Parser , Typ , Identifier , FALSE ) ;
2008-12-20 06:46:21 -05:00
else
2009-02-02 06:08:36 -05:00
VariableDefine ( Parser , Identifier , VariableAllocValueFromType ( Parser , 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-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-02 06:08:36 -05:00
ScanFile ( LexerValue - > Val - > String ) ;
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 :
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-02-01 06:31:18 -05:00
ProgramFail ( Parser , " not implemented yet " ) ;
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?
LexInitParser ( & Parser , Tokens , FileName , 1 ) ;
2009-02-01 06:31:18 -05:00
while ( ParseStatement ( & Parser , RunIt ) )
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
}