Skip to content

Commit f484c5d

Browse files
authored
Boolean logic (#11)
AND + OR
1 parent 6442dda commit f484c5d

File tree

25 files changed

+422
-74
lines changed

25 files changed

+422
-74
lines changed

SomeCompiler.Parser.Antlr4/ExpressionConverter.cs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Runtime.Intrinsics.Arm;
21
using Antlr4.Runtime.Tree;
32
using SomeCompiler.Core.Helpers;
43
using SomeCompiler.Parser.Model;
@@ -27,32 +26,44 @@ private Expression ParseAssignment(CParser.AssignmentExpressionContext expr)
2726

2827
private Expression ParseConditionalExpression(CParser.ConditionalExpressionContext node)
2928
{
30-
return ParseSomething((CParser.LogicalOrExpressionContext) node.GetChild(0));
29+
return LogicalOr((CParser.LogicalOrExpressionContext) node.GetChild(0));
3130
}
3231

33-
private Expression ParseSomething(CParser.LogicalOrExpressionContext node)
32+
private Expression LogicalOr(CParser.LogicalOrExpressionContext node)
3433
{
35-
return ParseLogicalAnd((CParser.LogicalAndExpressionContext) node.GetChild(0));
34+
if (node.ChildCount > 1)
35+
{
36+
var binaryTree = BinaryTreeHelper.FromPostFix(node.Children().ToList());
37+
return ToExpression(binaryTree!, tree => LogicalAnd((CParser.LogicalAndExpressionContext) tree));
38+
}
39+
40+
return LogicalAnd((CParser.LogicalAndExpressionContext) node.GetChild(0));
3641
}
3742

38-
private Expression ParseLogicalAnd(CParser.LogicalAndExpressionContext node)
43+
private Expression LogicalAnd(CParser.LogicalAndExpressionContext node)
3944
{
40-
return ParseInclusiveOr((CParser.InclusiveOrExpressionContext) node.GetChild(0));
45+
if (node.ChildCount > 1)
46+
{
47+
var binaryTree = BinaryTreeHelper.FromPostFix(node.Children().ToList());
48+
return ToExpression(binaryTree!, tree => InclusiveOr((CParser.InclusiveOrExpressionContext) tree));
49+
}
50+
51+
return InclusiveOr((CParser.InclusiveOrExpressionContext) node.GetChild(0));
4152
}
4253

43-
private Expression ParseInclusiveOr(CParser.InclusiveOrExpressionContext node)
54+
private Expression InclusiveOr(CParser.InclusiveOrExpressionContext node)
4455
{
45-
return ParseExclusive((CParser.ExclusiveOrExpressionContext)node.GetChild(0));
56+
return ExclusiveOr((CParser.ExclusiveOrExpressionContext)node.GetChild(0));
4657
}
4758

48-
private Expression ParseExclusive(CParser.ExclusiveOrExpressionContext exclusiveOrExpressionContext)
59+
private Expression ExclusiveOr(CParser.ExclusiveOrExpressionContext exclusiveOrExpressionContext)
4960
{
50-
return AndExpression((CParser.AndExpressionContext) exclusiveOrExpressionContext.GetChild(0));
61+
return And((CParser.AndExpressionContext) exclusiveOrExpressionContext.GetChild(0));
5162
}
5263

53-
private Expression AndExpression(CParser.AndExpressionContext exclusiveOrExpressionContext)
64+
private Expression And(CParser.AndExpressionContext andExpressionContext)
5465
{
55-
return EqualityExpr((CParser.EqualityExpressionContext) exclusiveOrExpressionContext.GetChild(0));
66+
return EqualityExpr((CParser.EqualityExpressionContext) andExpressionContext.GetChild(0));
5667
}
5768

5869
private Expression EqualityExpr(CParser.EqualityExpressionContext node)
@@ -62,10 +73,10 @@ private Expression EqualityExpr(CParser.EqualityExpressionContext node)
6273

6374
private Expression Relational(CParser.RelationalExpressionContext node)
6475
{
65-
return ShiftExpression((CParser.ShiftExpressionContext) node.GetChild(0));
76+
return Shift((CParser.ShiftExpressionContext) node.GetChild(0));
6677
}
6778

68-
private Expression ShiftExpression(CParser.ShiftExpressionContext node)
79+
private Expression Shift(CParser.ShiftExpressionContext node)
6980
{
7081
return Additive((CParser.AdditiveExpressionContext) node.GetChild(0));
7182
}
@@ -75,7 +86,8 @@ private Expression Additive(CParser.AdditiveExpressionContext node)
7586
if (node.ChildCount > 1)
7687
{
7788
var binaryTree = BinaryTreeHelper.FromPostFix(node.Children().ToList());
78-
return ToExpression(binaryTree!, tree => Multiplicative((CParser.MultiplicativeExpressionContext) tree)); }
89+
return ToExpression(binaryTree!, tree => Multiplicative((CParser.MultiplicativeExpressionContext) tree));
90+
}
7991

8092
return Multiplicative((CParser.MultiplicativeExpressionContext) node.GetChild(0));
8193
}
@@ -128,6 +140,8 @@ private static Expression GetExpr(BinaryNode<IParseTree> binaryTree, Expression
128140
"-" => new SubtractExpression(left, right),
129141
"*" => new MultiplyExpression(left, right),
130142
"/" => new DivideExpression(left, right),
143+
"&&" => new AndExpression(left, right),
144+
"||" => new OrExpression(left, right),
131145
_ => throw new ArgumentOutOfRangeException(t.GetText())
132146
};
133147
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace SomeCompiler.Parser.Model;
2+
3+
public record AndExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right)
4+
{
5+
public override IEnumerable<INode> Children { get; }
6+
public override string Symbol => "&&";
7+
public override int Precedence => 11;
8+
public override string ToString()
9+
{
10+
return base.ToString();
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace SomeCompiler.Parser.Model;
2+
3+
public record OrExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right)
4+
{
5+
public override IEnumerable<INode> Children { get; }
6+
public override string Symbol => "||";
7+
public override int Precedence => 12;
8+
public override string ToString()
9+
{
10+
return base.ToString();
11+
}
12+
}

SomeCompiler.Tests/CompilerTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ public void Main_function_should_be_declared()
4444
AssertError("int other() { }", ErrorKind.MainNotDeclared);
4545
}
4646

47+
[Fact]
48+
public void Variable_declaration()
49+
{
50+
AssertSuccess("int main() { int p; }");
51+
}
52+
4753
private static void AssertSuccess(string code)
4854
{
4955
Compile(code)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Antlr4.Runtime;
2+
using SomeCompiler.Parser.Antlr4;
3+
4+
namespace SomeCompiler.Tests;
5+
6+
public class ExpressionParsingTests
7+
{
8+
[Theory]
9+
[InlineData("1")]
10+
[InlineData("-1")]
11+
[InlineData("identifier")]
12+
[InlineData("1+1")]
13+
[InlineData("1-1")]
14+
[InlineData("1*2")]
15+
[InlineData("!a")]
16+
[InlineData("a=1")]
17+
[InlineData("id=1")]
18+
[InlineData("7/2*4")]
19+
[InlineData("7-2+4")]
20+
[InlineData("7*2+4/2")]
21+
[InlineData("(1+2)*4")]
22+
[InlineData("1 && 0")]
23+
[InlineData("(1 && 2) + 2")]
24+
[InlineData("0 || 1")]
25+
public void Expression(string input)
26+
{
27+
AssertExpression(input);
28+
}
29+
30+
private void AssertExpression(string s)
31+
{
32+
var lexer = new CLexer(CharStreams.fromString(s));
33+
var parser = new CParser(new CommonTokenStream(lexer));
34+
var expr = parser.expression();
35+
36+
var ret = new ExpressionConverter().ParseExpression(expr);
37+
ret.ToString().RemoveWhitespace().Should().Be(s.RemoveWhitespace());
38+
}
39+
}

SomeCompiler.Tests/ParserTests.cs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
using Antlr4.Runtime;
2-
using SomeCompiler.Parser.Antlr4;
3-
41
namespace SomeCompiler.Tests;
52

63
public class ParserTests
@@ -86,36 +83,4 @@ private static void AssertParse(string source)
8683
result.Should().BeSuccess()
8784
.And.Subject.Value.ToString().RemoveWhitespace().Should().Be(source.RemoveWhitespace());
8885
}
89-
}
90-
91-
public class ExpressionParsingTests
92-
{
93-
[Theory]
94-
[InlineData("1")]
95-
[InlineData("-1")]
96-
[InlineData("identifier")]
97-
[InlineData("1+1")]
98-
[InlineData("1-1")]
99-
[InlineData("1*2")]
100-
[InlineData("!a")]
101-
[InlineData("a=1")]
102-
[InlineData("id=1")]
103-
[InlineData("7/2*4")]
104-
[InlineData("7-2+4")]
105-
[InlineData("7*2+4/2")]
106-
[InlineData("(1+2)*4")]
107-
public void Expression(string input)
108-
{
109-
AssertExpression(input);
110-
}
111-
112-
private void AssertExpression(string s)
113-
{
114-
var lexer = new CLexer(CharStreams.fromString(s));
115-
var parser = new CParser(new CommonTokenStream(lexer));
116-
var expr = parser.expression();
117-
118-
var ret = new ExpressionConverter().ParseExpression(expr);
119-
ret.ToString().RemoveWhitespace().Should().Be(s.RemoveWhitespace());
120-
}
12186
}

SomeCompiler.Tests/ScopeTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using SomeCompiler.Parser.Model;
2+
3+
namespace SomeCompiler.Tests;
4+
5+
public class ScopeTests
6+
{
7+
[Fact]
8+
public void ScopeTest()
9+
{
10+
var sut = new BinderScope();
11+
var symbol = new Symbol(BoundType.Int);
12+
sut.Declare("pepito", symbol);
13+
var result = sut.Get("pepito");
14+
result.HasValue.Should().BeTrue();
15+
result.Value.Should().Be(symbol);
16+
}
17+
18+
[Fact]
19+
public void ScopeTest2()
20+
{
21+
var sut = new BinderScope();
22+
var symbol = new Symbol(BoundType.Int);
23+
sut.Declare("pepito", symbol);
24+
var scope = sut.CreateChild();
25+
scope.Declare("flokito", new Symbol(BoundType.Int));
26+
27+
var result = scope.Get("pepito");
28+
29+
result.HasValue.Should().BeTrue();
30+
result.Value.Should().Be(symbol);
31+
}
32+
}

SomeCompiler.VirtualMachine.Tests/UnitTest1.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

SomeCompiler.VirtualMachine.Tests/VirtualMachineTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,20 @@ public async Task Parentheses()
113113
state.Memory["a"].Should().BeEquivalentTo(new DataMemoryEntry(6));
114114
}
115115

116+
[Fact]
117+
public async Task And()
118+
{
119+
var state = await Run("int main() { a = 1 && 1; }");
120+
state.Memory["a"].Should().NotBeEquivalentTo(0);
121+
}
122+
123+
[Fact]
124+
public async Task Or()
125+
{
126+
var state = await Run("int main() { a = 1 || 0; }");
127+
state.Memory["a"].Should().NotBeEquivalentTo(0);
128+
}
129+
116130
private static IObservable<VirtualMachineState> Run(string code)
117131
{
118132
var gen = new Compiler();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using CodeGeneration.Model.Classes;
2+
3+
namespace SomeCompiler.VirtualMachine.Commands;
4+
5+
internal class AndCommand : Command
6+
{
7+
public AndCommand(IMachine machine, Reference left, Reference right, Reference destination)
8+
{
9+
Machine = machine;
10+
Left = left;
11+
Right = right;
12+
Destination = destination;
13+
}
14+
15+
public IMachine Machine { get; }
16+
public Reference Left { get; }
17+
public Reference Right { get; }
18+
public Reference Destination { get; }
19+
20+
public override void Execute()
21+
{
22+
var leftValue = ((DataMemoryEntry)Machine.Memory[Machine.Variables[Left]]).Value;
23+
var rightValue = ((DataMemoryEntry)Machine.Memory[Machine.Variables[Right]]).Value;
24+
Machine.Memory[Machine.Variables[Destination]] = new DataMemoryEntry(Convert.ToInt32(Convert.ToBoolean(leftValue) && Convert.ToBoolean(rightValue)));
25+
Machine.ExecutionPointer++;
26+
}
27+
}

0 commit comments

Comments
 (0)