Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implied Rule#value method.
If no methods are specified in an extension block, it is assumed that
the block is to be used to define a "value" method on an anonymous
module. This helps syntax to be much less verbose, and may be used in
the vast majority of cases.
  • Loading branch information
mjackson committed Sep 23, 2010
1 parent 2032d8b commit b91fd51
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 264 deletions.
62 changes: 14 additions & 48 deletions examples/calc.citrus
Expand Up @@ -13,9 +13,7 @@ grammar Calc

rule additive
(factor additive_operator term) {
def value
additive_operator.apply(factor.value, term.value)
end
additive_operator.value(factor.value, term.value)
}
end

Expand All @@ -25,9 +23,7 @@ grammar Calc

rule multiplicative
(prefix multiplicative_operator factor) {
def value
multiplicative_operator.apply(prefix.value, factor.value)
end
multiplicative_operator.value(prefix.value, factor.value)
}
end

Expand All @@ -37,9 +33,7 @@ grammar Calc

rule prefixed
(unary_operator prefix) {
def value
unary_operator.apply(prefix.value)
end
unary_operator.value(prefix.value)
}
end

Expand All @@ -49,9 +43,7 @@ grammar Calc

rule exponential
(primary exponential_operator exponent) {
def value
exponential_operator.apply(primary.value, exponent.value)
end
exponential_operator.value(primary.value, exponent.value)
}
end

Expand All @@ -60,11 +52,7 @@ grammar Calc
end

rule group
(lparen term rparen) {
def value
term.value
end
}
(lparen term rparen) { term.value }
end

## Syntax
Expand All @@ -74,56 +62,34 @@ grammar Calc
end

rule float
(digits '.' digits space) {
def value
text.strip.to_f
end
}
(digits '.' digits space) { text.strip.to_f }
end

rule integer
(digits space) {
def value
text.strip.to_i
end
}
(digits space) { text.strip.to_i }
end

rule digits
[0-9]+ ('_' [0-9]+)*
end

rule additive_operator
(('+' | '-') space) {
def apply(n1, n2)
n1.send(text.strip, n2)
end
}
(('+' | '-') space) { |a, b| a.send(text.strip, b) }
end

rule multiplicative_operator
(('*' | '/' | '%') space) {
def apply(n1, n2)
n1.send(text.strip, n2)
end
}
(('*' | '/' | '%') space) { |a, b| a.send(text.strip, b) }
end

rule exponential_operator
('**' space) {
def apply(n1, n2)
n1 ** n2
end
}
('**' space) { |a, b| a ** b }
end

rule unary_operator
(('~' | '+' | '-') space) {
def apply(n)
op = text.strip
# Unary + and - require an @.
n.send(op == '~' ? op : '%s@' % op)
end
(('~' | '+' | '-') space) { |n|
op = text.strip
# Unary + and - require an @.
n.send(op == '~' ? op : '%s@' % op)
}
end

Expand Down
62 changes: 14 additions & 48 deletions examples/calc.rb
Expand Up @@ -16,9 +16,7 @@

rule :additive do
all(:factor, :additive_operator, :term) {
def value
additive_operator.apply(factor.value, term.value)
end
additive_operator.value(factor.value, term.value)
}
end

Expand All @@ -28,9 +26,7 @@ def value

rule :multiplicative do
all(:prefix, :multiplicative_operator, :factor) {
def value
multiplicative_operator.apply(prefix.value, factor.value)
end
multiplicative_operator.value(prefix.value, factor.value)
}
end

Expand All @@ -40,9 +36,7 @@ def value

rule :prefixed do
all(:unary_operator, :prefix) {
def value
unary_operator.apply(prefix.value)
end
unary_operator.value(prefix.value)
}
end

Expand All @@ -52,9 +46,7 @@ def value

rule :exponential do
all(:primary, :exponential_operator, :exponent) {
def value
exponential_operator.apply(primary.value, exponent.value)
end
exponential_operator.value(primary.value, exponent.value)
}
end

Expand All @@ -63,11 +55,7 @@ def value
end

rule :group do
all(:lparen, :term, :rparen) {
def value
term.value
end
}
all(:lparen, :term, :rparen) { term.value }
end

## Syntax
Expand All @@ -77,56 +65,34 @@ def value
end

rule :float do
all(:digits, '.', :digits, :space) {
def value
text.strip.to_f
end
}
all(:digits, '.', :digits, :space) { text.strip.to_f }
end

rule :integer do
all(:digits, :space) {
def value
text.strip.to_i
end
}
all(:digits, :space) { text.strip.to_i }
end

rule :digits do
/[0-9]+(?:_[0-9]+)*/
end

rule :additive_operator do
all(any('+', '-'), :space) {
def apply(n1, n2)
n1.send(text.strip, n2)
end
}
all(any('+', '-'), :space) { |a, b| a.send(text.strip, b) }
end

rule :multiplicative_operator do
all(any('*', '/', '%'), :space) {
def apply(n1, n2)
n1.send(text.strip, n2)
end
}
all(any('*', '/', '%'), :space) { |a, b| a.send(text.strip, b) }
end

rule :exponential_operator do
all('**', :space) {
def apply(n1, n2)
n1 ** n2
end
}
all('**', :space) { |a, b| a ** b }
end

rule :unary_operator do
all(any('~', '+', '-'), :space) {
def apply(n)
op = text.strip
# Unary + and - require an @.
n.send(op == '~' ? op : '%s@' % op)
end
all(any('~', '+', '-'), :space) { |n|
op = text.strip
# Unary + and - require an @.
n.send(op == '~' ? op : '%s@' % op)
}
end

Expand Down
13 changes: 12 additions & 1 deletion lib/citrus.rb
Expand Up @@ -419,7 +419,18 @@ def name=(name)
# result from this rule. If +mod+ is a Proc, it is used to create an
# anonymous module.
def extension=(mod)
mod = Module.new(&mod) if Proc === mod
if Proc === mod
begin
tmp = Module.new(&mod)
raise NoMethodError unless tmp.instance_methods.any?
mod = tmp
rescue NameError, NoMethodError
mod = Module.new { define_method(:value, &mod) }
end
end

raise ArgumentError unless Module === mod

@extension = mod
end

Expand Down

0 comments on commit b91fd51

Please sign in to comment.