Implement parsing of relational operators

--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-11-28 16:59:45 -08:00
parent ffe6c88038
commit ea049d28d0
3 changed files with 131 additions and 24 deletions

View File

@@ -110,6 +110,100 @@ namespace Orchard.Tests.Modules.Scripting {
}); });
} }
[Test]
public void ParserShouldUnderstandRelationalOperators() {
var tree = new Parser("true == true").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.EqualEqual,
"const", true,
"const", true,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperators2() {
var tree = new Parser("1 != 2").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.NotEqual,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperators3() {
var tree = new Parser("1 < 2").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.LessThan,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperators4() {
var tree = new Parser("1 <= 2").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.LessThanEqual,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperators5() {
var tree = new Parser("1 > 2").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.GreaterThan,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperators6() {
var tree = new Parser("1 >= 2").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.GreaterThanEqual,
"const", 1,
"const", 2,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperatorPrecedence() {
var tree = new Parser("1 < 2 or 2 > 3 and !false").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.Or,
"binop", TokenKind.LessThan,
"const", 1,
"const", 2,
"binop", TokenKind.And,
"binop", TokenKind.GreaterThan,
"const", 2,
"const", 3,
"unop", TokenKind.NotSign,
"const", false,
});
}
[Test]
public void ParserShouldUnderstandRelationalOperatorPrecedence2() {
var tree = new Parser("1 < 2 and 2 > 3 or !false").Parse();
CheckTree(tree, new object[] {
"binop", TokenKind.And,
"binop", TokenKind.LessThan,
"const", 1,
"const", 2,
"binop", TokenKind.Or,
"binop", TokenKind.GreaterThan,
"const", 2,
"const", 3,
"unop", TokenKind.NotSign,
"const", false,
});
}
[Test] [Test]
public void ParserShouldUnderstandParenthesis() { public void ParserShouldUnderstandParenthesis() {
var tree = new Parser("1*(2+3)").Parse(); var tree = new Parser("1*(2+3)").Parse();
@@ -177,6 +271,8 @@ namespace Orchard.Tests.Modules.Scripting {
case "error": case "error":
type = typeof(ErrorAstNode); type = typeof(ErrorAstNode);
break; break;
default:
throw new InvalidOperationException(string.Format("Test error: unrecognized expression type abbreviation '{0}'", exprName));
} }
Trace.WriteLine(string.Format("{0}: {1}{2} (Current: {3})", indent, new string(' ', indent * 2), type.Name, astNode)); Trace.WriteLine(string.Format("{0}: {1}{2} (Current: {3})", indent, new string(' ', indent * 2), type.Name, astNode));

View File

@@ -6,7 +6,7 @@ namespace Orchard.Scripting.Ast {
private readonly AstNode _operand; private readonly AstNode _operand;
private readonly Token _token; private readonly Token _token;
public UnaryAstNode(AstNode operand, Token token) { public UnaryAstNode(Token token, AstNode operand) {
_operand = operand; _operand = operand;
_token = token; _token = token;
} }

View File

@@ -22,28 +22,11 @@ namespace Orchard.Scripting.Compiler {
} }
private AstNode ParseKeywordLogicalExpression() { private AstNode ParseKeywordLogicalExpression() {
return ParseKeywordOrExpression();
}
private AstNode ParseKeywordOrExpression() {
var expr = ParseKeywordAndExpression();
var token = IsMatch(TokenKind.Or);
if (token != null) {
var right = ParseKeywordOrExpression();
expr = new BinaryAstNode(expr, token, right);
}
return expr;
}
private AstNode ParseKeywordAndExpression() {
var expr = ParseKeywordNotExpression(); var expr = ParseKeywordNotExpression();
var token = IsMatch(TokenKind.And); var token = IsMatch(TokenKind.Or, TokenKind.And);
if (token != null) { if (token != null) {
var right = ParseKeywordAndExpression(); var right = ParseKeywordLogicalExpression();
expr = new BinaryAstNode(expr, token, right); expr = new BinaryAstNode(expr, token, right);
} }
@@ -56,15 +39,37 @@ namespace Orchard.Scripting.Compiler {
if (token != null) { if (token != null) {
var expr = ParseKeywordNotExpression(); var expr = ParseKeywordNotExpression();
return new UnaryAstNode(expr, token); return new UnaryAstNode(token, expr);
} }
return ParseRelationalExpression(); return ParseEqualityExpression();
}
private AstNode ParseEqualityExpression() {
var expr = ParseRelationalExpression();
var token = IsMatch(TokenKind.EqualEqual, TokenKind.NotEqual);
if (token != null) {
var right = ParseEqualityExpression();
expr = new BinaryAstNode(expr, token, right);
}
return expr;
} }
private AstNode ParseRelationalExpression() { private AstNode ParseRelationalExpression() {
var expr = ParseAdditiveExpression(); var expr = ParseAdditiveExpression();
//TODO
var token =
IsMatch(TokenKind.LessThan, TokenKind.LessThanEqual) ??
IsMatch(TokenKind.GreaterThan, TokenKind.GreaterThanEqual);
if (token != null) {
var right = ParseRelationalExpression();
expr = new BinaryAstNode(expr, token, right);
}
return expr; return expr;
} }
@@ -95,7 +100,13 @@ namespace Orchard.Scripting.Compiler {
} }
private AstNode ParseUnaryExpression() { private AstNode ParseUnaryExpression() {
//TODO var token = IsMatch(TokenKind.NotSign);
if (token != null) {
var expr = ParseUnaryExpression();
return new UnaryAstNode(token, expr);
}
return ParsePrimaryExpression(); return ParsePrimaryExpression();
} }