T
Trans
Been beating my head against this one for far too long now, and I think
others might be interested in it. I have a lib where the user needs to
define a set of "things" that have both assignable data and assignable
functions. Also they should be extensible so the user can add
additional functionality. It's a bit difficult to explain so I will
just give my exmaple.
|class Parser::Token
|
| class << self
| def esc(str) ; Regexp.escape(str) ; end
| def unit? ; @unit ; end
| def unit(u) ; @unit = ( u ? true : false ) ; end
| def exclusive? ; @exclusive ; end
| def exclusive(excl) ; @exclusive = ( excl ? true : false ) ; end
| def priority ; @priority ||= 10 ; end
| def priority(pri) ; @priority = pri ; end
| def <=> ; @priority ; end
| def start_exp(match=nil) ; @start.call(match) ; end
| def start(&blk) ; @start = blk ; end
| def stop_exp(match=nil) ; @stop.call(match) ; end
| def stop(&blk) ; @stop = blk ; end
| end
|
| attr_reader arent, :match, :body
|
| def initialize( parent, match )
| @parent = parent
| @match = match
| @body = []
| end
|
| def <<( content ) ; @body << content ; end
| def last ; @body.empty? ? @body : @body.last ; end
| def empty? ; @body.empty? ; end
| def pop ; @body.pop ; end
| def each(&blk) ; @body.each(&blk) ; end
|
|end #class Parser::Token
So then the lib usr can define each of their "things" based on this,
minimally:
|class Marker < Parser::Token
|
| exclusive false
| start { %r{ \< (.*?) \> }mx }
| stop { |match| %r{ \< [ ]* (#{esc(match[1])}) (.*?) \. \> }mx }
|
| #... user's optional methods ...
It toke me some time to work this out in itself. And I thought I had
finally gotten a fairly nice interface here. But to my dismay, I just
discovered that I can't subclass Marker b/c I loose the definitions of
the above attributes (ie. exclusive, start, stop). So now I'm back to
rethinking the whole setup. (Also note that if the user's methods
redefine #initialize or the other Token methods, it might cause the
parser that uses it to break --another slight down side and a possible
use case for RCR #198)
So how does one properly build something like this in a nice neat way?
Thanks,
T.
others might be interested in it. I have a lib where the user needs to
define a set of "things" that have both assignable data and assignable
functions. Also they should be extensible so the user can add
additional functionality. It's a bit difficult to explain so I will
just give my exmaple.
|class Parser::Token
|
| class << self
| def esc(str) ; Regexp.escape(str) ; end
| def unit? ; @unit ; end
| def unit(u) ; @unit = ( u ? true : false ) ; end
| def exclusive? ; @exclusive ; end
| def exclusive(excl) ; @exclusive = ( excl ? true : false ) ; end
| def priority ; @priority ||= 10 ; end
| def priority(pri) ; @priority = pri ; end
| def <=> ; @priority ; end
| def start_exp(match=nil) ; @start.call(match) ; end
| def start(&blk) ; @start = blk ; end
| def stop_exp(match=nil) ; @stop.call(match) ; end
| def stop(&blk) ; @stop = blk ; end
| end
|
| attr_reader arent, :match, :body
|
| def initialize( parent, match )
| @parent = parent
| @match = match
| @body = []
| end
|
| def <<( content ) ; @body << content ; end
| def last ; @body.empty? ? @body : @body.last ; end
| def empty? ; @body.empty? ; end
| def pop ; @body.pop ; end
| def each(&blk) ; @body.each(&blk) ; end
|
|end #class Parser::Token
So then the lib usr can define each of their "things" based on this,
minimally:
|class Marker < Parser::Token
|
| exclusive false
| start { %r{ \< (.*?) \> }mx }
| stop { |match| %r{ \< [ ]* (#{esc(match[1])}) (.*?) \. \> }mx }
|
| #... user's optional methods ...
It toke me some time to work this out in itself. And I thought I had
finally gotten a fairly nice interface here. But to my dismay, I just
discovered that I can't subclass Marker b/c I loose the definitions of
the above attributes (ie. exclusive, start, stop). So now I'm back to
rethinking the whole setup. (Also note that if the user's methods
redefine #initialize or the other Token methods, it might cause the
parser that uses it to break --another slight down side and a possible
use case for RCR #198)
So how does one properly build something like this in a nice neat way?
Thanks,
T.