This operator allows to find if the left operand is in the right one.
The left operand must be resort to a string, but the right operand can be:
* a string
* an array
* a hash (the search is done on the keys)
This syntax can be used in any place where an expression is supported.
Syntax:
$eatme = 'eat'
if $eatme in ['ate', 'eat'] {
...
}
$value = 'beat generation'
if 'eat' in $value {
notice("on the road")
}
Signed-off-by: Brice Figureau <[email protected]>
---
lib/puppet/parser/ast.rb | 1 +
lib/puppet/parser/ast/in_operator.rb | 26 +
lib/puppet/parser/grammar.ra | 6 +-
lib/puppet/parser/lexer.rb | 3 +-
lib/puppet/parser/parser.rb | 2044 +++++++++++++++++-----------------
spec/unit/parser/ast/in_operator.rb | 60 +
spec/unit/parser/lexer.rb | 3 +-
7 files changed, 1128 insertions(+), 1015 deletions(-)
create mode 100644 lib/puppet/parser/ast/in_operator.rb
create mode 100644 spec/unit/parser/ast/in_operator.rb
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index 06adb8b..5a8f7be 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -103,6 +103,7 @@ require 'puppet/parser/ast/comparison_operator'
require 'puppet/parser/ast/else'
require 'puppet/parser/ast/function'
require 'puppet/parser/ast/ifstatement'
+require 'puppet/parser/ast/in_operator'
require 'puppet/parser/ast/leaf'
require 'puppet/parser/ast/match_operator'
require 'puppet/parser/ast/minus'
diff --git a/lib/puppet/parser/ast/in_operator.rb
b/lib/puppet/parser/ast/in_operator.rb
new file mode 100644
index 0000000..0f543af
--- /dev/null
+++ b/lib/puppet/parser/ast/in_operator.rb
@@ -0,0 +1,26 @@
+require 'puppet'
+require 'puppet/parser/ast/branch'
+
+class Puppet::Parser::AST
+ class InOperator < AST::Branch
+
+ attr_accessor :lval, :rval
+
+ # Returns a boolean which is the result of the 'in' operation
+ # of lval and rval operands
+ def evaluate(scope)
+
+ # evaluate the operands, should return a boolean value
+ lval = @lval.safeevaluate(scope)
+ unless lval.is_a?(::String)
+ raise ArgumentError, "'#{lval}' from left operand of 'in'
expression is not a string"
+ end
+
+ rval = @rval.safeevaluate(scope)
+ unless rval.respond_to?(:include?)
+ raise ArgumentError, "'#{rval}' from right operand of 'in'
expression is not of a supported type (string, array or hash)"
+ end
+ return rval.include?(lval)
+ end
+ end
+end
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index c505556..1e14aff 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -12,11 +12,12 @@ token IF ELSE IMPORT DEFINE ELSIF VARIABLE CLASS INHERITS
NODE BOOLEAN
token NAME SEMIC CASE DEFAULT AT LCOLLECT RCOLLECT CLASSNAME CLASSREF
token NOT OR AND UNDEF PARROW PLUS MINUS TIMES DIV LSHIFT RSHIFT UMINUS
token MATCH NOMATCH REGEX IN_EDGE OUT_EDGE IN_EDGE_SUB OUT_EDGE_SUB
+token IN
prechigh
right NOT
nonassoc UMINUS
- left MATCH NOMATCH
+ left IN MATCH NOMATCH
left TIMES DIV
left MINUS PLUS
left LSHIFT RSHIFT
@@ -510,6 +511,9 @@ else: # nothing
# per operator :-(
expression: rvalue
+ | expression IN rvalue {
+ result = ast AST::InOperator, :lval => val[0], :rval => val[2]
+}
| expression MATCH regex {
result = ast AST::MatchOperator, :operator => val[1][:value], :lval =>
val[0], :rval => val[2]
}
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index def4621..951fc92 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -264,7 +264,8 @@ class Puppet::Parser::Lexer
"or" => :OR,
"undef" => :UNDEF,
"false" => :FALSE,
- "true" => :TRUE
+ "true" => :TRUE,
+ "in" => :IN
)
def clear
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 1ada48f..761339e 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
diff --git a/spec/unit/parser/ast/in_operator.rb
b/spec/unit/parser/ast/in_operator.rb
[parser.rb elided]
new file mode 100644
index 0000000..df73645
--- /dev/null
+++ b/spec/unit/parser/ast/in_operator.rb
@@ -0,0 +1,60 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/parser/ast/in_operator'
+
+describe Puppet::Parser::AST::InOperator do
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+
+ @lval = stub 'lval'
+ @lval.stubs(:safeevaluate).with(@scope).returns("left")
+
+ @rval = stub 'rval'
+ @rval.stubs(:safeevaluate).with(@scope).returns("right")
+
+ @operator = Puppet::Parser::AST::InOperator.new :lval => @lval, :rval
=> @rval
+ end
+
+ it "should evaluate the left operand" do
+ @lval.expects(:safeevaluate).with(@scope).returns("string")
+
+ @operator.evaluate(@scope)
+ end
+
+ it "should evaluate the right operand" do
+ @rval.expects(:safeevaluate).with(@scope).returns("string")
+
+ @operator.evaluate(@scope)
+ end
+
+ it "should raise an argument error if lval is not a string" do
+ @lval.expects(:safeevaluate).with(@scope).returns([12,13])
+
+ lambda { @operator.evaluate(@scope) }.should raise_error
+ end
+
+ it "should raise an argument error if rval doesn't support the include?
method" do
+ @rval.expects(:safeevaluate).with(@scope).returns(stub 'value')
+
+ lambda { @operator.evaluate(@scope) }.should raise_error
+ end
+
+ it "should not raise an argument error if rval supports the include?
method" do
+ @rval.expects(:safeevaluate).with(@scope).returns(stub 'value',
:include? => true)
+
+ lambda { @operator.evaluate(@scope) }.should_not raise_error
+ end
+
+ it "should return rval.include?(lval)" do
+ lval = stub 'lvalue', :is_a? => true
+ @lval.stubs(:safeevaluate).with(@scope).returns(lval)
+
+ rval = stub 'rvalue'
+ @rval.stubs(:safeevaluate).with(@scope).returns(rval)
+ rval.expects(:include?).with(lval).returns(:result)
+
+ @operator.evaluate(@scope).should == :result
+ end
+end
diff --git a/spec/unit/parser/lexer.rb b/spec/unit/parser/lexer.rb
index b1524f1..a27dac0 100755
--- a/spec/unit/parser/lexer.rb
+++ b/spec/unit/parser/lexer.rb
@@ -203,7 +203,8 @@ describe Puppet::Parser::Lexer::TOKENS do
"or" => :OR,
"undef" => :UNDEF,
"false" => :FALSE,
- "true" => :TRUE
+ "true" => :TRUE,
+ "in" => :IN,
}.each do |string, name|
it "should have a keyword named #{name.to_s}" do
Puppet::Parser::Lexer::KEYWORDS[name].should_not be_nil
--
1.6.6.1
--
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en.