Class: LinkParser::Definition
- Extended by:
- Forwardable
- Defined in:
- lib/linkparser/definition.rb
Constant Summary collapse
- Token =
Constants for definition parsing.
/\s+|@?[A-Z*^]+[a-z^*]*[+-]|\(|\[|\{|\)|\]|\}|[Aa][Nn][Dd]|&|[Oo][Rr]|\|/
- Connect =
/(@)?([A-Z*^]+[a-z^*]*)([+-])/
- Conjunction =
/(and)|(&)|(or)|(\|)/i
- Open =
/\(|\[|\{/
- Close =
/\)|\]|\}/
- Space =
/\s+/
Instance Attribute Summary collapse
-
#raw ⇒ Object
readonly
The raw string from which this definition is derived.
Class Method Summary collapse
-
.re_satisfy(definition) ⇒ Object
The main body of satisfy,.
-
.satisfy(definition) ⇒ Object
Takes a definition string and returns a Definition object populated with the set of sets of connectors that will satisfy that the provided string.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #===, #eql?)
tests for equality.
-
#connector_sets ⇒ Object
(also: #connectorSets)
The sets of sets of connectors that is the algorithmicly useful version of this object.
-
#includes_match?(connector) ⇒ Boolean
Returns whether or not there exists a matching connector to a given connector.
-
#initialize(an_arg) ⇒ Definition
constructor
The single argument may be either a String or an Array.
-
#inspect ⇒ Object
Stringification with a ‘sensible’ opposite of the one for to_s.
-
#sets_matching(connector) ⇒ Object
Returns those connector_sets which include a connector which matches the provided connector.
-
#to_connectors ⇒ Object
(also: #two_s)
Stringification of the connector sets.
-
#to_s ⇒ Object
The most sensible stringification of this definition.
Constructor Details
#initialize(an_arg) ⇒ Definition
The single argument may be either a String or an Array. If the argument is a string, it is treated as a definition string, and won’t be parsed until needed. If it is an array, no reverse engineering will be done to create the corresponding definition string.
151 152 153 154 155 156 157 158 159 |
# File 'lib/linkparser/definition.rb', line 151 def initialize( an_arg ) if an_arg.kind_of? String @raw = an_arg @connector_sets = [] else @raw = nil @connector_sets = an_arg end end |
Instance Attribute Details
#raw ⇒ Object (readonly)
The raw string from which this definition is derived.
162 163 164 |
# File 'lib/linkparser/definition.rb', line 162 def raw @raw end |
Class Method Details
.re_satisfy(definition) ⇒ Object
The main body of satisfy,
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/linkparser/definition.rb', line 55 def Definition.re_satisfy(definition) definition = StringScanner.new( definition, false ) unless definition.kind_of?(StringScanner) results = [] side = nil current = nil multi = false while definition.rest? case current = definition.scan(Token) when Connect # Connectors - puts the connector alone in a set, and # puts that into the results. connector_m = Connect.match( current ) side = connector_m[3] =~ /-/ ? Connector::LEFT : Connector::RIGHT multi = connector_m[1] ? Connector::PLUS : Connector::ONCE name_scan = StringScanner::new(connector_m[2]) # Slurp in all the characters up to the last capitol # letter and up to one star or caret. name = name_scan.scan(/.*[A-Z][*^]?/) sub_name = name_scan.rest or '' # Log.debug( "Found connector '%s'" % current ) results << [ Connector::new(name, sub_name, side, multi) ] when Conjunction # Conjunctions (and, or) - combine the results so far with the # results of what would be the rest of the parse, as per the # rules of the conjunction used. conj_m = Conjunction.match( current ) raise ParseError, "conjunction with nothing preceeding it: '#{definition.string}'" if results.empty? if conj_m[1] or conj_m[2] # and, & - the new results will be every combination of the # previous results and the results of the rest of the parse. rest = re_satisfy(definition) raise ParseError, "conjunction with nothing following: '#{definition.string}'" if rest.empty? results.combine!(rest) else # or, | - the new results will be the union of the previous # results and the results of the rest of the parse. rest = re_satisfy(definition) raise ParseError, "conjunction with nothing following: '#{definition.string}'" if rest.empty? results.add!(rest) end return results when Open # Open parens - treated the same as a single connector, but # concerning the entire contents of the parens. if current =~ /\[/ re_satisfy( definition ).each {|set| set.map! {|conn| Connector.new(conn.name,conn.subName,conn.side,conn.multiplicity,conn.cost+1) } results << set } elsif current =~ /\{/ re_satisfy( definition ).each {|set| set.map! {|conn| if conn.multiplicity == Connector::ONCE Connector.new(conn.name,conn.subName,conn.side,Connector::OPTIONAL,conn.cost) elsif conn.multiplicity == Connector::PLUS Connector.new(conn.name,conn.subName,conn.side,Connector::STAR,conn.cost) else conn end } results << set } else results.add!(re_satisfy( definition )) end raise ParseError, "improper parentheses usage: '#{definition.string}'" if results.empty? when Close # Close parens - if this is found, the method returns, checking # for the null-connector condition first. return results.empty? ? [ [Connector::new("*")] ] : results when Space # Spaces - are ignored when nil # Nil - means the parse has encountered something not matching # the Token regex. raise ParseError, "Definition unparsable before end of definition: '#{definition.rest}'" end end return results end |
.satisfy(definition) ⇒ Object
Takes a definition string and returns a Definition object populated with the set of sets of connectors that will satisfy that the provided string. args: definition - the string to be parsed for meaning, or a StringScanner on that string, possibly in mid-parse
50 51 52 |
# File 'lib/linkparser/definition.rb', line 50 def Definition.satisfy( definition ) Definition::new(Definition::re_satisfy(definition)) end |
Instance Method Details
#==(other) ⇒ Object Also known as: ===, eql?
tests for equality
195 196 197 198 199 200 201 |
# File 'lib/linkparser/definition.rb', line 195 def ==(other) return(false) unless other.kind_of?(self.class) return(@raw == other.raw) if (@raw && other.raw) and (@raw == other.raw) return self.connector_sets.set_of_sets_equal?(other.connector_sets) end |
#connector_sets ⇒ Object Also known as: connectorSets
The sets of sets of connectors that is the algorithmicly useful version of this object.
166 167 168 169 170 171 172 |
# File 'lib/linkparser/definition.rb', line 166 def connector_sets if @connector_sets and @connector_sets.empty? @connector_sets = Definition::re_satisfy(@raw) else @connector_sets end end |
#includes_match?(connector) ⇒ Boolean
Returns whether or not there exists a matching connector to a given connector.
216 217 218 219 220 221 222 |
# File 'lib/linkparser/definition.rb', line 216 def includes_match?(connector) self.find {|set| set.find {|c| c.match(connector) } } end |
#inspect ⇒ Object
Stringification with a ‘sensible’ opposite of the one for to_s.
190 191 192 |
# File 'lib/linkparser/definition.rb', line 190 def inspect (@connector_sets && @connector_sets.empty?) ? @raw : @connector_sets.inspect end |
#sets_matching(connector) ⇒ Object
Returns those connector_sets which include a connector which matches the provided connector.
207 208 209 210 211 212 213 |
# File 'lib/linkparser/definition.rb', line 207 def sets_matching(connector) self.find_all {|set| set.find {|c| c.match(connector) } } end |
#to_connectors ⇒ Object Also known as: two_s
Stringification of the connector sets.
184 185 186 |
# File 'lib/linkparser/definition.rb', line 184 def to_connectors self.connector_sets.inspect end |
#to_s ⇒ Object
The most sensible stringification of this definition.
179 180 181 |
# File 'lib/linkparser/definition.rb', line 179 def to_s @raw ? @raw : self.to_connectors end |