From 6a1d28c1dcd8c7485e5c6c4bdf064ab4a221038a Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Thu, 19 Feb 2009 09:07:00 +0000 Subject: [PATCH] switch is now working. did some work on break / continue in loops. git-svn-id: http://picoc.googlecode.com/svn/trunk@87 21eae674-98b7-11dd-bd71-f92a316d2d60 --- parse.c | 110 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/parse.c b/parse.c index 5f784d7..d7f60d1 100644 --- a/parse.c +++ b/parse.c @@ -490,6 +490,13 @@ void ParseMacroDefinition(struct ParseState *Parser) ProgramFail(Parser, "'%s' is already defined", &MacroName->Val->String); } +/* copy where we're at in the parsing */ +void ParserCopyPos(struct ParseState *To, struct ParseState *From) +{ + To->Pos = From->Pos; + To->Line = From->Line; +} + /* parse a "for" statement */ void ParseFor(struct ParseState *Parser) { @@ -508,40 +515,49 @@ void ParseFor(struct ParseState *Parser) if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) ProgramFail(Parser, "';' expected"); - PreConditional = *Parser; + ParserCopyPos(&PreConditional, Parser); Condition = ParseIntExpression(Parser); if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) ProgramFail(Parser, "';' expected"); - PreIncrement = *Parser; + ParserCopyPos(&PreIncrement, Parser); ParseStatementMaybeRun(Parser, FALSE); if (LexGetToken(Parser, NULL, TRUE) != TokenCloseBracket) ProgramFail(Parser, "')' expected"); - PreStatement = *Parser; + ParserCopyPos(&PreStatement, Parser); if (!ParseStatementMaybeRun(Parser, Condition)) ProgramFail(Parser, "statement expected"); - After = *Parser; - + if (Parser->Mode == RunModeContinue) + Parser->Mode = RunModeRun; + + ParserCopyPos(&After, Parser); + while (Condition && Parser->Mode == RunModeRun) { - *Parser = PreIncrement; + ParserCopyPos(Parser, &PreIncrement); ParseStatement(Parser); - *Parser = PreConditional; + ParserCopyPos(Parser, &PreConditional); Condition = ParseIntExpression(Parser); if (Condition) { - *Parser = PreStatement; + ParserCopyPos(Parser, &PreStatement); ParseStatement(Parser); + + if (Parser->Mode == RunModeContinue) + Parser->Mode = RunModeRun; } } - *Parser = After; + if (Parser->Mode == RunModeBreak) + Parser->Mode = RunModeRun; + + ParserCopyPos(Parser, &After); } /* parse a statement, but only run it if Condition is TRUE */ @@ -559,6 +575,32 @@ int ParseStatementMaybeRun(struct ParseState *Parser, int Condition) return ParseStatement(Parser); } +/* parse a block of code and return what mode it returned in */ +enum RunMode ParseBlock(struct ParseState *Parser, int AbsorbOpenBrace, int Condition) +{ + if (AbsorbOpenBrace && LexGetToken(Parser, NULL, TRUE) != TokenLeftBrace) + ProgramFail(Parser, "'{' expected"); + + if (Parser->Mode != RunModeSkip && !Condition) + { /* condition failed - skip this block instead */ + enum RunMode OldMode = Parser->Mode; + Parser->Mode = RunModeSkip; + while (ParseStatement(Parser)) + {} + Parser->Mode = OldMode; + } + else + { /* just run it in its current mode */ + while (ParseStatement(Parser)) + {} + } + + if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace) + ProgramFail(Parser, "'}' expected"); + + return Parser->Mode; +} + /* parse a statement */ int ParseStatement(struct ParseState *Parser) { @@ -582,11 +624,7 @@ int ParseStatement(struct ParseState *Parser) break; case TokenLeftBrace: - while (ParseStatement(Parser)) - {} - - if (LexGetToken(Parser, NULL, TRUE) != TokenRightBrace) - ProgramFail(Parser, "'}' expected"); + ParseBlock(Parser, FALSE, TRUE); break; case TokenIf: @@ -611,31 +649,40 @@ int ParseStatement(struct ParseState *Parser) case TokenWhile: { - struct ParseState PreConditional = *Parser; + struct ParseState PreConditional; + ParserCopyPos(&PreConditional, Parser); do { - *Parser = PreConditional; + ParserCopyPos(Parser, &PreConditional); Condition = ParseIntExpression(Parser); + ParseBlock(Parser, TRUE, Condition); + if (Parser->Mode == RunModeContinue) + Parser->Mode = RunModeRun; + + } while (Parser->Mode == RunModeRun && Condition); - if (!ParseStatementMaybeRun(Parser, Condition)) - ProgramFail(Parser, "statement expected"); - - } while (Parser->Mode == RunModeRun && Condition); + if (Parser->Mode == RunModeBreak) + Parser->Mode = RunModeRun; } break; case TokenDo: { - struct ParseState PreStatement = *Parser; + struct ParseState PreStatement; + ParserCopyPos(&PreStatement, Parser); do { - *Parser = PreStatement; - if (!ParseStatement(Parser)) - ProgramFail(Parser, "statement expected"); - + ParserCopyPos(Parser, &PreStatement); + ParseBlock(Parser, TRUE, TRUE); + if (Parser->Mode == RunModeContinue) + Parser->Mode = RunModeRun; + Condition = ParseIntExpression(Parser); } while (Condition && Parser->Mode == RunModeRun); + + if (Parser->Mode == RunModeBreak) + Parser->Mode = RunModeRun; } break; @@ -702,8 +749,7 @@ int ParseStatement(struct ParseState *Parser) Parser->Mode = RunModeCaseSearch; Parser->SearchLabel = Condition; - if (!ParseStatement(Parser)) - ProgramFail(Parser, "statement expected"); + ParseBlock(Parser, TRUE, TRUE); Parser->Mode = OldMode; Parser->SearchLabel = OldSearchLabel; @@ -711,7 +757,15 @@ int ParseStatement(struct ParseState *Parser) break; case TokenCase: - Condition = ParseIntExpression(Parser); + if (Parser->Mode == RunModeCaseSearch) + { + Parser->Mode = RunModeRun; + Condition = ParseIntExpression(Parser); + Parser->Mode = RunModeCaseSearch; + } + else + Condition = ParseIntExpression(Parser); + if (LexGetToken(Parser, NULL, TRUE) != TokenColon) ProgramFail(Parser, "':' expected");