diff --git a/src/Orchard.Tests.Modules/SimpleScripting/EvaluatorTests.cs b/src/Orchard.Tests.Modules/SimpleScripting/EvaluatorTests.cs
index e7da077a0..8c99c148a 100644
--- a/src/Orchard.Tests.Modules/SimpleScripting/EvaluatorTests.cs
+++ b/src/Orchard.Tests.Modules/SimpleScripting/EvaluatorTests.cs
@@ -1,10 +1,8 @@
-using System;
-using System.Diagnostics;
+using System.Diagnostics;
using NUnit.Framework;
-using Orchard.Widgets.SimpleScripting;
using Orchard.Widgets.SimpleScripting.Compiler;
-namespace Orchard.Tests.Modules.SimpleScriptingTests {
+namespace Orchard.Tests.Modules.SimpleScripting {
[TestFixture]
public class EvaluatorTests {
[Test]
diff --git a/src/Orchard.Tests.Modules/SimpleScripting/ParserTests.cs b/src/Orchard.Tests.Modules/SimpleScripting/ParserTests.cs
index 86480a851..9ba3c1436 100644
--- a/src/Orchard.Tests.Modules/SimpleScripting/ParserTests.cs
+++ b/src/Orchard.Tests.Modules/SimpleScripting/ParserTests.cs
@@ -1,11 +1,10 @@
using System;
using System.Diagnostics;
using NUnit.Framework;
-using Orchard.Widgets.SimpleScripting;
using Orchard.Widgets.SimpleScripting.Ast;
using Orchard.Widgets.SimpleScripting.Compiler;
-namespace Orchard.Tests.Modules.SimpleScriptingTests {
+namespace Orchard.Tests.Modules.SimpleScripting {
[TestFixture]
public class ParserTests {
[Test]
@@ -26,6 +25,37 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
});
}
+ [Test]
+ public void ParserShouldUnderstandCommandExpressions() {
+ var tree = new Parser("print 'foo', 'bar'").Parse();
+ CheckTree(tree, new object[] {
+ "call", TokenKind.Identifier, "print",
+ "const", "foo",
+ "const", "bar",
+ });
+ }
+
+ [Test]
+ public void ParserShouldUnderstandCallExpressions() {
+ var tree = new Parser("print('foo', 'bar')").Parse();
+ CheckTree(tree, new object[] {
+ "call", TokenKind.Identifier, "print",
+ "const", "foo",
+ "const", "bar",
+ });
+ }
+
+ [Test]
+ public void ParserShouldUnderstandCallExpressions2() {
+ var tree = new Parser("print 1+2").Parse();
+ CheckTree(tree, new object[] {
+ "call", TokenKind.Identifier, "print",
+ "binop", TokenKind.Plus,
+ "const", 1,
+ "const", 2,
+ });
+ }
+
[Test]
public void ParserShouldUnderstandOperatorPrecedence() {
var tree = new Parser("1+2*3").Parse();
@@ -123,7 +153,7 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
private void CheckExpression(AstNode astNode, int indent, object[] objects, ref int index) {
var exprName = (string)objects[index++];
Type type = null;
- switch(exprName) {
+ switch (exprName) {
case "const":
type = typeof(ConstantAstNode);
break;
@@ -133,6 +163,9 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
case "unop":
type = typeof(UnaryAstNode);
break;
+ case "call":
+ type = typeof(MethodCallAstNode);
+ break;
case "error":
type = typeof(ErrorAstNode);
break;
@@ -151,8 +184,12 @@ namespace Orchard.Tests.Modules.SimpleScriptingTests {
else if (exprName == "unop") {
Assert.That((astNode as UnaryAstNode).Operator.Kind, Is.EqualTo(objects[index++]));
}
+ else if (exprName == "call") {
+ Assert.That((astNode as MethodCallAstNode).Token.Kind, Is.EqualTo(objects[index++]));
+ Assert.That((astNode as MethodCallAstNode).Token.Value, Is.EqualTo(objects[index++]));
+ }
- foreach(var child in astNode.Children) {
+ foreach (var child in astNode.Children) {
CheckExpression(child, indent + 1, objects, ref index);
}
}
diff --git a/src/Orchard.Tests.Modules/SimpleScripting/TokenizerTests.cs b/src/Orchard.Tests.Modules/SimpleScripting/TokenizerTests.cs
index 8504b453b..7286e58cd 100644
--- a/src/Orchard.Tests.Modules/SimpleScripting/TokenizerTests.cs
+++ b/src/Orchard.Tests.Modules/SimpleScripting/TokenizerTests.cs
@@ -1,8 +1,7 @@
using NUnit.Framework;
-using Orchard.Widgets.SimpleScripting;
using Orchard.Widgets.SimpleScripting.Compiler;
-namespace Orchard.Tests.Modules.SimpleScriptingTests {
+namespace Orchard.Tests.Modules.SimpleScripting {
[TestFixture]
public class TokenizerTests {
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
index df88d2065..66b4c5264 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj
@@ -80,6 +80,7 @@
+
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/AstVisitor.cs b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/AstVisitor.cs
index e91d3ec69..6999d25f2 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/AstVisitor.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/AstVisitor.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Linq;
namespace Orchard.Widgets.SimpleScripting.Ast {
public class AstVisitor {
@@ -28,5 +25,9 @@ namespace Orchard.Widgets.SimpleScripting.Ast {
public virtual object VisitUnary(UnaryAstNode node) {
return null;
}
+
+ public virtual object VisitMethodCall(MethodCallAstNode node) {
+ return null;
+ }
}
}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/MethodCallAstNode.cs b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/MethodCallAstNode.cs
new file mode 100644
index 000000000..d77d1004a
--- /dev/null
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Ast/MethodCallAstNode.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using Orchard.Widgets.SimpleScripting.Compiler;
+
+namespace Orchard.Widgets.SimpleScripting.Ast {
+ public class MethodCallAstNode : AstNode, IAstNodeWithToken {
+ private readonly Token _token;
+ private readonly IList _arguments;
+
+ public MethodCallAstNode(Token token, IList arguments) {
+ _token = token;
+ _arguments = arguments;
+ }
+
+ public Token Token { get { return _token; } }
+
+ public override IEnumerable Children {
+ get { return _arguments; }
+ }
+
+ public override object Accept(AstVisitor visitor) {
+ return visitor.VisitMethodCall(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Parser.cs b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Parser.cs
index 79e230629..35b8b1b2d 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Parser.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Parser.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Orchard.Widgets.SimpleScripting.Ast;
namespace Orchard.Widgets.SimpleScripting.Compiler {
@@ -29,8 +30,7 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
var expr = ParseKeywordAndExpression();
var token = IsMatch(TokenKind.Or);
- if (token != null)
- {
+ if (token != null) {
var right = ParseKeywordOrExpression();
expr = new BinaryAstNode(expr, token, right);
@@ -56,7 +56,7 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
var token = IsMatch(TokenKind.Not);
if (token != null) {
var expr = ParseKeywordNotExpression();
-
+
return new UnaryAstNode(expr, token);
}
@@ -66,8 +66,6 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
private AstNode ParseRelationalExpression() {
var expr = ParseAdditiveExpression();
//TODO
- //var Token = IsMatch(TokenKind.Not);
- //if (Token != null) {
return expr;
}
@@ -104,7 +102,7 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
private AstNode ParsePrimaryExpression() {
var token = _lexer.Token();
- switch(_lexer.Token().Kind) {
+ switch (_lexer.Token().Kind) {
case TokenKind.True:
case TokenKind.False:
case TokenKind.SingleQuotedStringLiteral:
@@ -113,11 +111,41 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
return ProduceConstant(token);
case TokenKind.OpenParen:
return ParseParenthesizedExpression();
+ case TokenKind.Identifier:
+ return ParseMethodCallExpression();
default:
return ProduceError(token);
}
}
+ private AstNode ParseParenthesizedExpression() {
+ Match(TokenKind.OpenParen);
+ var expr = ParseExpression();
+ Match(TokenKind.CloseParen);
+ return expr;
+ }
+
+ private AstNode ParseMethodCallExpression() {
+ var target = _lexer.Token();
+ _lexer.NextToken();
+
+ bool hasParenthesis = (IsMatch(TokenKind.OpenParen) != null);
+
+ var arguments = new List();
+ while (true) {
+ var argument = ParseExpression();
+ arguments.Add(argument);
+
+ if (IsMatch(TokenKind.Comma) == null)
+ break;
+ }
+
+ if (hasParenthesis)
+ Match(TokenKind.CloseParen);
+
+ return new MethodCallAstNode(target, arguments);
+ }
+
private AstNode ProduceConstant(Token token) {
_lexer.NextToken();
return new ConstantAstNode(token);
@@ -125,15 +153,7 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
private AstNode ProduceError(Token token) {
_lexer.NextToken();
- return new ErrorAstNode(token,
- string.Format("Unexptected Token in primary expression ({0})", token));
- }
-
- private AstNode ParseParenthesizedExpression() {
- Match(TokenKind.OpenParen);
- var expr = ParseExpression();
- Match(TokenKind.CloseParen);
- return expr;
+ return new ErrorAstNode(token, string.Format("Unexptected Token in primary expression ({0})", token));
}
private void Match(TokenKind kind) {
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/TokenKind.cs b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/TokenKind.cs
index 0e6f3023b..dd6f8245e 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/TokenKind.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/TokenKind.cs
@@ -6,6 +6,7 @@
StringLiteral,
SingleQuotedStringLiteral,
Integer,
+ Comma,
Plus,
Minus,
Mul,
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Tokenizer.cs b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Tokenizer.cs
index 2d069154e..94b5952eb 100644
--- a/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Tokenizer.cs
+++ b/src/Orchard.Web/Modules/Orchard.Widgets/SimpleScripting/Compiler/Tokenizer.cs
@@ -27,6 +27,9 @@ namespace Orchard.Widgets.SimpleScripting.Compiler {
case ')':
NextCharacter();
return CreateToken(TokenKind.CloseParen);
+ case ',':
+ NextCharacter();
+ return CreateToken(TokenKind.Comma);
case '+':
NextCharacter();
return CreateToken(TokenKind.Plus);