46 lines
1.3 KiB
Ruby
46 lines
1.3 KiB
Ruby
module Mustermann
|
|
class Sinatra < AST::Pattern
|
|
# Sinatra syntax definition.
|
|
# @!visibility private
|
|
class Parser < AST::Parser
|
|
on(nil, ??, ?)) { |c| unexpected(c) }
|
|
|
|
on(?*) { |c| scan(/\w+/) ? node(:named_splat, buffer.matched) : node(:splat) }
|
|
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
|
on(?\\) { |c| node(:char, expect(/./)) }
|
|
on(?() { |c| node(:group) { read unless scan(?)) } }
|
|
on(?|) { |c| node(:or) }
|
|
|
|
on ?{ do |char|
|
|
current_pos = buffer.pos
|
|
type = scan(?+) ? :named_splat : :capture
|
|
name = expect(/[\w\.]+/)
|
|
if type == :capture && scan(?|)
|
|
buffer.pos = current_pos
|
|
capture = proc do
|
|
start = pos
|
|
match = expect(/(?<capture>[^\|}]+)/)
|
|
node(:capture, match[:capture], start: start)
|
|
end
|
|
grouped_captures = node(:group, [capture[]]) do
|
|
if scan(?|)
|
|
[min_size(pos - 1, pos, node(:or)), capture[]]
|
|
end
|
|
end
|
|
grouped_captures if expect(?})
|
|
else
|
|
type = :splat if type == :named_splat and name == 'splat'
|
|
expect(?})
|
|
node(type, name)
|
|
end
|
|
end
|
|
|
|
suffix ?? do |char, element|
|
|
node(:optional, element)
|
|
end
|
|
end
|
|
|
|
private_constant :Parser
|
|
end
|
|
end
|