diff options
| author | mokha <mokha@cisco.com> | 2019-05-14 21:12:37 -0600 |
|---|---|---|
| committer | mokha <mokha@cisco.com> | 2019-05-14 21:12:37 -0600 |
| commit | e31832068a8cb77cd346d9001a215b574070b761 (patch) | |
| tree | 2b0e7fb453f0cd1300a246caf9d8d4db666dafb7 | |
| parent | 7f7bdb2be416cb111c5d2d635343c42e5e0d4caa (diff) | |
start to implement a small transaction
| -rw-r--r-- | lib/mpeg.rb | 1 | ||||
| -rw-r--r-- | lib/mpeg/base.rb | 5 | ||||
| -rw-r--r-- | lib/mpeg/input.rb | 16 | ||||
| -rw-r--r-- | lib/mpeg/lookahead.rb | 7 | ||||
| -rw-r--r-- | lib/mpeg/sequence.rb | 6 | ||||
| -rw-r--r-- | lib/mpeg/transaction.rb | 19 | ||||
| -rw-r--r-- | spec/lookahead_spec.rb | 14 | ||||
| -rw-r--r-- | spec/sequence_spec.rb | 19 |
8 files changed, 82 insertions, 5 deletions
diff --git a/lib/mpeg.rb b/lib/mpeg.rb index c53cf89..a785c98 100644 --- a/lib/mpeg.rb +++ b/lib/mpeg.rb @@ -11,6 +11,7 @@ require "mpeg/repitition" require "mpeg/sequence" require "mpeg/slice" require "mpeg/str" +require "mpeg/transaction" module Mpeg class Error < StandardError; end diff --git a/lib/mpeg/base.rb b/lib/mpeg/base.rb index f8f97c5..e2e8563 100644 --- a/lib/mpeg/base.rb +++ b/lib/mpeg/base.rb @@ -1,8 +1,7 @@ module Mpeg class Base - def parse(string) - input = Input.new(string) - call(input) && input.end? + def parse(string, input: Input.new(string)) + call(input) && input.end_of_string? end def repeat(min = 0, max = nil) diff --git a/lib/mpeg/input.rb b/lib/mpeg/input.rb index 1a36fe6..7fd185b 100644 --- a/lib/mpeg/input.rb +++ b/lib/mpeg/input.rb @@ -14,8 +14,22 @@ module Mpeg Slice.new(position, slice) end - def end? + def rewind + transaction do |_| + yield + end + end + + def transaction(&block) + Transaction.new(@scanner).run(&block) + end + + def end_of_string? @scanner.eos? end + + def position + @scanner.pos + end end end diff --git a/lib/mpeg/lookahead.rb b/lib/mpeg/lookahead.rb index 7fcbf3d..19e1876 100644 --- a/lib/mpeg/lookahead.rb +++ b/lib/mpeg/lookahead.rb @@ -4,5 +4,12 @@ module Mpeg @parser = parser @positive = positive end + + def call(input) + input.rewind do + result = @parser.call(input) + @positive ? result : (result ? false : true) + end + end end end diff --git a/lib/mpeg/sequence.rb b/lib/mpeg/sequence.rb index e3823de..9172370 100644 --- a/lib/mpeg/sequence.rb +++ b/lib/mpeg/sequence.rb @@ -6,7 +6,11 @@ module Mpeg end def call(input) - @left.call(input) && @right.call(input) + input.transaction do |x| + result = @left.call(input) && @right.call(input) + x.commit! if result + result + end end end end diff --git a/lib/mpeg/transaction.rb b/lib/mpeg/transaction.rb new file mode 100644 index 0000000..718352c --- /dev/null +++ b/lib/mpeg/transaction.rb @@ -0,0 +1,19 @@ +module Mpeg + class Transaction + def initialize(scanner) + @scanner = scanner + @rewind_position = @scanner.pos + @commit = false + end + + def commit! + @commit = true + end + + def run(&block) + block.call(self) + ensure + @scanner.pos = @rewind_position unless @commit + end + end +end diff --git a/spec/lookahead_spec.rb b/spec/lookahead_spec.rb new file mode 100644 index 0000000..391df07 --- /dev/null +++ b/spec/lookahead_spec.rb @@ -0,0 +1,14 @@ +RSpec.describe Mpeg::Lookahead do + def str(string) + Mpeg::Str.new(string) + end + + def any + Mpeg::Re.new('.') + end + + subject { str('"').absent? >> any.repeat } + + specify { expect(subject.parse('"Hello')).to be_falsey } + specify { expect(subject.parse('Hello')).to be_truthy } +end diff --git a/spec/sequence_spec.rb b/spec/sequence_spec.rb new file mode 100644 index 0000000..31041db --- /dev/null +++ b/spec/sequence_spec.rb @@ -0,0 +1,19 @@ +RSpec.describe Mpeg::Sequence do + subject { Mpeg::Str.new('h') >> Mpeg::Str.new('i') } + + context "when the sequence does match" do + let(:input) { Mpeg::Input.new('hi') } + let!(:result) { subject.parse('hi', input: input) } + + specify { expect(result).to be_truthy } + specify { expect(input).to be_end_of_string } + end + + context "when the sequence does not match" do + let(:input) { Mpeg::Input.new('hello') } + let!(:result) { subject.parse('hello', input: input) } + + specify { expect(result).to be_falsey } + specify { expect(input.position).to be_zero } + end +end |
