Skip to content

Instantly share code, notes, and snippets.

/t.rb

Created April 13, 2012 06:02
Show Gist options
  • Save anonymous/2374233 to your computer and use it in GitHub Desktop.
Save anonymous/2374233 to your computer and use it in GitHub Desktop.
require 'parslet'
class Parser < Parslet::Parser
# commons
rule(:space) { match('[ \t]').repeat(1) }
rule(:space?) { space.maybe }
rule(:newline) { match('[\r\n]') }
rule(:comment) { str('#') >> match('[^\r\n]').repeat }
rule(:line_separator) {
(space? >> ((comment.maybe >> newline) | str(';')) >> space?).repeat(1)
}
rule(:blank) { line_separator | space }
rule(:blank?) { blank.maybe }
rule(:identifier) { match('[a-zA-Z0-9_]').repeat(1) }
# res_statement
rule(:reference) {
((str('@@') | str('@')) >> identifier).as(:reference)
}
rule(:res_action_or_link) {
str('.').as(:dot) >> (identifier >> str('?').maybe ).as(:name) >> str('()')
}
rule(:res_actions) {
(
reference
).as(:resources) >>
(
res_action_or_link.as(:res_action)
).repeat(0).as(:res_actions)
}
rule(:res_statement) {
res_actions >>
(str(':') >> identifier.as(:name)).maybe.as(:res_field)
}
# expression
rule(:expression) {
res_statement
}
# body
rule(:body) {
(line_separator >> (block | expression)).repeat(0).as(:body) >>
line_separator
}
# blocks
rule(:begin_block) {
(str('concurrent').as(:type) >> space).maybe.as(:pre) >>
str('begin').as(:begin) >>
body >>
str('end')
}
rule(:define_block) {
str('define').as(:define) >> space >>
identifier.as(:name) >> str('()') >>
body >>
str('end')
}
rule(:block) {
define_block | begin_block
}
# root
rule(:radix) {
line_separator.maybe >> block >> line_separator.maybe
}
root(:radix)
end
ds = [
%{
define f()
begin
@res:name
end
end
},
%{
define f()
begin
@res.name()
end
end
},
%{
define f()
@res.name
end
},
%{
define f()
begin
@res.name
end
end
}
]
class Parslet::Atoms::Base
# Extracts the deepest leaf in the error tree.
#
def deepest_error
line = 0
column = 0
cause = nil
error_tree.to_s.split("\n").each do |l|
m = l.match(/- (.+) at line (\d+) char (\d+)/)
if m && m[2].to_i >= line
line = m[2].to_i; column = m[3].to_i; cause = m[1]
end
end
"#{cause} at l#{line} c#{column}"
end
end
ds.each do |d|
puts '-' * 80
parser = Parser.new
begin
parser.parse(d)
puts 'success'
rescue => e
puts
puts e
puts
puts parser.root.error_tree
puts
puts parser.root.deepest_error
puts
end
end
puts '-' * 80
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment