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)
|
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
18
lex.c
|
@ -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
84
parse.c
|
@ -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
25
picoc.h
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue