From 8cfd9c60131d2b8f35928f8155f7a67e4e580ca9 Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Sat, 22 Nov 2008 02:56:08 +0000 Subject: [PATCH] Wrote much of the parser git-svn-id: http://picoc.googlecode.com/svn/trunk@9 21eae674-98b7-11dd-bd71-f92a316d2d60 --- lex.c | 8 ++ parse.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++----- picoc.h | 15 ++++ 3 files changed, 269 insertions(+), 23 deletions(-) diff --git a/lex.c b/lex.c index d89c6f5..5059887 100644 --- a/lex.c +++ b/lex.c @@ -161,6 +161,7 @@ enum LexToken LexGetToken(struct LexState *Lexer) case '}': return TokenRightBrace; case '[': return TokenLeftAngleBracket; case ']': return TokenRightAngleBracket; + case '!': return TokenUnaryNot; case '^': return TokenArithmeticExor; case '~': return TokenUnaryExor; case ',': return TokenComma; @@ -171,3 +172,10 @@ enum LexToken LexGetToken(struct LexState *Lexer) 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); +} + diff --git a/parse.c b/parse.c index 2ac5a50..9618432 100644 --- a/parse.c +++ b/parse.c @@ -13,36 +13,259 @@ void ParseInit() 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 */ void ParseRun(const Str *FileName, const Str *Source, int LineNo) { enum LexToken Token; struct LexState Lexer; - int ParseDepth = 0; - int IntValue; LexInit(&Lexer, Source, FileName, 1); - - while ( (Token = LexGetToken(&Lexer)) != TokenEOF) - { - /* 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: - } - } + + while (ParseStatement(Lexer, TRUE)) + {} } /* quick scan a source file for definitions */ diff --git a/picoc.h b/picoc.h index 58f7344..5a4ec8f 100644 --- a/picoc.h +++ b/picoc.h @@ -60,6 +60,7 @@ enum LexToken TokenArithmeticOr, TokenArithmeticExor, TokenUnaryExor, + TokenUnaryNot, TokenComma, TokenDot, TokenAddAssign, @@ -107,12 +108,24 @@ struct FuncDef int StartLine; }; +enum ValueType +{ + TypeInt, + TypeString +}; + union AnyValue { int Integer; Str String; }; +struct Value +{ + enum ValueType Typ; + union AnyValue Val; +}; + /* lexer state - so we can lex nested files */ struct LexState { @@ -135,6 +148,7 @@ void vStrPrintf(const char *Format, va_list Args); /* picoc.c */ void Fail(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); /* table.c */ @@ -145,6 +159,7 @@ void *TableLookup(struct Table *Tbl, const Str *Key); /* lex.c */ void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line); enum LexToken LexGetToken(struct LexState *Lexer); +enum LexToken LexPeekToken(struct LexState *Lexer); /* parse.c */ void ParseInit(void);