Can now parse parameterised macros. Can't evaluate them yet though.
git-svn-id: http://picoc.googlecode.com/svn/trunk@462 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
e977f325ae
commit
7c754bad48
|
@ -1110,7 +1110,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
|
|||
if (VariableValue->Typ->Base == TypeMacro)
|
||||
{
|
||||
/* evaluate a macro as a kind of simple subroutine */
|
||||
struct ParseState MacroParser = VariableValue->Val->Parser;
|
||||
struct ParseState MacroParser = VariableValue->Val->MacroDef.Body;
|
||||
struct Value *MacroResult;
|
||||
|
||||
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)
|
||||
|
|
18
lex.c
18
lex.c
|
@ -211,8 +211,12 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
|
|||
Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos);
|
||||
|
||||
Token = LexCheckReservedWord(Value->Val->Identifier);
|
||||
if (Token == TokenHashInclude)
|
||||
Lexer->ScanningHashInclude = TRUE;
|
||||
switch (Token)
|
||||
{
|
||||
case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break;
|
||||
case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (Token != TokenNone)
|
||||
return Token;
|
||||
|
@ -373,12 +377,14 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
|
|||
{
|
||||
Lexer->Line++;
|
||||
Lexer->Pos++;
|
||||
Lexer->ScanningHashInclude = FALSE;
|
||||
Lexer->Mode = LexModeNormal;
|
||||
#ifdef FANCY_ERROR_REPORTING
|
||||
Lexer->CharacterPos = 0;
|
||||
#endif
|
||||
return TokenEndOfLine;
|
||||
}
|
||||
else if (Lexer->Mode == LexModeHashDefine)
|
||||
Lexer->Mode = LexModeNormal;
|
||||
|
||||
LEXER_INC(Lexer);
|
||||
}
|
||||
|
@ -399,7 +405,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
|
|||
{
|
||||
case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break;
|
||||
case '\'': GotToken = LexGetCharacterConstant(Lexer, *Value); break;
|
||||
case '(': GotToken = TokenOpenBracket; break;
|
||||
case '(': if (Lexer->Mode == LexModeHashDefine) { GotToken = TokenOpenMacroBracket; Lexer->Mode = LexModeNormal; } else GotToken = TokenOpenBracket; break;
|
||||
case ')': GotToken = TokenCloseBracket; break;
|
||||
case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
|
||||
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); break;
|
||||
|
@ -407,7 +413,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
|
|||
case '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break;
|
||||
case '/': if (NextChar == '/' || NextChar == '*') LexSkipComment(Lexer, NextChar); else NEXTIS('=', TokenDivideAssign, TokenSlash); break;
|
||||
case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); break;
|
||||
case '<': if (Lexer->ScanningHashInclude) GotToken = LexGetStringConstant(Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break;
|
||||
case '<': if (Lexer->Mode == LexModeHashInclude) GotToken = LexGetStringConstant(Lexer, *Value, '>'); else { NEXTIS3PLUS('=', TokenLessEqual, '<', TokenShiftLeft, '=', TokenShiftLeftAssign, TokenLessThan); } break;
|
||||
case '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break;
|
||||
case ';': GotToken = TokenSemicolon; break;
|
||||
case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); break;
|
||||
|
@ -528,7 +534,7 @@ void *LexAnalyse(const char *FileName, const char *Source, int SourceLen, int *T
|
|||
Lexer.End = Source + SourceLen;
|
||||
Lexer.Line = 1;
|
||||
Lexer.FileName = FileName;
|
||||
Lexer.ScanningHashInclude = FALSE;
|
||||
Lexer.Mode = LexModeNormal;
|
||||
#ifdef FANCY_ERROR_REPORTING
|
||||
Lexer.CharacterPos = 1;
|
||||
Lexer.SourceText = Source;
|
||||
|
|
86
parse.c
86
parse.c
|
@ -26,24 +26,12 @@ enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser, int Condition
|
|||
return ParseStatement(Parser, CheckTrailingSemicolon);
|
||||
}
|
||||
|
||||
/* parse a function definition and store it for later */
|
||||
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier)
|
||||
/* count the number of parameters to a function or macro */
|
||||
int ParseCountParams(struct ParseState *Parser)
|
||||
{
|
||||
struct ValueType *ParamType;
|
||||
char *ParamIdentifier;
|
||||
enum LexToken Token;
|
||||
struct Value *FuncValue;
|
||||
struct Value *OldFuncValue;
|
||||
struct ParseState ParamParser;
|
||||
struct ParseState FuncBody;
|
||||
int ParamCount = 0;
|
||||
|
||||
if (TopStackFrame != NULL)
|
||||
ProgramFail(Parser, "nested function definitions are not allowed");
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
||||
ParamParser = *Parser;
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token != TokenCloseBracket && Token != TokenEOF)
|
||||
{
|
||||
/* count the number of parameters */
|
||||
|
@ -54,6 +42,28 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp
|
|||
ParamCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return ParamCount;
|
||||
}
|
||||
|
||||
/* parse a function definition and store it for later */
|
||||
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier)
|
||||
{
|
||||
struct ValueType *ParamType;
|
||||
char *ParamIdentifier;
|
||||
enum LexToken Token;
|
||||
struct ParseState ParamParser;
|
||||
struct Value *FuncValue;
|
||||
struct Value *OldFuncValue;
|
||||
struct ParseState FuncBody;
|
||||
int ParamCount = 0;
|
||||
|
||||
if (TopStackFrame != NULL)
|
||||
ProgramFail(Parser, "nested function definitions are not allowed");
|
||||
|
||||
LexGetToken(Parser, NULL, TRUE); /* open bracket */
|
||||
ParamParser = *Parser;
|
||||
ParamCount = ParseCountParams(Parser);
|
||||
if (ParamCount > PARAMETER_MAX)
|
||||
ProgramFail(Parser, "too many parameters");
|
||||
|
||||
|
@ -232,15 +242,53 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
|
|||
void ParseMacroDefinition(struct ParseState *Parser)
|
||||
{
|
||||
struct Value *MacroName;
|
||||
struct Value *MacroValue = VariableAllocValueAndData(Parser, sizeof(struct ParseState), FALSE, NULL, TRUE);
|
||||
struct Value *ParamName;
|
||||
struct Value *MacroValue;
|
||||
|
||||
if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
|
||||
ProgramFail(Parser, "identifier expected");
|
||||
|
||||
MacroValue->Val->Parser = *Parser;
|
||||
if (LexGetToken(Parser, NULL, FALSE) == TokenOpenMacroBracket)
|
||||
{
|
||||
/* it's a parameterised macro, read the parameters */
|
||||
enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
|
||||
struct ParseState ParamParser = *Parser;
|
||||
int NumParams = ParseCountParams(&ParamParser);
|
||||
int ParamCount = 0;
|
||||
|
||||
MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef) + sizeof(const char *) * NumParams, FALSE, NULL, TRUE);
|
||||
MacroValue->Val->MacroDef.NumParams = NumParams;
|
||||
Token = LexGetToken(Parser, &ParamName, TRUE);
|
||||
|
||||
while (Token == TokenIdentifier)
|
||||
{
|
||||
/* store a parameter name */
|
||||
MacroValue->Val->MacroDef.ParamName[ParamCount++] = ParamName->Val->Identifier;
|
||||
|
||||
/* get the trailing comma */
|
||||
Token = LexGetToken(Parser, NULL, TRUE);
|
||||
if (Token == TokenComma)
|
||||
Token = LexGetToken(Parser, &ParamName, TRUE);
|
||||
|
||||
else if (Token != TokenCloseBracket)
|
||||
ProgramFail(Parser, "comma expected");
|
||||
}
|
||||
|
||||
if (Token != TokenCloseBracket)
|
||||
ProgramFail(Parser, "close bracket expected");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allocate a simple unparameterised macro */
|
||||
MacroValue = VariableAllocValueAndData(Parser, sizeof(struct MacroDef), FALSE, NULL, TRUE);
|
||||
MacroValue->Val->MacroDef.NumParams = 0;
|
||||
}
|
||||
|
||||
/* copy the body of the macro to execute later */
|
||||
MacroValue->Val->MacroDef.Body = *Parser;
|
||||
MacroValue->Typ = &MacroType;
|
||||
LexToEndOfLine(Parser);
|
||||
MacroValue->Val->Parser.Pos = LexCopyTokens(&MacroValue->Val->Parser, 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);
|
||||
|
|
25
picoc.h
25
picoc.h
|
@ -76,7 +76,8 @@ enum LexToken
|
|||
/* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef,
|
||||
/* 0x43 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn,
|
||||
/* 0x4e */ TokenHashDefine, TokenHashInclude, TokenNew, TokenDelete,
|
||||
/* 0x52 */ TokenEOF, TokenEndOfLine, TokenEndOfFunction
|
||||
/* 0x52 */ TokenOpenMacroBracket,
|
||||
/* 0x53 */ TokenEOF, TokenEndOfLine, TokenEndOfFunction
|
||||
};
|
||||
|
||||
/* used in dynamic memory allocation */
|
||||
|
@ -161,6 +162,14 @@ struct FuncDef
|
|||
struct ParseState Body; /* lexical tokens of the function body if not intrinsic */
|
||||
};
|
||||
|
||||
/* macro definition */
|
||||
struct MacroDef
|
||||
{
|
||||
int NumParams; /* the number of parameters */
|
||||
char **ParamName; /* array of parameter names */
|
||||
struct ParseState Body; /* lexical tokens of the function body if not intrinsic */
|
||||
};
|
||||
|
||||
/* values */
|
||||
union AnyValue
|
||||
{
|
||||
|
@ -173,13 +182,14 @@ union AnyValue
|
|||
unsigned long UnsignedLongInteger;
|
||||
char *Identifier;
|
||||
char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */
|
||||
struct ParseState Parser;
|
||||
/* struct ParseState Parser; */
|
||||
struct ValueType *Typ;
|
||||
struct FuncDef FuncDef;
|
||||
struct MacroDef MacroDef;
|
||||
#ifndef NO_FP
|
||||
double FP;
|
||||
#endif
|
||||
void *Pointer; /* unsafe native pointers */
|
||||
void *Pointer; /* unsafe native pointers */
|
||||
};
|
||||
|
||||
struct Value
|
||||
|
@ -228,13 +238,20 @@ struct StackFrame
|
|||
};
|
||||
|
||||
/* lexer state */
|
||||
enum LexMode
|
||||
{
|
||||
LexModeNormal,
|
||||
LexModeHashInclude,
|
||||
LexModeHashDefine
|
||||
};
|
||||
|
||||
struct LexState
|
||||
{
|
||||
const char *Pos;
|
||||
const char *End;
|
||||
const char *FileName;
|
||||
int Line;
|
||||
int ScanningHashInclude;
|
||||
enum LexMode Mode;
|
||||
#ifdef FANCY_ERROR_REPORTING
|
||||
int CharacterPos;
|
||||
const char *SourceText;
|
||||
|
|
|
@ -34,7 +34,7 @@ void VariableFree(struct Value *Val)
|
|||
|
||||
/* free macro bodies */
|
||||
if (Val->Typ == &MacroType)
|
||||
HeapFreeMem((void *)Val->Val->Parser.Pos);
|
||||
HeapFreeMem((void *)Val->Val->MacroDef.Body.Pos);
|
||||
|
||||
/* free the value */
|
||||
HeapFreeMem(Val);
|
||||
|
|
Loading…
Reference in a new issue