I am interested in creating DSL in Ruby for use in parsing microblog updates. In particular, I thought I could translate text into a Ruby string in the same way that the Rails gem allows "4.days.ago". I already have a regex code that will translate the text
@USER_A: give X points to @USER_B for accomplishing some task
@USER_B: take Y points from @USER_A for not giving me enough points
into something like
Scorekeeper.new.give(x).to("USER_B").for("accomplishing some task").giver("USER_A")
Scorekeeper.new.take(x).from("USER_A").for("not giving me enough points").giver("USER_B")
It is acceptable for me to formalize the syntax of updates so that only standardized text is provided and analyzed, which allows me to intensively process updates. So it seems like it is more a question of how to implement the DSL class. I have the following stub class (removed all error checking and replaced some with comments to minimize insertion):
class Scorekeeper
attr_accessor :score, :user, :reason, :sender
def give(num)
self.score = num
self
end
def take(num)
self.score = num < 0 ? num : num * -1
self
end
def plus
self.score > 0
end
def to (str)
self.user = str
self
end
def from(str)
self.user = str
self
end
def for(str)
self.reason = str
self
end
def giver(str)
self.sender = str
self
end
def command
str = plus ? "giving @#{user} #{score} points" : "taking #{score * -1} points from @#{user}"
"@#{sender} is #{str} for #{reason}"
end
end
Execution of the following commands:
t = eval('Scorekeeper.new.take(4).from("USER_A").for("not giving me enough points").giver("USER_B")')
p t.command
p t.inspect
Sets the expected results:
"@USER_B is taking 4 points from @USER_A for not giving me enough points"
"#<Scorekeeper:0x100152010 @reason=\"not giving me enough points\", @user=\"USER_A\", @score=4, @sender=\"USER_B\">"
, : -, , ? - DSL - ?
, eval, sub/gsub regex, , , .