Skip to content

Instantly share code, notes, and snippets.

@kschiess
Forked from damncabbage/failing_example.rb
Created October 11, 2011 13:31
Show Gist options
  • Save kschiess/1278080 to your computer and use it in GitHub Desktop.
Save kschiess/1278080 to your computer and use it in GitHub Desktop.
Parslet Woes
require 'parslet'
require 'parslet/convenience'
require 'pp'
def parse(input)
parser = SongParser.new
begin
tree = parser.parse(input)
rescue Parslet::ParseFailed => error
puts error, parser.root.error_tree
end
tree
end
class SongParser < Parslet::Parser
# Convenience: End of Line / Whitespace matchers
rule(:line_end) { match('[\r\n]').repeat(1) }
# Elements
rule(:syllable) { ((timecode | line_end).absent? >> any).repeat(1) }
rule(:timecode) {
str('[') >> match('\d').repeat(1).as(:min) >>
str(':') >> match('\d').repeat(1).as(:sec) >>
str(':') >> match('\d').repeat(1).as(:msec) >> str(']')
}
# Groups
rule(:pair) { timecode >> syllable.as(:syllable) }
rule(:line) { (pair.repeat >> timecode.maybe).as(:line) >> line_end }
rule(:song) { line.repeat.as(:lines) }
root :song
end
input = "[01:06:07]Beat[01:06:30]ing [01:06:56]up [01:06:83]the [01:07:09]wrong "
input << "[01:07:52]guy[01:08:03]junk\n[01:08:50]Oh [01:08:93]man![01:09:48]\n"
input_no_trailing_new_line = input.chomp
# puts "INPUT"
# puts input
# puts
def parser
SongParser.new
end
# pp parser.line.parse_with_debug("[01:06:07]syll[01:06:07]junk[01:06:07]\n")
tree = parser.parse(input)
Syllable = Struct.new(:min, :text)
transform = Parslet::Transform.new do
rule(:min=>simple(:min), :sec=>simple(:sec), :msec=>simple(:msec), :syllable=>simple(:text)) { Syllable.new(min, text) }
rule(:min=>simple(:min), :sec=>simple(:sec), :msec=>simple(:msec)) { Syllable.new(min, nil) }
rule(:line => sequence(:syllables)) { syllables.last.text = nil; syllables }
end
pp transform.apply(tree)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment