Wrote much of the parser
git-svn-id: http://picoc.googlecode.com/svn/trunk@9 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
50c7494508
commit
8cfd9c6013
8
lex.c
8
lex.c
|
@ -161,6 +161,7 @@ enum LexToken LexGetToken(struct LexState *Lexer)
|
||||||
case '}': return TokenRightBrace;
|
case '}': return TokenRightBrace;
|
||||||
case '[': return TokenLeftAngleBracket;
|
case '[': return TokenLeftAngleBracket;
|
||||||
case ']': return TokenRightAngleBracket;
|
case ']': return TokenRightAngleBracket;
|
||||||
|
case '!': return TokenUnaryNot;
|
||||||
case '^': return TokenArithmeticExor;
|
case '^': return TokenArithmeticExor;
|
||||||
case '~': return TokenUnaryExor;
|
case '~': return TokenUnaryExor;
|
||||||
case ',': return TokenComma;
|
case ',': return TokenComma;
|
||||||
|
@ -171,3 +172,10 @@ enum LexToken LexGetToken(struct LexState *Lexer)
|
||||||
return TokenEOF;
|
return TokenEOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* look at the next token without changing the lexer state */
|
||||||
|
enum LexToken LexPeekToken(struct LexState *Lexer)
|
||||||
|
{
|
||||||
|
struct LexToken LocalState = *Lexer;
|
||||||
|
return LexGetToken(&LocalState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
267
parse.c
267
parse.c
|
@ -13,36 +13,259 @@ void ParseInit()
|
||||||
TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE);
|
TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ParseValue(struct LexState *Lexer, struct Value *Result)
|
||||||
|
{
|
||||||
|
struct LexState PreState = *Lexer;
|
||||||
|
enum LexToken Token = LexGetToken(Lexer);
|
||||||
|
|
||||||
|
switch (Token)
|
||||||
|
{
|
||||||
|
case TokenIntegerConstant: case TokenCharacterConstant: case TokenStringConstant:
|
||||||
|
Result->Typ = TypeInt;
|
||||||
|
Result->Val = Lexer->Value;
|
||||||
|
if (Token == TokenStringConstant)
|
||||||
|
Result->Typ = TypeString;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
||||||
|
if (!ParseExpression(Lexer, Result))
|
||||||
|
ProgramFail(Lexer, "invalid expression");
|
||||||
|
|
||||||
|
switch(Token)
|
||||||
|
{
|
||||||
|
case TokenMinus: Result = -Result; break;
|
||||||
|
case TokenUnaryExor: Result = ~Result; break;
|
||||||
|
case TokenUnaryNot: Result = !Result; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenOpenBracket:
|
||||||
|
if (!ParseExpression(Lexer, Result))
|
||||||
|
ProgramFail(Lexer, "invalid expression");
|
||||||
|
|
||||||
|
if (LexGetToken(Lexer) != TokenCloseBracket)
|
||||||
|
ProgramFail(Lexer, "')' expected");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenAsterisk:
|
||||||
|
case TokenAmpersand:
|
||||||
|
ProgramFail(Lexer, "not implemented");
|
||||||
|
|
||||||
|
case TokenIdentifier:
|
||||||
|
ReadVariable(XXX);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*Lexer = PreState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseExpression(struct LexState *Lexer, struct Value *Result)
|
||||||
|
{
|
||||||
|
struct Value CurrentValue;
|
||||||
|
struct Value TotalValue;
|
||||||
|
|
||||||
|
if (!ParseValue(Lexer, &TotalValue))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
enum LexToken Token = LexPeekToken(Lexer);
|
||||||
|
switch (Token)
|
||||||
|
{
|
||||||
|
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
|
||||||
|
case TokenEquality: case TokenLessThan: case TokenGreaterThan:
|
||||||
|
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
|
||||||
|
case TokenLogicalOr: case TokenArithmeticOr: case TokenArithmeticExor:
|
||||||
|
case TokenDot:
|
||||||
|
LexGetToken(Lexer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*Result = TotalValue;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParseValue(Lexer, &CurrentValue))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
||||||
|
ProgramFail(Lexer, "bad operand types");
|
||||||
|
|
||||||
|
switch (Token)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
case TokenDot: ProgramFail(Lexer, "operator not supported"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ParseStatement(struct LexState *Lexer, int RunIt)
|
||||||
|
{
|
||||||
|
int Conditional;
|
||||||
|
struct LexState PreState = *Lexer;
|
||||||
|
enum LexToken Token = LexGetToken(Lexer);
|
||||||
|
|
||||||
|
switch (Token)
|
||||||
|
{
|
||||||
|
case TokenIdentifier:
|
||||||
|
ParseIdentStatement(&PreState, RunIt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenLeftBrace:
|
||||||
|
while (ParseStatement(Lexer, RunIt))
|
||||||
|
{}
|
||||||
|
|
||||||
|
if (LexGetToken(Lexer) != TokenRightBrace)
|
||||||
|
ProgramFail(Lexer, "'}' expected");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenIf:
|
||||||
|
if (!ParseIntExpression(Lexer, &Conditional))
|
||||||
|
ProgramFail(Lexer, "expression expected");
|
||||||
|
|
||||||
|
if (!ParseStatement(Lexer, RunIt && Conditional))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
|
||||||
|
if (LexPeekToken(Lexer) == TokenElse)
|
||||||
|
{
|
||||||
|
LexGetToken(Lexer);
|
||||||
|
if (!ParseStatement(Lexer, RunIt && !Conditional))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenWhile:
|
||||||
|
{
|
||||||
|
struct LexState PreConditional = *Lexer;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*Lexer = PreConditional;
|
||||||
|
if (!ParseIntExpression(Lexer, &Conditional))
|
||||||
|
ProgramFail(Lexer, "expression expected");
|
||||||
|
|
||||||
|
if (!ParseStatement(Lexer, RunIt && Conditional))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
|
||||||
|
} while (Conditional && RunIt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenDo:
|
||||||
|
{
|
||||||
|
struct LexState PreStatement = *Lexer;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*Lexer = PreStatement;
|
||||||
|
if (!ParseStatement(Lexer, RunIt))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
|
||||||
|
if (!ParseIntExpression(Lexer, &Conditional))
|
||||||
|
ProgramFail(Lexer, "expression expected");
|
||||||
|
|
||||||
|
} while (Conditional && RunIt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenFor:
|
||||||
|
{
|
||||||
|
struct LexState PreConditional;
|
||||||
|
struct LexState PreIncrement;
|
||||||
|
struct LexState PreStatement;
|
||||||
|
struct LexState After;
|
||||||
|
|
||||||
|
if (LexGetToken(Lexer) != TokenOpenBracket)
|
||||||
|
ProgramFail(Lexer, "'(' expected");
|
||||||
|
|
||||||
|
if (!ParseStatement(Lexer, RunIt))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
|
||||||
|
PreConditional = *Lexer;
|
||||||
|
if (!ParseIntExpression(Lexer, &Conditional))
|
||||||
|
ProgramFail(Lexer, "expression expected");
|
||||||
|
|
||||||
|
if (LexGetToken(Lexer) != TokenSemicolon)
|
||||||
|
ProgramFail(Lexer, "';' expected");
|
||||||
|
|
||||||
|
PreIncrement = *Lexer;
|
||||||
|
ParseStatement(Lexer, FALSE);
|
||||||
|
|
||||||
|
if (LexGetToken(Lexer) != TokenCloseBracket)
|
||||||
|
ProgramFail(Lexer, "')' expected");
|
||||||
|
|
||||||
|
PreStatement = *Lexer;
|
||||||
|
if (!ParseStatement(Lexer, Conditional && RunIt))
|
||||||
|
ProgramFail(Lexer, "statement expected");
|
||||||
|
|
||||||
|
After = *Lexer;
|
||||||
|
|
||||||
|
while (Conditional && RunIt)
|
||||||
|
{
|
||||||
|
*Lexer = PreIncrement;
|
||||||
|
ParseStatement(Lexer, TRUE);
|
||||||
|
|
||||||
|
*Lexer = PreConditional;
|
||||||
|
ParseIntExpression(Lexer, &Conditional);
|
||||||
|
|
||||||
|
if (Conditional)
|
||||||
|
{
|
||||||
|
*Lexer = PreStatement;
|
||||||
|
ParseStatement(Lexer, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*Lexer = After;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TokenSemicolon: break;
|
||||||
|
|
||||||
|
case TokenIntType:
|
||||||
|
case TokenCharType:
|
||||||
|
case TokenVoidType:
|
||||||
|
if (LexGetToken(Lexer) != TokenIdentifier)
|
||||||
|
ProgramFail(Lexer, "identifier expected");
|
||||||
|
|
||||||
|
DeclareVariable(Lexer, Lexer->Value.String);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*Lexer = PreState;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse and run some code */
|
/* parse and run some code */
|
||||||
void ParseRun(const Str *FileName, const Str *Source, int LineNo)
|
void ParseRun(const Str *FileName, const Str *Source, int LineNo)
|
||||||
{
|
{
|
||||||
enum LexToken Token;
|
enum LexToken Token;
|
||||||
struct LexState Lexer;
|
struct LexState Lexer;
|
||||||
int ParseDepth = 0;
|
|
||||||
int IntValue;
|
|
||||||
|
|
||||||
LexInit(&Lexer, Source, FileName, 1);
|
LexInit(&Lexer, Source, FileName, 1);
|
||||||
|
|
||||||
while ( (Token = LexGetToken(&Lexer)) != TokenEOF)
|
while (ParseStatement(Lexer, TRUE))
|
||||||
{
|
{}
|
||||||
/* do parsey things here */
|
|
||||||
StrPrintf("token %d\n", (int)Token);
|
|
||||||
|
|
||||||
switch (ParseDepth)
|
|
||||||
{
|
|
||||||
case 0: /* top level */
|
|
||||||
if (Token == XXX
|
|
||||||
break;
|
|
||||||
|
|
||||||
case X: /* primary expression */
|
|
||||||
switch (Token)
|
|
||||||
{
|
|
||||||
case TokenIdentifier: IntValue = XXX; GoUp = TRUE; break;
|
|
||||||
case TokenIntegerConstant: IntValue = Lexer->Value.Integer; GoUp = TRUE; break;
|
|
||||||
case TokenStringConstant: StringValue = Lexer->Value.String; GoUp = TRUE; break;
|
|
||||||
case TokenOpenBracket:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* quick scan a source file for definitions */
|
/* quick scan a source file for definitions */
|
||||||
|
|
15
picoc.h
15
picoc.h
|
@ -60,6 +60,7 @@ enum LexToken
|
||||||
TokenArithmeticOr,
|
TokenArithmeticOr,
|
||||||
TokenArithmeticExor,
|
TokenArithmeticExor,
|
||||||
TokenUnaryExor,
|
TokenUnaryExor,
|
||||||
|
TokenUnaryNot,
|
||||||
TokenComma,
|
TokenComma,
|
||||||
TokenDot,
|
TokenDot,
|
||||||
TokenAddAssign,
|
TokenAddAssign,
|
||||||
|
@ -107,12 +108,24 @@ struct FuncDef
|
||||||
int StartLine;
|
int StartLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ValueType
|
||||||
|
{
|
||||||
|
TypeInt,
|
||||||
|
TypeString
|
||||||
|
};
|
||||||
|
|
||||||
union AnyValue
|
union AnyValue
|
||||||
{
|
{
|
||||||
int Integer;
|
int Integer;
|
||||||
Str String;
|
Str String;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Value
|
||||||
|
{
|
||||||
|
enum ValueType Typ;
|
||||||
|
union AnyValue Val;
|
||||||
|
};
|
||||||
|
|
||||||
/* lexer state - so we can lex nested files */
|
/* lexer state - so we can lex nested files */
|
||||||
struct LexState
|
struct LexState
|
||||||
{
|
{
|
||||||
|
@ -135,6 +148,7 @@ void vStrPrintf(const char *Format, va_list Args);
|
||||||
/* picoc.c */
|
/* picoc.c */
|
||||||
void Fail(const char *Message, ...);
|
void Fail(const char *Message, ...);
|
||||||
void ProgramError(const Str *FileName, int Line, const char *Message, ...);
|
void ProgramError(const Str *FileName, int Line, const char *Message, ...);
|
||||||
|
void ProgramFail(struct LexState *Lexer, const char *Message, ...);
|
||||||
void ScanFile(const Str *FileName);
|
void ScanFile(const Str *FileName);
|
||||||
|
|
||||||
/* table.c */
|
/* table.c */
|
||||||
|
@ -145,6 +159,7 @@ void *TableLookup(struct Table *Tbl, const Str *Key);
|
||||||
/* lex.c */
|
/* lex.c */
|
||||||
void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line);
|
void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line);
|
||||||
enum LexToken LexGetToken(struct LexState *Lexer);
|
enum LexToken LexGetToken(struct LexState *Lexer);
|
||||||
|
enum LexToken LexPeekToken(struct LexState *Lexer);
|
||||||
|
|
||||||
/* parse.c */
|
/* parse.c */
|
||||||
void ParseInit(void);
|
void ParseInit(void);
|
||||||
|
|
Loading…
Reference in a new issue