Completed parameterised macros
git-svn-id: http://picoc.googlecode.com/svn/trunk@463 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
7c754bad48
commit
145a99a7b1
90
expression.c
90
expression.c
|
@ -1099,7 +1099,9 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
ProgramFail(Parser, "identifier not expected here");
|
||||
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenBracket)
|
||||
{
|
||||
ExpressionParseFunctionCall(Parser, &StackTop, LexValue->Val->Identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
|
@ -1113,6 +1115,9 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
struct ParseState MacroParser = VariableValue->Val->MacroDef.Body;
|
||||
struct Value *MacroResult;
|
||||
|
||||
if (VariableValue->Val->MacroDef.NumParams != 0)
|
||||
ProgramFail(&MacroParser, "macro arguments missing");
|
||||
|
||||
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
||||
ProgramFail(&MacroParser, "expression expected");
|
||||
|
||||
|
@ -1195,6 +1200,83 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
}
|
||||
|
||||
|
||||
/* do a parameterised macro call */
|
||||
void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *MacroName, struct MacroDef *MDef)
|
||||
{
|
||||
struct Value *ReturnValue = NULL;
|
||||
struct Value *Param;
|
||||
struct Value **ParamArray = NULL;
|
||||
int ArgCount;
|
||||
enum LexToken Token;
|
||||
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
/* create a stack frame for this macro */
|
||||
ExpressionStackPushValueByType(Parser, StackTop, &FPType); /* largest return type there is */
|
||||
ReturnValue = (*StackTop)->Val;
|
||||
HeapPushStackFrame();
|
||||
ParamArray = HeapAllocStack(sizeof(struct Value *) * MDef->NumParams);
|
||||
if (ParamArray == NULL)
|
||||
ProgramFail(Parser, "out of memory");
|
||||
}
|
||||
else
|
||||
ExpressionPushInt(Parser, StackTop, 0);
|
||||
|
||||
/* parse arguments */
|
||||
ArgCount = 0;
|
||||
do {
|
||||
if (ExpressionParse(Parser, &Param))
|
||||
{
|
||||
if (Parser->Mode == RunModeRun)
|
||||
{
|
||||
if (ArgCount < MDef->NumParams)
|
||||
ParamArray[ArgCount] = Param;
|
||||
else
|
||||
ProgramFail(Parser, "too many arguments to %s()", MacroName);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* evaluate the macro */
|
||||
struct ParseState MacroParser;
|
||||
int Count;
|
||||
struct Value *EvalValue;
|
||||
|
||||
if (ArgCount < MDef->NumParams)
|
||||
ProgramFail(Parser, "not enough arguments to '%s'", MacroName);
|
||||
|
||||
if (MDef->Body.Pos == NULL)
|
||||
ProgramFail(Parser, "'%s' is undefined", MacroName);
|
||||
|
||||
memcpy((void *)&MacroParser, (void *)&MDef->Body, sizeof(struct ParseState));
|
||||
VariableStackFrameAdd(Parser, 0);
|
||||
TopStackFrame->NumParams = ArgCount;
|
||||
TopStackFrame->ReturnValue = ReturnValue;
|
||||
for (Count = 0; Count < MDef->NumParams; Count++)
|
||||
VariableDefine(Parser, MDef->ParamName[Count], ParamArray[Count], NULL, TRUE);
|
||||
|
||||
ExpressionParse(&MacroParser, &EvalValue);
|
||||
ExpressionAssign(Parser, ReturnValue, EvalValue, TRUE, MacroName, 0, FALSE);
|
||||
VariableStackFramePop(Parser);
|
||||
HeapPopStackFrame();
|
||||
}
|
||||
}
|
||||
|
||||
/* do a function call */
|
||||
void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionStack **StackTop, const char *FuncName)
|
||||
{
|
||||
|
@ -1209,6 +1291,14 @@ void ExpressionParseFunctionCall(struct ParseState *Parser, struct ExpressionSta
|
|||
{
|
||||
/* get the function definition */
|
||||
VariableGet(Parser, FuncName, &FuncValue);
|
||||
|
||||
if (FuncValue->Typ->Base == TypeMacro)
|
||||
{
|
||||
/* this is actually a macro, not a function */
|
||||
ExpressionParseMacroCall(Parser, StackTop, FuncName, &FuncValue->Val->MacroDef);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FuncValue->Typ->Base != TypeFunction)
|
||||
ProgramFail(Parser, "%t is not a function - can't call", FuncValue->Typ);
|
||||
|
||||
|
|
10
lex.c
10
lex.c
|
@ -221,6 +221,9 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
|
|||
if (Token != TokenNone)
|
||||
return Token;
|
||||
|
||||
if (Lexer->Mode == LexModeHashDefineSpace)
|
||||
Lexer->Mode = LexModeHashDefineSpaceIdent;
|
||||
|
||||
return TokenIdentifier;
|
||||
}
|
||||
|
||||
|
@ -383,7 +386,10 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
|
|||
#endif
|
||||
return TokenEndOfLine;
|
||||
}
|
||||
else if (Lexer->Mode == LexModeHashDefine)
|
||||
else if (Lexer->Mode == LexModeHashDefine || Lexer->Mode == LexModeHashDefineSpace)
|
||||
Lexer->Mode = LexModeHashDefineSpace;
|
||||
|
||||
else if (Lexer->Mode == LexModeHashDefineSpaceIdent)
|
||||
Lexer->Mode = LexModeNormal;
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
|
@ -405,7 +411,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
|
|||
{
|
||||
case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break;
|
||||
case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break;
|
||||
case '(': if (Lexer->Mode == LexModeHashDefine) { GotToken = TokenOpenMacroBracket; Lexer->Mode = LexModeNormal; } else GotToken = TokenOpenBracket; break;
|
||||
case '(': if (Lexer->Mode == LexModeHashDefineSpaceIdent) GotToken = TokenOpenMacroBracket; else GotToken = TokenOpenBracket; Lexer->Mode = LexModeNormal; break;
|
||||
case ')': GotToken = TokenCloseBracket; break;
|
||||
case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
|
||||
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break;
|
||||
|
|
9
parse.c
9
parse.c
|
@ -242,12 +242,15 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|||
void ParseMacroDefinition(struct ParseState *Parser)
|
||||
{
|
||||
struct Value *MacroName;
|
||||
char *MacroNameStr;
|
||||
struct Value *ParamName;
|
||||
struct Value *MacroValue;
|
||||
|
||||
if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
|
||||
ProgramFail(Parser, "identifier expected");
|
||||
|
||||
MacroNameStr = MacroName->Val->Identifier;
|
||||
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenMacroBracket)
|
||||
{
|
||||
/* it's a parameterised macro, read the parameters */
|
||||
|
@ -258,6 +261,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
|||
|
||||
MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE);
|
||||
MacroValue->Val->MacroDef.NumParams = NumParams;
|
||||
MacroValue->Val->MacroDef.ParamName = (char **)((char *)MacroValue->Val + sizeof(struct MacroDef));
|
||||
|
||||
Token = LexGetToken(Parser, &ParamName, TRUE);
|
||||
|
||||
while (Token == TokenIdentifier)
|
||||
|
@ -290,8 +295,8 @@ void ParseMacroDefinition(struct ParseState *Parser)
|
|||
LexToEndOfLine(Parser);
|
||||
MacroValue->Val->MacroDef.Body.Pos = LexCopyTokens(&MacroValue->Val->MacroDef.Body, Parser);
|
||||
|
||||
if (!TableSet(&GlobalTable, MacroName->Val->Identifier, MacroValue))
|
||||
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier);
|
||||
if (!TableSet(&GlobalTable, MacroNameStr, MacroValue))
|
||||
ProgramFail(Parser, "'%s' is already defined", MacroNameStr);
|
||||
}
|
||||
|
||||
/* copy where we're at in the parsing */
|
||||
|
|
4
picoc.h
4
picoc.h
|
@ -242,7 +242,9 @@ enum LexMode
|
|||
{
|
||||
LexModeNormal,
|
||||
LexModeHashInclude,
|
||||
LexModeHashDefine
|
||||
LexModeHashDefine,
|
||||
LexModeHashDefineSpace,
|
||||
LexModeHashDefineSpaceIdent
|
||||
};
|
||||
|
||||
struct LexState
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
#define BLOGGS(x) (12*(x))
|
||||
|
||||
printf("%d\n", FRED);
|
||||
//printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3));
|
||||
printf("%d, %d, %d\n", BLOGGS(1), BLOGGS(2), BLOGGS(3));
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
12
|
||||
12, 24, 36
|
||||
|
|
8
tests/33_ternary_op.c
Normal file
8
tests/33_ternary_op.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int Count;
|
||||
|
||||
for (Count = 0; Count < 10; Count++)
|
||||
{
|
||||
printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3));
|
||||
}
|
10
tests/33_ternary_op.expect
Normal file
10
tests/33_ternary_op.expect
Normal file
|
@ -0,0 +1,10 @@
|
|||
0
|
||||
1
|
||||
4
|
||||
9
|
||||
16
|
||||
15
|
||||
18
|
||||
21
|
||||
24
|
||||
27
|
Loading…
Reference in a new issue