Skip to content

Commit

Permalink
(ForNeVeR#74) Parser: labeled and switch statements
Browse files Browse the repository at this point in the history
  • Loading branch information
gsomix committed Jul 21, 2022
1 parent 9d92cbc commit 535b898
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 10 deletions.
13 changes: 12 additions & 1 deletion Cesium.Ast/Statements.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
using System.Collections.Immutable;
using Yoakke.SynKit.C.Syntax;
using Yoakke.SynKit.Lexer;

namespace Cesium.Ast;

// 6.8 Statements and blocks
public abstract record Statement : IBlockItem;

// 6.8.1 Labeled statement
public record LabelStatement(string Identifier, Statement Body) : Statement;

public record CaseStatement(IToken<CTokenType> Constant, Statement Body) : Statement;

public record DefaultStatement(Statement Body) : Statement;

// 6.8.2 Compound statement
public record CompoundStatement(ImmutableArray<IBlockItem> Block) : Statement;

Expand All @@ -18,6 +27,8 @@ public record ExpressionStatement(Expression? Expression) : Statement;
// 6.8.4 Selection statements
public record IfElseStatement(Expression Expression, Statement TrueBranch, Statement? FalseBranch) : Statement;

public record SwitchStatement(Expression Expression, Statement Body) : Statement;

// 6.8.5 Iteration statements
public record ForStatement(
Expression? InitExpression,
Expand All @@ -30,4 +41,4 @@ public record GoToStatement(string Identifier) : Statement;

public record BreakStatement : Statement;

public record ReturnStatement(Expression Expression) : Statement;
public record ReturnStatement(Expression Expression) : Statement;
23 changes: 21 additions & 2 deletions Cesium.Parser.Tests/ParserTests/StatementParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ private static Task DoTest(string source)
[Fact]
public Task NestedIfs() => DoTest(@"
if (1)
if (2) {
if (2) {
int x = 0;
} else {
int y = 1;
}
}
");

[Fact]
Expand Down Expand Up @@ -92,4 +92,23 @@ public Task ArrayAssigment() => DoTest(@"{
int a[1];
a[0] = 0;
}");

[Fact]
public Task SwitchStatement_Empty() => DoTest(@"switch(x) { }");

[Fact]
public Task SwitchStatement_OneCase() => DoTest(@"switch(x) { case 0: break; }");

[Fact]
public Task SwitchStatement_MultiCases() => DoTest(@"switch(x) {
case 0: break;
case 1: break;
}");

[Fact]
public Task SwitchStatement_MultiCasesWithDefault() => DoTest(@"switch(x) {
case 0: break;
case 1: break;
default: break;
}");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$type": "Cesium.Ast.SwitchStatement, Cesium.Ast",
"Expression": {
"$type": "Cesium.Ast.ConstantExpression, Cesium.Ast",
"Constant": {
"Kind": "Identifier",
"Text": "x"
}
},
"Body": {
"$type": "Cesium.Ast.CompoundStatement, Cesium.Ast",
"Block": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$type": "Cesium.Ast.SwitchStatement, Cesium.Ast",
"Expression": {
"$type": "Cesium.Ast.ConstantExpression, Cesium.Ast",
"Constant": {
"Kind": "Identifier",
"Text": "x"
}
},
"Body": {
"$type": "Cesium.Ast.CompoundStatement, Cesium.Ast",
"Block": [
{
"$type": "Cesium.Ast.CaseStatement, Cesium.Ast",
"Constant": {
"Kind": "IntLiteral",
"Text": "0"
},
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
},
{
"$type": "Cesium.Ast.CaseStatement, Cesium.Ast",
"Constant": {
"Kind": "IntLiteral",
"Text": "1"
},
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$type": "Cesium.Ast.SwitchStatement, Cesium.Ast",
"Expression": {
"$type": "Cesium.Ast.ConstantExpression, Cesium.Ast",
"Constant": {
"Kind": "Identifier",
"Text": "x"
}
},
"Body": {
"$type": "Cesium.Ast.CompoundStatement, Cesium.Ast",
"Block": [
{
"$type": "Cesium.Ast.CaseStatement, Cesium.Ast",
"Constant": {
"Kind": "IntLiteral",
"Text": "0"
},
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
},
{
"$type": "Cesium.Ast.CaseStatement, Cesium.Ast",
"Constant": {
"Kind": "IntLiteral",
"Text": "1"
},
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
},
{
"$type": "Cesium.Ast.DefaultStatement, Cesium.Ast",
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$type": "Cesium.Ast.SwitchStatement, Cesium.Ast",
"Expression": {
"$type": "Cesium.Ast.ConstantExpression, Cesium.Ast",
"Constant": {
"Kind": "Identifier",
"Text": "x"
}
},
"Body": {
"$type": "Cesium.Ast.CompoundStatement, Cesium.Ast",
"Block": [
{
"$type": "Cesium.Ast.CaseStatement, Cesium.Ast",
"Constant": {
"Kind": "IntLiteral",
"Text": "0"
},
"Body": {
"$type": "Cesium.Ast.BreakStatement, Cesium.Ast"
}
}
]
}
}
36 changes: 29 additions & 7 deletions Cesium.Parser/CParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -635,15 +635,28 @@ private static AssignmentInitializer MakeInitializer(Expression assignmentExpres
// TODO: 6.7.10 Static assertions

// 6.8 Statements and blocks
// TODO: [Rule("statement: labeled_statement")]
[Rule("statement: labeled_statement")]
[Rule("statement: compound_statement")]
[Rule("statement: expression_statement")]
[Rule("statement: selection_statement")]
[Rule("statement: iteration_statement")]
[Rule("statement: jump_statement")]
private static Statement MakeStatementIdentity(Statement statement) => statement;

// TODO: 6.8.1 Labeled statements
// 6.8.1 Labeled statements
[Rule("labeled_statement: Identifier ':' statement")]
private static Statement MakeLabelStatement(IToken identifier, IToken _, Statement block) =>
new LabelStatement(identifier.Text, block);

// TODO: constant or constant-expression? What's difference? gsomix.
[Rule("labeled_statement: 'case' constant ':' statement")]
private static Statement MakeCaseStatement(IToken _, ICToken constant, IToken __, Statement block) =>
new CaseStatement(constant, block);

[Rule("labeled_statement: 'default' ':' statement")]
private static Statement MakeDefaultStatement(IToken _, IToken __, Statement block) =>
new DefaultStatement(block);

// 6.8.2 Compound statement
[Rule("compound_statement: '{' block_item_list? '}'")]
private static CompoundStatement MakeCompoundStatement(ICToken _, BlockItemList? block, ICToken __) =>
Expand All @@ -665,25 +678,34 @@ private static CompoundStatement MakeCompoundStatement(ICToken _, BlockItemList?

// 6.8.4 Selection statements
[Rule("selection_statement: 'if' '(' expression ')' statement")]
private static IfElseStatement MakeIfStatement(
private static Statement MakeIfStatement(
IToken _,
IToken __,
Expression expression,
IToken ___,
Statement statement)
=> new(expression, statement, null);
=> new IfElseStatement(expression, statement, null);

[Rule("selection_statement: 'if' '(' expression ')' statement 'else' statement")]
private static IfElseStatement MakeIfElseStatement(
private static Statement MakeIfElseStatement(
IToken _,
IToken __,
Expression expression,
IToken ___,
Statement trueBranch,
IToken ____,
Statement falseBranch)
=> new(expression, trueBranch, falseBranch);
// TODO: 6.8.4 Selection statements switch
=> new IfElseStatement(expression, trueBranch, falseBranch);

[Rule("selection_statement: 'switch' '(' expression ')' statement")]
private static Statement MakeSwitchStatement(
IToken _, // switch
IToken __, // (
Expression expression,
IToken ___, // )
Statement body)
=> new SwitchStatement(expression, body);


// TODO: 6.8.5 Iteration statements
[Rule("iteration_statement: 'for' '(' expression? ';' expression? ';' expression? ')' statement")]
Expand Down

0 comments on commit 535b898

Please sign in to comment.