Allow omission of braces on multiple-statement switch cases.
This commit is contained in:
parent
4e47cdcaf6
commit
96f6773904
|
@ -287,6 +287,9 @@ struct FileData {
|
|||
// The column that was last marked as "valid", the start of the error block if something goes wrong.
|
||||
long CurrentSafeColumn;
|
||||
|
||||
// Whether or not we are currently parsing a switch statement - changes the behavior of compound statements!
|
||||
bool SwitchStatement;
|
||||
|
||||
// The symbol currently being lexed - TokenTypes index and integer value.
|
||||
struct Token CurrentSymbol;
|
||||
// The function currently being parsed - null if in global scope or if finished.
|
||||
|
|
32
src/Parser.c
32
src/Parser.c
|
@ -39,10 +39,13 @@ static int OperatorPrecedence(int Token) {
|
|||
int Prec = Precedence[Token];
|
||||
|
||||
if (Prec == 0 || Token >= PPMM_PLUS) {
|
||||
if (Token == TY_IDENTIFIER)
|
||||
DieMessage("Attempting to determine operator precedence of identifier", CurrentIdentifier);
|
||||
if (Token == TY_IDENTIFIER) {
|
||||
ErrorReport("Attempting to determine operator precedence of identifier %s\n", CurrentIdentifier);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]);
|
||||
ErrorReport("Attempting to determine operator precedence of an EOF or INT literal: %s\n", TokenNames[Token]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return Prec;
|
||||
|
@ -259,9 +262,8 @@ struct ASTNode* ParsePrimary(void) {
|
|||
return Node;
|
||||
}
|
||||
|
||||
|
||||
Tokenise();
|
||||
|
||||
Safe();
|
||||
return Node;
|
||||
}
|
||||
|
||||
|
@ -286,7 +288,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
|
|||
// int LeftType, RightType;
|
||||
int NodeType, OpType;
|
||||
|
||||
fflush(stdout);
|
||||
Safe();
|
||||
LeftNode = PrefixStatement();
|
||||
|
||||
NodeType = CurrentFile->CurrentSymbol.type;
|
||||
|
@ -296,14 +298,19 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
|
|||
return LeftNode;
|
||||
}
|
||||
|
||||
Safe();
|
||||
|
||||
while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) ||
|
||||
(IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
|
||||
Tokenise();
|
||||
if (CurrentFile->CurrentSymbol.type == LI_RPARE)
|
||||
break;
|
||||
|
||||
Safe();
|
||||
|
||||
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
|
||||
|
||||
Safe();
|
||||
/**
|
||||
* While parsing this node, we may need to widen some types.
|
||||
* This requires a few functions and checks.
|
||||
|
@ -483,7 +490,9 @@ struct ASTNode* ParseStatement(void) {
|
|||
printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentFile->CurrentSymbol.type], CurrentFile->CurrentSymbol.type);
|
||||
switch (CurrentFile->CurrentSymbol.type) {
|
||||
case LI_LBRAC:
|
||||
Tokenise();
|
||||
Node = ParseCompound();
|
||||
VerifyToken(LI_RBRAC, "}");
|
||||
return Node;
|
||||
case TY_CHAR:
|
||||
case TY_LONG:
|
||||
|
@ -541,10 +550,6 @@ struct ASTNode* ParseStatement(void) {
|
|||
struct ASTNode* ParseCompound() {
|
||||
struct ASTNode* Left = NULL, * Tree;
|
||||
|
||||
// Compound statements are defined by comprising
|
||||
// multiple statements inside { a bracket block }
|
||||
VerifyToken(LI_LBRAC, "{");
|
||||
|
||||
while (1) {
|
||||
printf("\tNew branch in compound\n");
|
||||
|
||||
|
@ -563,7 +568,11 @@ struct ASTNode* ParseCompound() {
|
|||
}
|
||||
|
||||
if (CurrentFile->CurrentSymbol.type == LI_RBRAC) {
|
||||
VerifyToken(LI_RBRAC, "}");
|
||||
fflush(stdout);
|
||||
return Left;
|
||||
}
|
||||
|
||||
if (CurrentFile->SwitchStatement && (CurrentFile->CurrentSymbol.type == KW_CASE || CurrentFile->CurrentSymbol.type == KW_DEFAULT)) {
|
||||
return Left;
|
||||
}
|
||||
}
|
||||
|
@ -592,7 +601,6 @@ void ParseGlobals() {
|
|||
printf("Parsing global definitions\r\n");
|
||||
|
||||
while (1) {
|
||||
|
||||
// We loop early if there's a struct, and since a struct may be the last
|
||||
// thing in a file, we need to check for eof before anything else
|
||||
if (CurrentFile->CurrentSymbol.type == LI_EOF)
|
||||
|
|
|
@ -292,7 +292,9 @@ struct ASTNode* ParseFunction(int Type) {
|
|||
CurrentFile->FunctionEntry = OldFunction;
|
||||
|
||||
CurrentFile->CurrentLoopDepth = 0;
|
||||
VerifyToken(LI_LBRAC, "{");
|
||||
Tree = ParseCompound();
|
||||
VerifyToken(LI_RBRAC, "}");
|
||||
|
||||
if (Type != RET_VOID) {
|
||||
// Functions with one statement have no composite node, so we have to check
|
||||
|
@ -550,6 +552,7 @@ struct ASTNode* SwitchStatement() {
|
|||
int ASTOp, casevalue;
|
||||
|
||||
printf("\tParsing switch statement\n");
|
||||
CurrentFile->SwitchStatement = true;
|
||||
|
||||
// Skip switch(
|
||||
Tokenise();
|
||||
|
@ -615,7 +618,7 @@ struct ASTNode* SwitchStatement() {
|
|||
VerifyToken(LI_COLON, ":");
|
||||
Safe();
|
||||
|
||||
left = ParseStatement();
|
||||
left = ParseCompound();
|
||||
OptionallyConsume(LI_SEMIC);
|
||||
cases++;
|
||||
Safe();
|
||||
|
@ -641,6 +644,7 @@ struct ASTNode* SwitchStatement() {
|
|||
// Consume the right brace immediately
|
||||
VerifyToken(LI_RBRAC, "}");
|
||||
|
||||
CurrentFile->SwitchStatement = false;
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@ -668,8 +672,8 @@ struct ASTNode* SwitchStatement() {
|
|||
* @return the AST of this statement
|
||||
*/
|
||||
struct ASTNode* BreakStatement() {
|
||||
if (CurrentFile->CurrentLoopDepth == 0)
|
||||
Die("Unable to break without a loop");
|
||||
if (CurrentFile->CurrentLoopDepth == 0 && !CurrentFile->SwitchStatement)
|
||||
Die("Unable to break without a loop or switch statement");
|
||||
|
||||
Tokenise();
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ int :: main() {
|
|||
case 1: {
|
||||
y = 5;
|
||||
break; }
|
||||
case 2: {
|
||||
case 2:
|
||||
y = 7;
|
||||
break; }
|
||||
break;
|
||||
case 3:
|
||||
y = 9;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue
Block a user