diff --git a/CHANGELOG.md b/CHANGELOG.md index 45d6914..2d75202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- all expressions now respond to `#negative?` / `#negated?` + - previously only sets, props, and posix classes did +- implemented `#negative?` / `#negated?` for more applicable expressions + - `\B`, `\D`, `\H`, `\S`, `\W`, `(?!...)`, `(? [:root, negative?: false] + include_examples 'parse', /a/, [0] => [:literal, negative?: false] + + include_examples 'parse', /\b/, [0] => [:word_boundary, negative?: false] + include_examples 'parse', /\B/, [0] => [:nonword_boundary, negative?: true] + + include_examples 'parse', /(?=)/, [0] => [:lookahead, negative?: false] + include_examples 'parse', /(?!)/, [0] => [:nlookahead, negative?: true] + + include_examples 'parse', /(?<=)/, [0] => [:lookbehind, negative?: false] + include_examples 'parse', /(? [:nlookbehind, negative?: true] + + include_examples 'parse', /[a]/, [0] => [:character, negative?: false] + include_examples 'parse', /[^a]/, [0] => [:character, negative?: true] + + include_examples 'parse', /\d/, [0] => [:digit, negative?: false] + include_examples 'parse', /\D/, [0] => [:nondigit, negative?: true] + + include_examples 'parse', /[[:word:]]/, [0, 0] => [:word, negative?: false] + include_examples 'parse', /[[:^word:]]/, [0, 0] => [:word, negative?: true] + + include_examples 'parse', /\p{word}/, [0] => [:word, negative?: false] + include_examples 'parse', /\p{^word}/, [0] => [:word, negative?: true] + + include_examples 'parse', //, [] => [:root, negated?: false] + include_examples 'parse', /[^a]/, [0] => [:character, negated?: true] +end diff --git a/spec/parser/posix_classes_spec.rb b/spec/parser/posix_classes_spec.rb index d7b8ea3..b413189 100644 --- a/spec/parser/posix_classes_spec.rb +++ b/spec/parser/posix_classes_spec.rb @@ -3,10 +3,10 @@ RSpec.describe('PosixClass parsing') do include_examples 'parse', /[[:word:]]/, [0] => [CharacterSet, count: 1], - [0, 0] => [:posixclass, :word, PosixClass, name: 'word', text: '[:word:]', negative?: false] + [0, 0] => [:posixclass, :word, PosixClass, name: 'word', text: '[:word:]'] include_examples 'parse', /[[:^word:]]/, [0] => [CharacterSet, count: 1], - [0, 0] => [:nonposixclass, :word, PosixClass, name: 'word', text: '[:^word:]', negative?: true] + [0, 0] => [:nonposixclass, :word, PosixClass, name: 'word', text: '[:^word:]'] # cases treated as regular subsets by Ruby, not as (invalid) posix classes include_examples 'parse', '[[:ab]c:]', diff --git a/spec/parser/properties_spec.rb b/spec/parser/properties_spec.rb index 48652ef..30e5e0e 100644 --- a/spec/parser/properties_spec.rb +++ b/spec/parser/properties_spec.rb @@ -2,32 +2,32 @@ RSpec.describe('Property parsing') do # test various notations supported by Ruby - include_examples 'parse', '\p{sd}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\p{SD}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\p{Soft Dotted}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\p{Soft-Dotted}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\p{sOfT_dOtTeD}', 0 => [:property, :soft_dotted, negative?: false] + include_examples 'parse', '\p{sd}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\p{SD}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\p{Soft Dotted}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\p{Soft-Dotted}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\p{sOfT_dOtTeD}', 0 => [:property, :soft_dotted] # test ^-negation - include_examples 'parse', '\p{^sd}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\p{^SD}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\p{^Soft Dotted}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\p{^Soft-Dotted}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\p{^sOfT_dOtTeD}', 0 => [:nonproperty, :soft_dotted, negative?: true] + include_examples 'parse', '\p{^sd}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\p{^SD}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\p{^Soft Dotted}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\p{^Soft-Dotted}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\p{^sOfT_dOtTeD}', 0 => [:nonproperty, :soft_dotted] # test P-negation - include_examples 'parse', '\P{sd}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\P{SD}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\P{Soft Dotted}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\P{Soft-Dotted}', 0 => [:nonproperty, :soft_dotted, negative?: true] - include_examples 'parse', '\P{sOfT_dOtTeD}', 0 => [:nonproperty, :soft_dotted, negative?: true] + include_examples 'parse', '\P{sd}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\P{SD}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\P{Soft Dotted}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\P{Soft-Dotted}', 0 => [:nonproperty, :soft_dotted] + include_examples 'parse', '\P{sOfT_dOtTeD}', 0 => [:nonproperty, :soft_dotted] # double negation is positive again - include_examples 'parse', '\P{^sd}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\P{^SD}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\P{^Soft Dotted}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\P{^Soft-Dotted}', 0 => [:property, :soft_dotted, negative?: false] - include_examples 'parse', '\P{^sOfT_dOtTeD}', 0 => [:property, :soft_dotted, negative?: false] + include_examples 'parse', '\P{^sd}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\P{^SD}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\P{^Soft Dotted}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\P{^Soft-Dotted}', 0 => [:property, :soft_dotted] + include_examples 'parse', '\P{^sOfT_dOtTeD}', 0 => [:property, :soft_dotted] # test #shortcut include_examples 'parse', '\p{soft_dotted}', 0 => [:property, :soft_dotted, shortcut: 'sd'] diff --git a/spec/parser/set/intersections_spec.rb b/spec/parser/set/intersections_spec.rb index 8ff5c43..e5aa373 100644 --- a/spec/parser/set/intersections_spec.rb +++ b/spec/parser/set/intersections_spec.rb @@ -17,7 +17,7 @@ [0, 0, 0] => [CharacterSet::IntersectedSequence, count: 1], [0, 0, 0, 0] => [CharacterSet::Range, count: 2], [0, 0, 1] => [CharacterSet::IntersectedSequence, count: 1], - [0, 0, 1, 0] => [CharacterSet, count: 1, negative?: true] + [0, 0, 1, 0] => [CharacterSet, count: 1] include_examples 'parse', /[a&&a-z]/, [0] => [CharacterSet, count: 1], diff --git a/spec/parser/sets_spec.rb b/spec/parser/sets_spec.rb index 3949ea8..c508d5c 100644 --- a/spec/parser/sets_spec.rb +++ b/spec/parser/sets_spec.rb @@ -48,11 +48,11 @@ [0, 1, 1, 0] => [:literal, :literal, Literal, text: 'c', set_level: 3] include_examples 'parse', '[a[^b[c]]]', - [0] => [:set, :character, CharacterSet, text: '[', count: 2, set_level: 0, negative?: false], + [0] => [:set, :character, CharacterSet, text: '[', count: 2, set_level: 0], [0, 0] => [:literal, :literal, Literal, text: 'a', set_level: 1], - [0, 1] => [:set, :character, CharacterSet, text: '[', count: 2, set_level: 1, negative?: true], + [0, 1] => [:set, :character, CharacterSet, text: '[', count: 2, set_level: 1], [0, 1, 0] => [:literal, :literal, Literal, text: 'b', set_level: 2], - [0, 1, 1] => [:set, :character, CharacterSet, text: '[', count: 1, set_level: 2, negative?: false], + [0, 1, 1] => [:set, :character, CharacterSet, text: '[', count: 1, set_level: 2], [0, 1, 1, 0] => [:literal, :literal, Literal, text: 'c', set_level: 3] include_examples 'parse', '[aaa]',