Permalink
Browse files

Added specs for semantic predicates

  • Loading branch information...
cjheath committed Sep 4, 2009
1 parent dc2952a commit b7262dc125571ec1da69a5bd373c1879d7392e74
Showing with 176 additions and 1 deletion.
  1. +1 −1 lib/treetop/version.rb
  2. +175 −0 spec/compiler/semantic_predicate_spec.rb
View
@@ -2,7 +2,7 @@ module Treetop #:nodoc:
module VERSION #:nodoc:
MAJOR = 1
MINOR = 4
- TINY = 0
+ TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
end
@@ -0,0 +1,175 @@
+require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
+
+module SemanticPredicateSpec
+ describe "An &-predicate block" do
+ testing_expression '& {|| $ok_to_succeed}'
+
+ it "succeeds if it returns true, returning an epsilon syntax node" do
+ $ok_to_succeed = true
+ parse('foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.interval.should == (0...0)
+ end
+ end
+
+ it "fails if it returns false" do
+ $ok_to_succeed = false
+ parse('foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ end
+
+ describe "A sequence of a terminal and an &-predicate block" do
+ testing_expression '"prior " &{|s| $value = s[0].text_value; $ok_to_succeed }'
+
+ it "matches the input terminal and consumes it if the block returns true, seeing the terminal in the sequence" do
+ $ok_to_succeed = true
+ $value = nil
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.elements[0].text_value.should == "prior "
+ result.text_value.should == 'prior '
+ $value.should == 'prior '
+ end
+ end
+
+ it "fails if the block returns false, but sees the terminal in the sequence" do
+ $ok_to_succeed = false
+ $value = nil
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ $value.should == 'prior '
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ end
+
+ describe "A sequence of an optional terminal and an &-predicate block" do
+ testing_expression '"prior "? &{|s| $value = s[0].text_value; $ok_to_succeed}'
+
+ it "matches the input terminal and consumes it if the block returns true" do
+ $ok_to_succeed = true
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.elements[0].text_value.should == "prior "
+ result.text_value.should == 'prior '
+ $value.should == 'prior '
+ end
+ end
+
+ it "fails with no terminal_failures if the block returns false" do
+ $ok_to_succeed = false
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ $value.should == 'prior '
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ it "fail and return the expected optional preceeding terminal as expected input if the block returns false" do
+ $ok_to_succeed = false
+ parse('foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 1
+ failure = terminal_failures[0]
+ failure.index.should == 0
+ failure.expected_string.should == 'prior '
+ end
+ end
+
+ end
+
+ describe "A !-predicate block" do
+ testing_expression '! {|| $ok_to_succeed}'
+
+ it "succeeds if it returns false, returning an epsilon syntax node" do
+ $ok_to_succeed = false
+ parse('foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.interval.should == (0...0)
+ end
+ end
+
+ it "fails if it returns true" do
+ $ok_to_succeed = true
+ parse('foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ end
+
+ describe "A sequence of a terminal and an !-predicate block" do
+ testing_expression '"prior " !{|s| $value = s[0].text_value; $ok_to_succeed }'
+
+ it "matches the input terminal and consumes it if the block returns false, seeing the terminal in the sequence" do
+ $ok_to_succeed = false
+ $value = nil
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.elements[0].text_value.should == "prior "
+ result.text_value.should == 'prior '
+ $value.should == 'prior '
+ end
+ end
+
+ it "fails if the block returns true, but sees the terminal in the sequence" do
+ $ok_to_succeed = true
+ $value = nil
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ $value.should == 'prior '
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ end
+
+ describe "A sequence of an optional terminal and an !-predicate block" do
+ testing_expression '"prior "? !{|s| $value = s[0].text_value; $ok_to_succeed}'
+
+ it "matches the input terminal and consumes it if the block returns false" do
+ $ok_to_succeed = false
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should_not be_nil
+ result.elements[0].text_value.should == "prior "
+ result.text_value.should == 'prior '
+ $value.should == 'prior '
+ end
+ end
+
+ it "fails with no terminal_failures if the block returns true" do
+ $ok_to_succeed = true
+ parse('prior foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ $value.should == 'prior '
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 0
+ end
+ end
+
+ it "fail and return the expected optional preceeding terminal as expected input if the block returns true" do
+ $ok_to_succeed = true
+ parse('foo', :consume_all_input => false) do |result|
+ result.should be_nil
+ terminal_failures = parser.terminal_failures
+ terminal_failures.size.should == 1
+ failure = terminal_failures[0]
+ failure.index.should == 0
+ failure.expected_string.should == 'prior '
+ end
+ end
+
+ end
+end

0 comments on commit b7262dc

Please sign in to comment.