Parser stuff

This commit is contained in:
Sen 2023-02-02 14:05:53 +00:00
parent 7acaa9df76
commit abbd4a74ef
25 changed files with 1044 additions and 32 deletions

View file

@ -0,0 +1,91 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShintenScript;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShintenScriptTest
{
[TestClass]
public class EvaluationTest
{
[TestMethod]
public void TestBlock()
{
IASTNode ast = new ASTNodeBlock(new List<IASTNode>()
{
new ASTNodeLiteral(1f),
new ASTNodeLiteral(true),
new ASTNodeLiteral(5f)
});
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(5f, func(null));
}
[TestMethod]
public void TestAdd()
{
IASTNode ast = new ASTNodeAdd(new ASTNodeLiteral(2f), new ASTNodeLiteral(3f));
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(5f, func(null));
}
[TestMethod]
public void TestMul()
{
IASTNode ast = new ASTNodeMultiply(new ASTNodeLiteral(2f), new ASTNodeLiteral(3f));
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(6f, func(null));
}
[TestMethod]
public void TestSub()
{
IASTNode ast = new ASTNodeSubtract(new ASTNodeLiteral(2f), new ASTNodeLiteral(3f));
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(-1f, func(null));
}
[TestMethod]
public void TestDiv()
{
IASTNode ast = new ASTNodeDivide(new ASTNodeLiteral(7f), new ASTNodeLiteral(2f));
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(3.5f, func(null));
}
[TestMethod]
public void TestNegative()
{
IASTNode ast = new ASTNodeNegative(new ASTNodeLiteral(7f));
Assert.AreEqual(SSType.real, ast.Type());
Func<ExecutionContext, float> func = (Func<ExecutionContext, float>)ast.CreateFunction();
Assert.AreEqual(-7f, func(null));
}
}
}

View file

@ -19,6 +19,7 @@ namespace ShintenScriptTest
1.5e6
2.4e-6
;
( ) { }
+ - * /
> < == >= <= !=
@ -36,6 +37,7 @@ namespace ShintenScriptTest
new Token { type = Token.Type.NUMBER, data = 1.5e6f },
new Token { type = Token.Type.NUMBER, data = 2.4e-6f },
new Token { type = Token.Type.SEMICOLON },
new Token { type = Token.Type.LPAREN },
new Token { type = Token.Type.RPAREN },
new Token { type = Token.Type.LBRACE },
@ -59,8 +61,18 @@ namespace ShintenScriptTest
new Token { type = Token.Type.IF },
new Token { type = Token.Type.WHILE },
new Token { type = Token.Type.FN },
}));
}
new Token { type = Token.Type.EOF },
[TestMethod]
public void TestHexExponent()
{
Lexer lexer = new Lexer(@"0xcafe-1337");
Assert.IsTrue(lexer.TokenStream().SequenceEqual(new Token[] {
new Token { type = Token.Type.NUMBER, data = 51966f },
new Token { type = Token.Type.MINUS },
new Token { type = Token.Type.NUMBER, data = 1337f },
}));
}
}

View file

@ -0,0 +1,153 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShintenScript;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShintenScriptTest
{
[TestClass]
public class ParserTest
{
[TestMethod]
public void TestBlock()
{
Lexer lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.LBRACE },
new Token { type = Token.Type.NUMBER, data = 1f },
new Token { type = Token.Type.NUMBER, data = 2f },
new Token { type = Token.Type.NUMBER, data = 3f },
new Token { type = Token.Type.RBRACE },
});
IASTNode ast = new Parser(lexer).ParseExpression();
if (ast is ASTNodeBlock block)
{
Assert.AreEqual(3, block.statements.Count);
Assert.IsInstanceOfType(block.statements[0], typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(block.statements[1], typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(block.statements[2], typeof(ASTNodeLiteral));
}
else Assert.Fail();
}
[TestMethod]
public void TestComparison()
{
Lexer lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.NUMBER, data = 1f },
new Token { type = Token.Type.LE },
new Token { type = Token.Type.NUMBER, data = 2f },
new Token { type = Token.Type.NE },
new Token { type = Token.Type.NUMBER, data = 3f },
});
IASTNode ast = new Parser(lexer).ParseExpression();
if (ast is ASTNodeComparison comp)
{
Assert.AreEqual(3, comp.nodes.Count);
Assert.AreEqual(2, comp.comparisons.Count);
Assert.IsInstanceOfType(comp.nodes[0], typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(comp.nodes[1], typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(comp.nodes[2], typeof(ASTNodeLiteral));
Assert.AreEqual(Token.Type.LE, comp.comparisons[0]);
Assert.AreEqual(Token.Type.NE, comp.comparisons[1]);
}
else Assert.Fail();
}
[TestMethod]
public void TestDivision()
{
Lexer lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.NUMBER, data = 1f },
new Token { type = Token.Type.SLASH },
new Token { type = Token.Type.NUMBER, data = 2f },
});
IASTNode ast = new Parser(lexer).ParseExpression();
Assert.IsInstanceOfType(ast, typeof(ASTNodeDivide));
}
[TestMethod]
public void TestMinus()
{
Lexer lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.MINUS },
new Token { type = Token.Type.NUMBER, data = 2f },
new Token { type = Token.Type.MINUS },
new Token { type = Token.Type.NUMBER, data = 3f },
});
IASTNode ast = new Parser(lexer).ParseExpression();
if (ast is ASTNodeSubtract sub)
{
Assert.IsInstanceOfType(sub.lhs, typeof(ASTNodeNegative));
Assert.IsInstanceOfType(sub.rhs, typeof(ASTNodeLiteral));
}
else Assert.Fail();
}
[TestMethod]
public void TestOrderOfOperations()
{
Lexer lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.NUMBER, data = 1f },
new Token { type = Token.Type.PLUS },
new Token { type = Token.Type.NUMBER, data = 2f },
new Token { type = Token.Type.ASTERISK },
new Token { type = Token.Type.NUMBER, data = 3f },
});
IASTNode ast = new Parser(lexer).ParseExpression();
if (ast is ASTNodeAdd add)
{
Assert.IsInstanceOfType(add.lhs, typeof(ASTNodeLiteral));
if (add.rhs is ASTNodeMultiply mul)
{
Assert.IsInstanceOfType(mul.lhs, typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(mul.rhs, typeof(ASTNodeLiteral));
}
else Assert.Fail();
}
else Assert.Fail();
lexer = new ScaffoldLexer(new Token[]
{
new Token { type = Token.Type.NUMBER, data = 1f },
new Token { type = Token.Type.ASTERISK },
new Token { type = Token.Type.NUMBER, data = 2f },
new Token { type = Token.Type.PLUS },
new Token { type = Token.Type.NUMBER, data = 3f },
});
ast = new Parser(lexer).ParseExpression();
if (ast is ASTNodeAdd add2)
{
Assert.IsInstanceOfType(add2.rhs, typeof(ASTNodeLiteral));
if (add2.lhs is ASTNodeMultiply mul)
{
Assert.IsInstanceOfType(mul.lhs, typeof(ASTNodeLiteral));
Assert.IsInstanceOfType(mul.rhs, typeof(ASTNodeLiteral));
}
else Assert.Fail();
}
else Assert.Fail();
}
}
}

View file

@ -0,0 +1,27 @@
using ShintenScript;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShintenScriptTest
{
class ScaffoldLexer : Lexer
{
Queue<Token> tokenQueue;
public ScaffoldLexer(IEnumerable<Token> queue) : base("")
{
tokenQueue = new Queue<Token>(queue);
}
public override Token ParseOne()
{
if (tokenQueue.Count == 0)
return new Token { type = Token.Type.EOF };
return tokenQueue.Dequeue();
}
}
}

View file

@ -49,8 +49,11 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="EvaluationTest.cs" />
<Compile Include="LexerTests.cs" />
<Compile Include="ParserTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScaffoldLexer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />