A few fixes and renames

--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-11-27 17:36:55 -08:00
parent ca1d1987bf
commit 334726e08a
8 changed files with 104 additions and 69 deletions

View File

@@ -135,6 +135,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CodeGeneration\Commands\CodeGenerationCommandsTests.cs" />
<Compile Include="SimpleScriptingTests\ExpressionEvaluatorTests.cs" />
<Compile Include="SimpleScriptingTests\ExpressionParserTests.cs" />
<Compile Include="SimpleScriptingTests\ExpressionLexerTests.cs" />
<Compile Include="SimpleScriptingTests\SimpleScriptingTests.cs" />

View File

@@ -0,0 +1,13 @@
using NUnit.Framework;
using Orchard.Widgets.SimpleScripting;
namespace Orchard.Tests.Modules.SimpleScriptingTests {
[TestFixture]
public class ExpressionEvaluatorTests {
[Test]
public void EvaluateSimpleConstant() {
var tree = new ExpressionParser("1*2+3").Parse();
}
}
}

View File

@@ -35,9 +35,9 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void LexerShouldProcessReservedWords() {
TestReservedWord("true", true, TokenKind.True);
TestReservedWord("false", false, TokenKind.False);
TestReservedWord("not", "not", TokenKind.Not);
TestReservedWord("and", "and", TokenKind.And);
TestReservedWord("or", "or", TokenKind.Or);
TestReservedWord("not", null, TokenKind.Not);
TestReservedWord("and", null, TokenKind.And);
TestReservedWord("or", null, TokenKind.Or);
}
private void TestReservedWord(string expression, object value, TokenKind expectedTokenKind) {
@@ -58,7 +58,7 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
[Test]
public void LexerShouldProcesSequenceOfTokens2() {
CheckTokenSequence("1+2*3", TokenKind.NumberLiteral, TokenKind.Plus, TokenKind.NumberLiteral, TokenKind.Mul, TokenKind.NumberLiteral);
CheckTokenSequence("1+2*3", TokenKind.Integer, TokenKind.Plus, TokenKind.Integer, TokenKind.Mul, TokenKind.Integer);
}

View File

@@ -10,7 +10,7 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandConstantExpressions() {
var tree = new ExpressionParser("true").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.ContantExpression), true,
"const", true,
});
}
@@ -18,9 +18,9 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandBinaryExpressions() {
var tree = new ExpressionParser("true+true").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.ContantExpression), true,
typeof(ExpressionTree.ContantExpression), true,
"binop", TokenKind.Plus,
"const", true,
"const", true,
});
}
@@ -28,11 +28,11 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandOperatorPrecedence() {
var tree = new ExpressionParser("1+2*3").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.ContantExpression), 1,
typeof(ExpressionTree.BinaryExpression), TokenKind.Mul,
typeof(ExpressionTree.ContantExpression), 2,
typeof(ExpressionTree.ContantExpression), 3,
"binop", TokenKind.Plus,
"const", 1,
"binop", TokenKind.Mul,
"const", 2,
"const", 3,
});
}
@@ -40,11 +40,11 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandOperatorPrecedence2() {
var tree = new ExpressionParser("1*2+3").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.BinaryExpression), TokenKind.Mul,
typeof(ExpressionTree.ContantExpression), 1,
typeof(ExpressionTree.ContantExpression), 2,
typeof(ExpressionTree.ContantExpression), 3,
"binop", TokenKind.Plus,
"binop", TokenKind.Mul,
"const", 1,
"const", 2,
"const", 3,
});
}
@@ -52,10 +52,10 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandOperatorPrecedence3() {
var tree = new ExpressionParser("not true or true").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Or,
typeof(ExpressionTree.UnaryExpression), TokenKind.Not,
typeof(ExpressionTree.ContantExpression), true,
typeof(ExpressionTree.ContantExpression), true,
"binop", TokenKind.Or,
"unop", TokenKind.Not,
"const", true,
"const", true,
});
}
@@ -63,10 +63,10 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandOperatorPrecedence4() {
var tree = new ExpressionParser("not (true or true)").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.UnaryExpression), TokenKind.Not,
typeof(ExpressionTree.BinaryExpression), TokenKind.Or,
typeof(ExpressionTree.ContantExpression), true,
typeof(ExpressionTree.ContantExpression), true,
"unop", TokenKind.Not,
"binop", TokenKind.Or,
"const", true,
"const", true,
});
}
@@ -74,11 +74,11 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandParenthesis() {
var tree = new ExpressionParser("1*(2+3)").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Mul,
typeof(ExpressionTree.ContantExpression), 1,
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.ContantExpression), 2,
typeof(ExpressionTree.ContantExpression), 3,
"binop", TokenKind.Mul,
"const", 1,
"binop", TokenKind.Plus,
"const", 2,
"const", 3,
});
}
@@ -86,16 +86,16 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldUnderstandComplexExpressions() {
var tree = new ExpressionParser("not 1 * (2 / 4 * 6 + (3))").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.UnaryExpression), TokenKind.Not,
typeof(ExpressionTree.BinaryExpression), TokenKind.Mul,
typeof(ExpressionTree.ContantExpression), 1,
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.BinaryExpression), TokenKind.Div,
typeof(ExpressionTree.ContantExpression), 2,
typeof(ExpressionTree.BinaryExpression), TokenKind.Mul,
typeof(ExpressionTree.ContantExpression), 4,
typeof(ExpressionTree.ContantExpression), 6,
typeof(ExpressionTree.ContantExpression), 3,
"unop", TokenKind.Not,
"binop", TokenKind.Mul,
"const", 1,
"binop", TokenKind.Plus,
"binop", TokenKind.Div,
"const", 2,
"binop", TokenKind.Mul,
"const", 4,
"const", 6,
"const", 3,
});
}
@@ -103,9 +103,9 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
public void ParserShouldContainErrorExpressions() {
var tree = new ExpressionParser("1 + not 3").Parse();
CheckTree(tree, new object[] {
typeof(ExpressionTree.BinaryExpression), TokenKind.Plus,
typeof(ExpressionTree.ContantExpression), 1,
typeof(ExpressionTree.ErrorExpression),
"binop", TokenKind.Plus,
"const", 1,
"error",
});
}
@@ -119,19 +119,34 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
}
private void CheckExpression(ExpressionTree.Expression expression, int indent, object[] objects, ref int index) {
var type = (Type)objects[index++];
var exprName = (string)objects[index++];
Type type = null;
switch(exprName) {
case "const":
type = typeof(ExpressionTree.ConstantExpression);
break;
case "binop":
type = typeof(ExpressionTree.BinaryExpression);
break;
case "unop":
type = typeof(ExpressionTree.UnaryExpression);
break;
case "error":
type = typeof(ExpressionTree.ErrorExpression);
break;
}
Trace.WriteLine(string.Format("{0}: {1}{2} (Current: {3})", indent, new string(' ', indent * 2), type.Name, expression));
Assert.That(expression.GetType(), Is.EqualTo(type));
if (type == typeof(ExpressionTree.ContantExpression)) {
Assert.That((expression as ExpressionTree.ContantExpression).Value, Is.EqualTo(objects[index++]));
if (exprName == "const") {
Assert.That((expression as ExpressionTree.ConstantExpression).Value, Is.EqualTo(objects[index++]));
}
else if (type == typeof(ExpressionTree.BinaryExpression)) {
else if (exprName == "binop") {
Assert.That((expression as ExpressionTree.BinaryExpression).Operator.Kind, Is.EqualTo(objects[index++]));
}
else if (type == typeof(ExpressionTree.UnaryExpression)) {
else if (exprName == "unop") {
Assert.That((expression as ExpressionTree.UnaryExpression).Operator.Kind, Is.EqualTo(objects[index++]));
}

View File

@@ -109,17 +109,25 @@ namespace Orchard.Widgets.SimpleScripting {
case TokenKind.False:
case TokenKind.SingleQuotedStringLiteral:
case TokenKind.StringLiteral:
case TokenKind.NumberLiteral:
_lexer.NextToken();
return new ExpressionTree.ContantExpression(token);
case TokenKind.Integer:
return ProduceConstant(token);
case TokenKind.OpenParen:
return ParseParenthesizedExpression();
default:
return ProduceError(token);
}
}
private ExpressionTree.Expression ProduceConstant(ExpressionTokenizer.Token token) {
_lexer.NextToken();
return new ExpressionTree.ConstantExpression(token);
}
private ExpressionTree.Expression ProduceError(ExpressionTokenizer.Token token) {
_lexer.NextToken();
return new ExpressionTree.ErrorExpression(token,
string.Format("Unexptected token in primary expression ({0})", token));
}
}
private ExpressionTree.Expression ParseParenthesizedExpression() {
Match(TokenKind.OpenParen);

View File

@@ -6,6 +6,7 @@ namespace Orchard.Widgets.SimpleScripting {
private readonly string _expression;
private readonly StringBuilder _stringBuilder;
private int _index;
private int _startTokenIndex;
public ExpressionTokenizer(string expression) {
_expression = expression;
@@ -17,6 +18,7 @@ namespace Orchard.Widgets.SimpleScripting {
return CreateToken(TokenKind.Eof);
LexAgain:
_startTokenIndex = _index;
char ch = Character();
switch (ch) {
case '(':
@@ -84,7 +86,7 @@ namespace Orchard.Widgets.SimpleScripting {
_stringBuilder.Append(Character());
}
else {
return CreateToken(TokenKind.NumberLiteral, Int32.Parse(_stringBuilder.ToString()));
return CreateToken(TokenKind.Integer, Int32.Parse(_stringBuilder.ToString()));
}
}
}
@@ -96,11 +98,11 @@ namespace Orchard.Widgets.SimpleScripting {
case "false":
return CreateToken(TokenKind.False, false);
case "or":
return CreateToken(TokenKind.Or, identifier);
return CreateToken(TokenKind.Or, null);
case "and":
return CreateToken(TokenKind.And, identifier);
return CreateToken(TokenKind.And, null);
case "not":
return CreateToken(TokenKind.Not, identifier);
return CreateToken(TokenKind.Not, null);
default:
return CreateToken(TokenKind.Identifier, identifier);
}
@@ -201,7 +203,7 @@ namespace Orchard.Widgets.SimpleScripting {
private Token CreateToken(TokenKind kind, object value = null) {
return new Token {
Kind = kind,
Position = _index,
Position = _startTokenIndex,
Value = value
};
}
@@ -216,7 +218,7 @@ namespace Orchard.Widgets.SimpleScripting {
public object Value { get; set; }
public override string ToString() {
return string.Format("{0} at position {1}", Value ?? Kind, Position);
return string.Format("{0} ({1}) at position {2}", Kind, Value ?? "<noval>", Position);
}
}
}

View File

@@ -24,11 +24,7 @@ namespace Orchard.Widgets.SimpleScripting {
var ewt = (this as IExpressionWithToken);
if (ewt != null) {
sb.Append(" - ");
sb.Append(ewt.Token.Kind);
if (ewt.Token.Value != null) {
sb.Append(" - ");
sb.Append(ewt.Token.Value);
}
sb.Append(ewt.Token);
}
return sb.ToString();
}
@@ -57,10 +53,10 @@ namespace Orchard.Widgets.SimpleScripting {
}
public class ContantExpression : Expression, IExpressionWithToken {
public class ConstantExpression : Expression, IExpressionWithToken {
private readonly ExpressionTokenizer.Token _token;
public ContantExpression(ExpressionTokenizer.Token token) {
public ConstantExpression(ExpressionTokenizer.Token token) {
_token = token;
}

View File

@@ -5,7 +5,7 @@
CloseParen,
StringLiteral,
SingleQuotedStringLiteral,
NumberLiteral,
Integer,
Plus,
Minus,
Mul,