Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Last active December 10, 2015 22:08
Show Gist options
  • Save fowlmouth/4499782 to your computer and use it in GitHub Desktop.
Save fowlmouth/4499782 to your computer and use it in GitHub Desktop.
require'parslet'
require'parslet/convenience'
require'pry'
class P < Parslet::Parser
def join rule, on, min = 0
rule >> (on >> rule).repeat(min)
end
root :type
rule :comma do str(?,) end
rule :space do match['\s'].repeat(1) end
rule :space? do space.maybe end
rule :type do
(derived_type >> space?).maybe.as(:derived) >>
(
ident >> (space >> ident).repeat(0) |
func_sig
).as(:base)
end
rule :derived_type do
join(
str(?^).as(:ptr) |
str(?&).as(:ref) |
(str(?[) >> match['\d'].repeat(1).maybe.as(:size) >> str(?])).as(:arr),
space?
)
end
rule :func_sig do
str(?() >> space? >>
(
type >> (space? >> comma >> space? >> type).repeat(0)
).as(:args) >>
space? >> str(?)) >>
space? >> str('->') >> space? >>
type.as(:returns)
end
rule :ident do
match['\w'].repeat(1)
end
end
module Nodes
Type = Struct.new(:derived, :base)
Func = Struct.new(:args, :returns)
end
Trans = Parslet::Transform.new do
rule ptr: simple(:p) do :ptr end
rule derived: simple(:d), base: simple(:b) do Nodes::Type.new [d], b end
rule derived: sequence(:d), base: simple(:b) do Nodes::Type.new d, b end
rule args: sequence(:a), returns: simple(:r) do Nodes::Func.new a, r end
rule args: simple(:a), returns: simple(:r) do Nodes::Func.new [a], r end
end
r =
[
'long long',
'^ [10] int', ## int (*foo)[10]
'^ (int) -> int', ## int (*foo)(int)
'^ (int) -> ^(float)->void' ## void (*(*foo)(int))(float)
].map { |t| Trans.apply( P.new.parse_with_debug t) }
binding.pry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment