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:
zik.saleeba 2010-07-08 04:52:05 +00:00
parent e977f325ae
commit 7c754bad48
5 changed files with 102 additions and 31 deletions

View file

@ -1110,7 +1110,7 @@ int ExpressionParse(struct ParseState *Parser, struct Value **Result)
if (VariableValue->Typ->Base == TypeMacro) if (VariableValue->Typ->Base == TypeMacro)
{ {
/* evaluate a macro as a kind of simple subroutine */ /* 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; struct Value *MacroResult;
if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction) if (!ExpressionParse(&MacroParser, &MacroResult) || LexGetToken(&MacroParser, NULL, FALSE) != TokenEndOfFunction)

18
lex.c
View file

@ -211,8 +211,12 @@ enum LexToken LexGetWord(struct LexState *Lexer, struct Value *Value)
Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos); Value->Val->Identifier = TableStrRegister2(StartPos, Lexer->Pos - StartPos);
Token = LexCheckReservedWord(Value->Val->Identifier); Token = LexCheckReservedWord(Value->Val->Identifier);
if (Token == TokenHashInclude) switch (Token)
Lexer->ScanningHashInclude = TRUE; {
case TokenHashInclude: Lexer->Mode = LexModeHashInclude; break;
case TokenHashDefine: Lexer->Mode = LexModeHashDefine; break;
default: break;
}
if (Token != TokenNone) if (Token != TokenNone)
return Token; return Token;
@ -373,12 +377,14 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
{ {
Lexer->Line++; Lexer->Line++;
Lexer->Pos++; Lexer->Pos++;
Lexer->ScanningHashInclude = FALSE; Lexer->Mode = LexModeNormal;
#ifdef FANCY_ERROR_REPORTING #ifdef FANCY_ERROR_REPORTING
Lexer->CharacterPos = 0; Lexer->CharacterPos = 0;
#endif #endif
return TokenEndOfLine; return TokenEndOfLine;
} }
else if (Lexer->Mode == LexModeHashDefine)
Lexer->Mode = LexModeNormal;
LEXER_INC(Lexer); LEXER_INC(Lexer);
} }
@ -399,7 +405,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value)
{ {
case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break; case '"': GotToken = LexGetStringConstant(Lexer, *Value, '"'); break;
case '\'': GotToken = LexGetCharacterConstant(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 ')': GotToken = TokenCloseBracket; break;
case '=': NEXTIS('=', TokenEqual, TokenAssign); break; case '=': NEXTIS('=', TokenEqual, TokenAssign); break;
case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); 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 '*': NEXTIS('=', TokenMultiplyAssign, TokenAsterisk); break;
case '/': if (NextChar == '/' || NextChar == '*') LexSkipComment(Lexer, NextChar); else NEXTIS('=', TokenDivideAssign, TokenSlash); break; case '/': if (NextChar == '/' || NextChar == '*') LexSkipComment(Lexer, NextChar); else NEXTIS('=', TokenDivideAssign, TokenSlash); break;
case '%': NEXTIS('=', TokenModulusAssign, TokenModulus); 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 '>': NEXTIS3PLUS('=', TokenGreaterEqual, '>', TokenShiftRight, '=', TokenShiftRightAssign, TokenGreaterThan); break;
case ';': GotToken = TokenSemicolon; break; case ';': GotToken = TokenSemicolon; break;
case '&': NEXTIS3('=', TokenArithmeticAndAssign, '&', TokenLogicalAnd, TokenAmpersand); 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.End = Source + SourceLen;
Lexer.Line = 1; Lexer.Line = 1;
Lexer.FileName = FileName; Lexer.FileName = FileName;
Lexer.ScanningHashInclude = FALSE; Lexer.Mode = LexModeNormal;
#ifdef FANCY_ERROR_REPORTING #ifdef FANCY_ERROR_REPORTING
Lexer.CharacterPos = 1; Lexer.CharacterPos = 1;
Lexer.SourceText = Source; Lexer.SourceText = Source;

84
parse.c
View file

@ -26,24 +26,12 @@ enum ParseResult ParseStatementMaybeRun(struct ParseState *Parser, int Condition
return ParseStatement(Parser, CheckTrailingSemicolon); return ParseStatement(Parser, CheckTrailingSemicolon);
} }
/* parse a function definition and store it for later */ /* count the number of parameters to a function or macro */
struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier) 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; int ParamCount = 0;
if (TopStackFrame != NULL) enum LexToken Token = LexGetToken(Parser, NULL, TRUE);
ProgramFail(Parser, "nested function definitions are not allowed");
LexGetToken(Parser, NULL, TRUE); /* open bracket */
ParamParser = *Parser;
Token = LexGetToken(Parser, NULL, TRUE);
if (Token != TokenCloseBracket && Token != TokenEOF) if (Token != TokenCloseBracket && Token != TokenEOF)
{ {
/* count the number of parameters */ /* count the number of parameters */
@ -54,6 +42,28 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp
ParamCount++; 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) if (ParamCount > PARAMETER_MAX)
ProgramFail(Parser, "too many parameters"); ProgramFail(Parser, "too many parameters");
@ -232,15 +242,53 @@ int ParseDeclaration(struct ParseState *Parser, enum LexToken Token)
void ParseMacroDefinition(struct ParseState *Parser) void ParseMacroDefinition(struct ParseState *Parser)
{ {
struct Value *MacroName; 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) if (LexGetToken(Parser, &MacroName, TRUE) != TokenIdentifier)
ProgramFail(Parser, "identifier expected"); 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; MacroValue->Typ = &MacroType;
LexToEndOfLine(Parser); 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)) if (!TableSet(&GlobalTable, MacroName->Val->Identifier, MacroValue))
ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier); ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->Identifier);

25
picoc.h
View file

@ -76,7 +76,8 @@ enum LexToken
/* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef, /* 0x3c */ TokenLongType, TokenSignedType, TokenShortType, TokenStructType, TokenUnionType, TokenUnsignedType, TokenTypedef,
/* 0x43 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn, /* 0x43 */ TokenContinue, TokenDo, TokenElse, TokenFor, TokenIf, TokenWhile, TokenBreak, TokenSwitch, TokenCase, TokenDefault, TokenReturn,
/* 0x4e */ TokenHashDefine, TokenHashInclude, TokenNew, TokenDelete, /* 0x4e */ TokenHashDefine, TokenHashInclude, TokenNew, TokenDelete,
/* 0x52 */ TokenEOF, TokenEndOfLine, TokenEndOfFunction /* 0x52 */ TokenOpenMacroBracket,
/* 0x53 */ TokenEOF, TokenEndOfLine, TokenEndOfFunction
}; };
/* used in dynamic memory allocation */ /* used in dynamic memory allocation */
@ -161,6 +162,14 @@ struct FuncDef
struct ParseState Body; /* lexical tokens of the function body if not intrinsic */ 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 */ /* values */
union AnyValue union AnyValue
{ {
@ -173,13 +182,14 @@ union AnyValue
unsigned long UnsignedLongInteger; unsigned long UnsignedLongInteger;
char *Identifier; char *Identifier;
char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */ char ArrayMem[2]; /* placeholder for where the data starts, doesn't point to it */
struct ParseState Parser; /* struct ParseState Parser; */
struct ValueType *Typ; struct ValueType *Typ;
struct FuncDef FuncDef; struct FuncDef FuncDef;
struct MacroDef MacroDef;
#ifndef NO_FP #ifndef NO_FP
double FP; double FP;
#endif #endif
void *Pointer; /* unsafe native pointers */ void *Pointer; /* unsafe native pointers */
}; };
struct Value struct Value
@ -228,13 +238,20 @@ struct StackFrame
}; };
/* lexer state */ /* lexer state */
enum LexMode
{
LexModeNormal,
LexModeHashInclude,
LexModeHashDefine
};
struct LexState struct LexState
{ {
const char *Pos; const char *Pos;
const char *End; const char *End;
const char *FileName; const char *FileName;
int Line; int Line;
int ScanningHashInclude; enum LexMode Mode;
#ifdef FANCY_ERROR_REPORTING #ifdef FANCY_ERROR_REPORTING
int CharacterPos; int CharacterPos;
const char *SourceText; const char *SourceText;

View file

@ -34,7 +34,7 @@ void VariableFree(struct Value *Val)
/* free macro bodies */ /* free macro bodies */
if (Val->Typ == &MacroType) if (Val->Typ == &MacroType)
HeapFreeMem((void *)Val->Val->Parser.Pos); HeapFreeMem((void *)Val->Val->MacroDef.Body.Pos);
/* free the value */ /* free the value */
HeapFreeMem(Val); HeapFreeMem(Val);