Module: LazyPP
- Defined in:
- lib/readable-cpp/nodes.rb,
lib/readable-cpp/parser.rb,
lib/readable-cpp/package.rb,
lib/readable-cpp/program.rb,
lib/readable-cpp/transformer.rb
Overview
class Object
private
def CallerInspect c
c = c.map { |x|
(x =~ /(\/[.\w\/]+):(\d+):in `([^']+)'/) ?
[$1,$2.to_i, $3] :
nil
}.compact
files = {}
c.map { |i| i[0] }.uniq.each { |file|
warn "reading #{file}"
files[file] = File.readlines file
}
res = c.uniq
weights = Hash[res.map { |x| [x, c.count(x)] }]
res.map! { |r|#(f, n, b)|
[*r, weights[r], files[r[0]][r[1]],
(r[1] .. [0, r[1]-20].max).map { |n|
if files[r[0]][n] =~ /def[\s]+(([A-Za-z_][A-Za-z_0-9]*[\=!?]?)|([+\-*\/<>\[\]@]+))[\s\(]*/
binding.pry
$1
else
nil
end
}.compact
]
}
binding.pry
res
end
end
Defined Under Namespace
Classes: BracketStmts, ClassDecl, Node, OperDecl, Package, Parser, Program, RenderState, Unit
Constant Summary collapse
- Conditional =
Node.new(:kind, :condition, :body) do def scan *args; body.scan(*args) unless body.nil? end def kind= val val = val.to_s @kind = if val =~ /elseif/i; "else if" # ;) else val end end def to_cpp(rs) "#{rs.indentation}#{kind.to_cpp}#{ "(#{condition.to_cpp rs})" unless condition.nil? } {\n#{body.to_cpp(rs.indent)}\n#{rs.indentation}}" end end
- RangeForStmt =
Node.new(:var, :container, :body) do def scan p; p.set_cpp0x; body.scan p end def to_cpp rs "#{rs.indentation}for(#{var.to_cpp(rs)} : #{container.to_cpp rs}) {\n"+ body.to_cpp(rs.indent)+ "#{rs.indentation}}" end end
- ForStmt =
Class.new(Conditional) do def scan *args; body.scan(*args); condition.compact.each{|c|c.scan(*args)} end def to_cpp rs "#{rs.indentation}for(#{last = condition[0].to_cpp(rs)}#{ ';' unless last[-1] == ';'}#{condition[1].to_cpp rs};#{condition[2].to_cpp rs}) {\n#{ body.to_cpp(rs.indent)}\n#{rs.indentation}}" end end
- NamespaceIdent =
Node.new(:names) do def names= val; @names = Array.wrap(val) end def to_cpp(rs) names.map{|n|n.to_cpp(rs)}.join '::' end end
- GotoLabel =
Node.new :type, :label do def to_cpp rs case type when :goto; "goto #{label};" else "#{label}:" end end end
- ThrowStmt =
DOUBLE CHECK, maybe
Node.new :expr do ## DOUBLE CHECK, maybe def to_cpp rs "throw #{expr.to_cpp rs}" end end
- DotName =
Node.new(:name) do def name= val; @name = Array.wrap(val) end def to_cpp(*) if caller.size > 500 c=CallerInspect(caller) #binding.pry end name.map { |n| n.is_a?(Hash) ? n.values : n }.flatten(1).map(&:to_cpp).join end def prefix name; @name.insert 0, name end end
- Visibility =
Node.new(:v) do def to_cpp rs = RenderState.new(); end def to_hpp rs=RenderState.new raise "visiblity stmt only allowed in a class decl" \ unless rs.parent.is_a? ClassDecl "#{v}:" end end
- FuncCall =
Class.new Node.new(:name, :args, :generics) do def initialize(n, a, g = nil) super n, a, g end def args= val @args = if val == ?! || val == '()' nil else Array.wrap val end end def generics= val @generics = Array.wrap_nil val end def to_cpp(rs) name.to_cpp(rs) + "#{"<#{generics.map { |g| g.to_cpp(rs, '') }.join', '}>" unless generics.nil?}(" + ( args.nil? ? '' : args.map{|a|a.to_cpp rs}.join(', ')) + ')' #args != ?! && [*args].map(&:to_cpp).join(', ') || '') << ')' end end
- ExprStmt =
Node.new(:expr) do def to_cpp(rs); rs.indentation + expr.to_cpp(rs) + ';' end end
- LangSection =
Node.new(:txt)
- AutoDecl =
Node.new(:name, :val) do def scan p p.set_cpp0x end def to_cpp(rs) "#{rs.indentation}auto #{name.to_cpp rs} = #{val.to_cpp rs};" end end
- ReturnStmt =
Node.new(:expr) do def to_cpp rs "#{rs.indentation}return #{expr.to_cpp rs};" end end
- StmtList =
Node.new(:stmts) do
Class.new(Array) do #Node.new(:stmts) do #def [](key) stmts[key] end def inspect "<#{self.class}(#{size}) #{map { |s| s.inspect }.join(', ') }>" end def scan p each { |s| s.scan p } end def to_hpp(rs = RenderState.new) map { |s| s.to_hpp(rs) }.join"\n" end def to_cpp(rs = RenderState.new, &discriminator) if block_given? select(&discriminator).map { |s| s.to_cpp(rs, &discriminator) } else map { |s| s.to_cpp(rs) } end.join("\n") end def at index; self[index] end end
- Type =
Node.new(:base, :derived, :storage) do attr_accessor :constness, :static, :inline attr_accessor :specifiers def initialize(b, d, s) self.base = b self.derived = d self.specifiers =Set.new self.storage = s end def no_storage() Type.new(base, derived, nil) end def derived= val @derived = (val == [''] || val.nil?) ? nil : Array.wrap(val) end def base= val; @base = Array.wrap val; end def derived_cpp(rs, m = :to_cpp) #@derived_cpp ||= ( ##caching bad, this can change between header/src res = '%s' left = false derived.each do |d| d = Hash[d] if d.is_a?(Array) next if d.empty? # if d.has_key? :constness; self.constness = d[:constness].to_s # #elsif d.has_key? :static; self.static = d[:static].to_s case d when :ptr res = "*#{res}" left = true when :ref res = "&#{res}" left = true when Hash #if d.has_key?(:size) || d.has_key?(:array) if d.has_key?(:array) || d.has_key?(:array_unsized) n = "[#{d[:array] && d[:array].send(m, rs)}]" #n = "[#{d[:size] && d[:size].send(m, rs)}]" res = if left; left = false; "(#{res})#{n}" else; "#{res}#{n}" end elsif d.has_key? :func_sig begin n = "(#{[*d[:func_sig]].map { |a| a.send(m, rs) % '' }.join', '})" res = if left; left = false; "(#{res})#{n}" else; "#{res}#{n}" end rescue => e binding.pry end elsif d.has_key? :const res = "#{d[:const].to_s.downcase} #{res}" left = true # elsif d.has_key? :storage # @storage = d[:storage].to_s.downcase unless d[:storage].nil? else ##what the hell is this? :o binding.pry end else binding.pry end end unless derived.nil? res #) end def storage_cpp() "#{"#{storage.to_s.downcase} " unless storage.nil?}" end def base_hpp rs derived_cpp rs storage_cpp + base.map{|x|x.to_hpp rs}.join(' ') end def base_cpp rs derived_cpp rs #just to cache it storage_cpp + base.map{|x|x.to_cpp rs}.join(' ') end def to_hpp rs base_hpp(rs) << ' ' << derived_cpp(rs) end def to_cpp rs=RenderState.new, name=nil ##note to self: % format result with the name r = base_cpp(rs) << ' ' << derived_cpp(rs) (name.nil? ? r : r % name).rstrip end end
- TypeDecl =
Node.new(:name, :type) do def to_cpp rs rs.gen_header? ? '' : to_hpp(rs) end def to_hpp rs "#{rs.indentation}typedef #{type.base_cpp rs} #{type.derived_cpp(rs) % name.to_cpp(rs)};" end end
- Expr =
Node.new(:prefix, :expr, :postfix) do def to_cpp(rs) # prefix.nil? && postfix.nil? ? # expr.to_cpp : # "(#{prefix.to_cpp}#{expr.to_cpp}#{postfix.to_cpp})" "#{prefix.to_cpp rs}#{expr.to_cpp rs}#{postfix.to_cpp rs}" end end
- DotExpr =
Node.new(:exprs) do def to_cpp(rs = RenderState.new) "#{exprs.map{|e| e.to_cpp rs }.join''}" end end
- AccessExpr =
Node.new(:access, :expr) do def to_cpp(rs) "#{access.to_cpp rs}#{expr.to_cpp rs}" end end
- ParenExpr =
Node.new(:expr) do def to_cpp(rs) "(#{expr.to_cpp rs})" end end
- CastExpr =
Node.new(:type, :expr) do def to_cpp rs "(#{type.to_cpp(rs) % ''})(#{expr.to_cpp rs})" end end
- CaseStmt =
Node.new(:exprs, :body) do def scan(*args) body.each { |b| b.scan *args } end def to_cpp(rs) i = rs.indentation (exprs == :default ? i+"default:\n" : exprs.map { |x| i+"case #{x.to_cpp rs}:\n"}.join('') ) + body.to_cpp(rs.indent) + "\n#{rs.indent.indentation}break;" end end
- SwitchStmt =
Node.new(:expr, :body) do def scan(*args) body.each { |b| b.scan *args } end def to_cpp(rs) "#{rs.indentation}switch(#{expr.to_cpp rs}) {\n" + body.map { |s| s.to_cpp(rs) }.join("\n") + "\n#{rs.indentation}}" end end
- InfixExpr =
Node.new(:left, :infix, :right) do def to_cpp rs #binding.pry "#{left.to_cpp rs } #{infix.to_cpp rs } #{right.to_cpp rs}" end end
- FuncCall2 =
Node.new(:args) do def args= v @args = Array.wrap_nil(v.to_s == "!" ? nil : v) end def to_cpp rs "(#{args.map{|_|_.to_cpp rs}.join(', ') unless args.nil?})" end end
- PostfixExpr =
Node.new(:x, :postfixen) do def scan *args postfixen.each do |c| c.scan *args end end def postfixen= v @postfixen = Array.wrap(v) end def to_cpp rs "#{x.to_cpp rs}#{postfixen.map{|_|_.to_cpp rs}.join}" end end
- TernaryExpr =
Node.new(:cond, :t, :f) do def to_cpp rs "#{cond.to_cpp rs} ? #{t.to_cpp rs} : #{f.to_cpp rs}" end end
- PrefixExpr =
Node.new(:op, :expr) do def scan p op.scan p expr.scan p end def to_cpp rs "#{op}#{expr.to_cpp rs}" end end
- BracketExpr =
Node.new(:expr) do def to_cpp(rs=RenderState.new) "[#{expr.to_cpp(rs)}]" end end
- GenericIdent =
Node.new(:ident, :generic) do def generic= val @generic = Array.wrap(val) end def to_cpp(rs) "#{ident.to_cpp(rs)}<#{generic.map{|n| n.to_cpp(rs, '')}.join', '}>" end end
- UnionType =
Node.new(:members) do def members= val; @members = Array.wrap val; end def to_cpp rs "union{#{members.map{|f|f.to_cpp(rs) + ';'}.join' '}}" end end
- EnumType =
Node.new(:fields) do def fields= val; @fields = Array.wrap val; end def to_cpp(rs) "enum{#{fields.map{|f|f.to_cpp rs}.join', '}}" end end
- EnumDecl =
the other one works for anonymous enum types (var x: enumA,B,C)
Node.new :name, :fields do def fields= val; @fields = Array.wrap val; end def header_only rs unless rs.gen_header? to_hpp rs else '' end end def to_cpp(rs) header_only(rs) end def to_hpp rs "#{rs.indentation}enum #{name} {#{fields.map{|f|f.to_cpp rs}.join', '}};" end end
- StructType =
Node.new(:body) do def to_cpp(rs) "struct{#{"\n#{body.to_cpp rs.indent}\n#{rs.indentation}" unless body.nil?}}" end end
- VarDeclSimple =
Node.new(:name, :type, :val) do def scan p name.scan p type.scan p val.scan p end def to_cpp(rs = RenderState.new()) # res = type.to_cpp # [*names].map { |n| (res + ';') % n }.join('') rs.indentation + (type.base_cpp(rs) % '') + ' ' + (type.derived_cpp(rs)%name) + (val && " = #{val.to_cpp(rs)};" || ';') end end
- VarDeclInitializer =
Node.new(:names, :type)do def to_cpp(rs = RenderState.new()) derived = type.derived_cpp rs #cpp rs.indentation + type.base_cpp(rs) + ' ' + [*names].map { |n| name = derived % n.name rescue binding.pry if n.args.nil? name else name + '(' + [*n.args].map{|a|a.to_cpp(rs)}.join(', ') + ')' end }.join(', ') + ';' end end
- ConstructorName =
Node.new(:name, :args)
- IdentDef =
Node.new(:names, :type, :default) do def names= val; @names = Array.wrap(val) end def to_cpp(rs) #return to_hpp(rs) unless rs.gen_header? t = type.to_cpp(rs) names.map { |n| t % n }.join', ' end def to_hpp(rs) t = type.to_hpp(rs) names.map { |n| res = t % n (res << ' = ' << default.to_cpp(rs)) unless default.nil? res }.join', ' end end
- ImportStmt =
Node.new(:pkg) do attr_reader :p def initialize(pkg) @p = Package.new(pkg) end def scan(prog) prog.notify self end def to_cpp(rs) @p.includes.map { |i| "#include #{i}\n" }.join('') unless @p.includes.nil? end end
- StringLit =
Node.new(:wchar, :str) do def scan p str.gsub!(/[^\\]\n/, "\\\n") ##add \ to the ends of multiline strings for c++ end def to_cpp(*); "#{?L if wchar}\"#{str}\"" end def str= val; @str = val.to_s end extend Forwardable def_delegators :@str, :=~, :to_s end
- DefineStmt =
Node.new(:name, :expr) do def to_cpp(rs) to_hpp(rs) if not rs.gen_header? end def to_hpp(rs) "#define #{name.to_cpp rs} #{expr.to_cpp rs}" end end
- StructLit =
Node.new(:x) do def x= val; @x = Array(val) end def to_cpp(rs) "{#{x.map{|_|_.to_cpp rs}.join', '}}" end end
- TryStmt =
Node.new(:attempt, :catches) do def to_cpp rs "#{rs.indentation}try {\n#{attempt.to_cpp rs.indent}\n"\ "#{rs.indentation}} #{catches.map{|c|c.to_cpp rs}.join''}" end end
- CatchStmt =
Node.new(:c, :body) do def to_cpp rs "#{rs.indentation}catch (#{c.to_cpp rs}) {\n"\ "#{body.to_cpp rs.indent}\n"\ "#{rs.indentation}}" end end
- IncludeStmt =
Node.new(:file, :type) do def file= val if file && file.is_a?(StringLit) @file.str = val else @file = val end end def scan p; p.notify self end def to_cpp(rs) "#include " << ( type == :std ? '<' << file << '>' : file.to_cpp) end end
- UsingStmt =
Node.new(:name) do def to_cpp(rs) "using #{name.to_cpp rs};" end end
- IntLiteral =
Node.new(:value) do def to_cpp(*); "#{value}" end end
- CharLiteral =
Node.new(:char) do def to_cpp(*); "'#{char}'" end end
- FloatLiteral =
Node.new(:value, :type) do def to_cpp(*) "#{value}#{type}" end end
- LambdaFunc =
Node.new(:captures, :params, :returns, :body) { def captures=(val) @captures = Array.wrap_nil val end def params=(val) @params = Array.wrap_nil val end def to_cpp(rs) "[#{ captures.join(', ') unless captures.nil? }](#{ params.map{|p|p.to_cpp rs}.join', ' unless params.nil? })#{ "->#{returns.to_cpp(rs) % ''}" unless returns.nil? }{#{body.to_cpp(rs)}}" end }
- Namespace =
Node.new(:name, :body) do def to_hpp(rs) "namespace #{name.to_hpp rs} {\n" << body.to_hpp(rs.indent) << "\n}" end def to_cpp(rs, &b) "namespace #{name.to_cpp rs} {\n" << body.to_cpp(rs.indent,&b) << "\n}" end end
- DtorDecl =
Node.new(:stmts, :specifier) do def specifier= val @specifier = if val.nil? then '' else val.to_s + ' ' end end def to_cpp rs #parent = rs.parent pname = rs.parent_names + '::~' + rs.parents.last.name.to_s "#{rs.indentation}#{pname}() \n"\ "#{rs.indentation}{\n"\ "#{stmts.to_cpp(rs.indent)}\n"\ "#{rs.indentation}}" end def to_hpp rs "#{rs.indentation}#{ specifier unless specifier.nil? }~#{rs.last_parent}();" end end
- AnonDecl =
DOUBLE CHECK THIS
Node.new :type do ## DOUBLE CHECK THIS def to_cpp rs end ## works fine inside structs/class where def to_hpp rs ## the header is always generated above the impl "#{rs.indentation}#{type.to_cpp(rs) % ''};" end end
- CtorDecl =
Node.new(:args, :initializers, :body, :explicit) do def explicit= val; @explicit = val.nil? ? nil : val.to_s.chomp+' ' end def args= a; @args = Array.wrap a; end def initializers= i; @initializers = (i.nil? ? nil : Array.wrap( i)); end def scan(*args) body.scan(*args) end def to_cpp rs Pry.rescue { pname = rs.parent_names pname << "::" << rs.parent.last.name.to_s <<-LULZ #{rs.indentation}#{pname}#{#rs.parent.last.name}::#{pname.nil? ? #parent.respond_to?(:name) ? # parent.name : # (binding.pry;'/*constructor name missing and parent node has no name*/'): #pname }(#{args.map{|a|a.to_cpp rs}.join', '}) #{ ( ': ' + initializers.map{|i| i = i[:initializer] "#{i[:member].to_cpp rs}(#{[*i[:args]].map{|a|a.to_cpp rs}.join(', ')})" }.join(', ') ) unless initializers.nil? } #{ if body.nil? then ?; else "{\n#{body.to_cpp(rs.indent)}\n#{rs.indentation}}" end} LULZ } end def to_hpp rs parent = rs.parent.last "#{rs.indentation}#{explicit}#{parent.name.to_hpp(rs)}(#{args.map{|a|a.to_hpp rs}.join', '});" end end
- FuncDecl =
Class.new Node.new(:name, :sig, :body, :generics, :specifiers) do def initialize(n,s,b,g,ss= nil) super end def specifiers= val; @specifiers = val.nil? ? nil : Array.wrap(val) end def generics= val; @generics = val.nil? ? nil : Array.wrap(val) end def scan(*args) body.scan(*args) unless body.nil? end def to_cpp(rs) ## more info on functions returning functions and such at http://www.newty.de/fpt/fpt.html prename = '' prename = rs.parent_names+'::' unless rs.parents.empty? "#{"#{rs.indentation}template <#{generics.map{|x|'typename '+ x.to_cpp(rs)}.join', '}>\n" if generics}" + "#{rs.indentation}#{ if rs.gen_header? #remove the storage if headers are generated sig.no_storage.base_cpp(rs) else sig.base_cpp(rs) end} #{ sig.derived_cpp(rs) % "#{prename}#{name}"}"+ "#{body == :EQ0 ? ' = 0;' : body.nil? ? ';' : "\n#{rs.indentation}{\n#{ body.to_cpp(rs.indent) }\n"\ "#{rs.indentation}}" }" end def to_hpp(rs) "#{rs.indentation}#{ specifiers.map{|s|s.to_hpp rs}.join(' ')+' ' if !specifiers.nil?}#{ sig.base_hpp rs} #{sig.derived_cpp(rs, :to_hpp) % name};" end end
- Transform =
Parslet::Transform.new { rule(ident: simple(:i)) { i.to_s } rule(ident: simple(:i), generics: simple(:g)) { GenericIdent.new(i, g) } rule(ident: simple(:i), generics: sequence(:g)) { GenericIdent.new i, g } rule(expr: simple(:x), generics: simple(:g)) { GenericIdent.new x,g } rule(expr: simple(:x), generics: sequence(:g)) { GenericIdent.new x,g } rule(void: simple(:v)) { 'void' } rule(any: simple(:__)) { '...' } rule(ptr: simple(:p)) { :ptr } rule(ref: simple(:r)) { :ref } rule(list_item: simple(:i)){ i } rule(ident_eq: { ident: simple(:i), dot_expr: simple(:x) }) { InfixExpr.new(i, '=', x) } rule(ident_eq: simple(:i)) { i } rule(stmts: sequence(:s)) { StmtList.new s } rule(stmts: simple(:s)) { StmtList.new Array.wrap s } rule(anon_decl: simple(:ty)) { AnonDecl.new ty } rule(bracket_stmts: sequence(:s)) { BracketStmts.new s } rule(wchar: simple(:w), string: simple(:s)) { StringLit.new(w, s.to_s) } rule(wchar: simple(:w), string: sequence(:s)) { StringLit.new(w, s.join('')) } rule(goto: simple(:l)) { GotoLabel.new :goto, l } rule(label: simple(:g)){ GotoLabel.new :label,g } # rule(type: {derived: subtree(:d), base: subtree(:b), storage: simple(:s)}){ # Type.new(b, Array.wrap(d), s) # } # rule(type: {derived: subtree(:d), base: subtree(:b)}) { # Type.new b, Array.wrap(d), nil # } rule(derived: subtree(:d), base: subtree(:b)) { Type.new b, d, nil } rule(derived: subtree(:d), base: subtree(:b), storage: subtree(:s)) { Type.new b, d, s } rule(type: simple(:t)) {t} rule(union: { members: subtree(:m) }) { UnionType.new(m) } rule(auto_decl: {name: simple(:n), value: subtree(:v)}) { AutoDecl.new(n, v) } rule(:catch => simple(:c), body: simple(:b)) { CatchStmt.new(c, b) } rule(attempt: simple(:at), catches: sequence(:c)) { TryStmt.new(at, c) } rule(enum: { fields: subtree(:f) }) { EnumType.new f } rule(struct: simple(:body)) { StructType.new body } rule(lang_section: subtree(:l)) { #binding.pry LangSection.new(l) } rule(id_names: sequence(:n), type: simple(:t)) { IdentDef.new n, t, nil } rule(#ident_def: { id_names: sequence(:n), type: simple(:t), id_default: simple(:d)}) { IdentDef.new n, t, d } rule(id_names: simple(:n), type: simple(:t)) { IdentDef.new n, t, nil } rule(#ident_def: { names: simple(:n), type: simple(:t), default: simple(:d) }) { IdentDef.new n, t, d } rule(ident_def: simple(:i), any: simple(:a)) {[i, '...']} rule(type: simple(:t), any: simple(:a)) {[t, '...']} rule(ident_def: simple(:_)) {_} rule(var_decl: {name: simple(:n), type: simple(:t)}) { VarDeclSimple.new(n, t, nil) } rule(var_decl: {name: simple(:n), type: simple(:t), expr: simple(:x)}){ VarDeclSimple.new(n, t, x) } rule(var_decl: {vdi_names: subtree(:n), vdi_type: simple(:t)}) { VarDeclInitializer.new n, t } rule(case_: 'default', body: sequence(:b)) { CaseStmt.new :default, b } rule(case_: simple(:c), body: sequence(:b)) { CaseStmt.new [c], b } rule(case_: sequence(:c), body: sequence(:b)) { CaseStmt.new c, b } rule(switch_stmt: {expr: simple(:x), cases: sequence(:cases)}) { SwitchStmt.new x, cases } rule(name: simple(:n), constructor: subtree(:c)) { ConstructorName.new n, c } rule(import_pkg: subtree(:i)) { ImportStmt.new(i) } rule(define_stmt: {name: simple(:n), expr: simple(:x)}) { DefineStmt.new n, x } rule(include_stmt: { std: simple(:x), file: simple(:f) }) { IncludeStmt.new f, :std } rule(include_stmt: { local: simple(:f) }) { IncludeStmt.new f, :local } rule(include_stmt: sequence(:s)) { StmtList.new(s) } rule(include_stmt: simple(:s)) { s } rule(using_stmt: { ns: simple(:ns), using_namespace: simple(:n) }) { UsingStmt.new("namespace #{n}") } # rule(using_stmt: { using_namespace: simple(:n) }) { # UsingStmt.new(n) # } rule(using_namespace: simple(:n)) { UsingStmt.new n } rule(using_stmt: sequence(:s)) { StmtList.new(s) } rule(using_stmt: simple(:s)) { s } rule(namespace_decl: {namespace: subtree(:n), body: subtree(:b)}){ Namespace.new(n, b) } rule(oper_decl: { pos: simple(:pos), name: simple(:name), sig: simple(:sig), body: simple(:body) }) { OperDecl.new name, sig, body, pos } rule(oper_decl: { name: simple(:name), sig: simple(:sig), body: simple(:body)}) { OperDecl.new name, sig, body, nil } rule(func_decl: { name: simple(:name), generics: simple(:g), sig: simple(:sig) }) { FuncDecl.new name, sig, nil, g } rule(func_decl: { name: simple(:name), generics: simple(:g), sig: simple(:sig), body: simple(:b)}){ FuncDecl.new name, sig, b, g } rule(func_decl: { name: simple(:name), generics: subtree(:g), specifiers: subtree(:s), sig: simple(:sig), body: simple(:b)}) { FuncDecl.new name, sig, b, g, s } rule(func_decl: { name: simple(:name), generics: subtree(:g), specifiers: subtree(:s), sig: simple(:sig) }) { FuncDecl.new name, sig, nil, g, s } rule(func_decl: { name: simple(:name), generics: subtree(:g), specifiers: subtree(:s), sig: simple(:sig), eq_0: simple(:eee)}) { FuncDecl.new name, sig, :EQ0, g, s } # rule(func_decl: { # name: simple(:name), # sig: { args: subtree(:args), returns: subtree(:returns) }, # body: simple(:b) }) { # FuncDecl.new name, args, returns, b # } # rule(func_decl: { # name: simple(:name), # sig: { args: subtree(:args), returns: subtree(:returns) }}) { # FuncDecl.new name, args, returns, nil # } rule(op: simple(:o)) { o.is_a?(Parslet::Slice) ? o.to_s.intern : o } rule(float: simple(:f), type: simple(:t)) { FloatLiteral.new(f, t) } rule(cast: { type: simple(:t), expr: simple(:x) }) { CastExpr.new t, x } rule(int: simple(:i)) { IntLiteral.new i.to_i } rule(char: simple(:c)) { CharLiteral.new c.to_s } rule(return: simple(:exp)) { ReturnStmt.new exp } rule(ctor_decl: { explicit: simple(:e), args: subtree(:args), initializers: subtree(:i), body: simple(:b)}) { CtorDecl.new args, i, b, e } rule(dtor_decl: subtree(:d)) { DtorDecl.new(d[:body], d[:specifier] || nil) } rule(parens: simple(:x)) { ParenExpr.new x } rule(ref: simple(:r), name: simple(:n)) { "#{r}#{n}" } rule(lambda_func: { captures: simple(:c), args: subtree(:p), returns: simple(:r), body: simple(:b) }) { LambdaFunc.new c, p, r, b } rule(lambda_func: { captures: { auto_ref: simple(:___) }, args: subtree(:p), returns: simple(:r), body: simple(:b) }) { LambdaFunc.new '&', p, r, b } rule(lambda_func: { captures: {auto_val: simple(:___)}, args: subtree(:p), returns: simple(:r), body: simple(:b) }) { LambdaFunc.new '=', p, r, b } rule(infix: { left: simple(:l), op: simple(:o), right: simple(:r)}) { InfixExpr.new l, o.to_s, r } #rule(postfix: sequence(:x)) { PostfixExpr.new x } rule(left: simple(:x), access: simple(:a), ident: simple(:i)) { PostfixExpr.new x, [a.to_s, i.to_s] } rule(prefix_op: simple(:o), expr: simple(:x)) { PrefixExpr.new o.to_s, x } rule(ternary: { condition: simple(:c), true: simple(:t), false: simple(:f) }) { TernaryExpr.new c, t, f } rule(expr: simple(:x), postfix: sequence(:p)) { PostfixExpr.new x, p } rule(expr: simple(:x), postfix: sequence(:p), args: subtree(:a)) { PostfixExpr.new x, [*p, FuncCall2.new(a)] } rule(args: sequence(:a)) { FuncCall2.new a } rule(args: simple(:a)) { FuncCall2.new a } rule(cast: {type: simple(:t), ident: simple(:i)}) # rule(prefix: simple(:p), expr: simple(:x), postfix: simple(:pp), # args: subtree(:a), infix: simple(:i), right: simple(:x2)) { # InfixExpr.new FuncCall.new(Expr.new(p, x, nil), a), i.to_s.intern, x2 # } # rule(expr: simple(:x), args: subtree(:a), infix: simple(:i), right: simple(:r)) { # InfixExpr.new FuncCall.new(x, a), i.to_s.intern, r # } # rule(prefix: simple(:p), expr: simple(:x), args: simple(:a)) { # FuncCall.new(Expr.new(p.to_s, x, nil), a) # } # rule( # prefix: simple(:p), expr: simple(:x), # infix: simple(:i), right: simple(:x2)) { # InfixExpr.new(Expr.new(p, x, nil), i.to_s, x2) # } # rule( # prefix: simple(:p), expr: simple(:x), postfix: simple(:pp), # infix: simple(:i), right: simple(:x2)) { # InfixExpr.new(Expr.new(p, x, pp), i.to_s, x2) # } # rule( # expr: simple(:x), postfix: simple(:pp), # infix: simple(:i), right: simple(:x2)) { # InfixExpr.new(Expr.new(nil, x, pp), i.to_s, x2) # } # rule(expr: simple(:x)) { # Expr.new(nil, x, nil) # } # rule(expr: simple(:x), postfix: simple(:pp)) { # Expr.new(nil, x, pp) # } # rule(expr: simple(:l), infix: simple(:i), right: simple(:r)) { # InfixExpr.new(l, i.to_s, r) # } rule(expr: simple(:x)) { x.is_a?(Parslet::Slice) ? x.to_s : x } rule(expr_stmt: simple(:x)) { ExprStmt.new(x) } # rule(expr: simple(:x), args: subtree(:a)) { # FuncCall.new x, a # } # rule(parens: simple(:x), args: subtree(:a)) { # FuncCall.new x, a # } # rule(func: simple(:name), args: subtree(:args)) { # FuncCall.new name, Array.wrap(args) # } # rule(access: simple(:a), func: simple(:name), args: subtree(:args)) { # FuncCall.new name.prefix(a), Array.wrap(args) # } rule(type_decl: { name: simple(:n), type: { class_type: simple(:c), parents: subtree(:p), body: subtree(:b) }}) { ClassDecl.new(n, c, b, p) } rule(type_decl: { name: simple(:n), type: { class_type: simple(:c), body: subtree(:b) }}) { ClassDecl.new(n, c, b, nil) } rule(type_decl: { name: simple(:n), enum: { fields: subtree(:f) }}) { EnumDecl.new n, f } rule(struct_lit: simple(:x)) { StructLit.new x } rule(struct_lit: sequence(:x)) { StructLit.new x } rule(type_decl: { name: simple(:n), type: simple(:t) }) { TypeDecl.new(n, t) } rule(dot_ident: subtree(:d)) { DotName.new d } # rule(dot_ident: simple(:d)) { # DotName.new d # } rule(namespace: sequence(:n)) { NamespaceIdent.new n } rule(conditional: { kind: simple(:k), cond: simple(:c), body: simple(:b) }) { Conditional.new k, c, b } rule(for_stmt: { l: simple(:l), m: simple(:m), r: simple(:r), body: simple(:b) }) { ForStmt.new :for, [l, m, r], b } rule(conditional: { kind: simple(:k), ##else body: simple(:b) }) { Conditional.new k, nil, b } rule(range_for: { var: simple(:v), range: simple(:container), body: simple(:b)}) { RangeForStmt.new v, container, b } rule(namespaced: simple(:i)) { NamespaceIdent.new i } rule(namespaced: sequence(:i)) { NamespaceIdent.new(i) } rule(namespaced: {left: simple(:l), right: simple(:r)}) { NamespaceIdent.new [l, r] } rule(modifier: simple(:m), namespaced: simple(:n)) { [m, n] } rule(modifier: simple(:m), namespaced: sequence(:n)) { [m, NamespaceIdent.new(n)] } rule(sq_bracket_expr: simple(:x)) { BracketExpr.new x } rule(visibility_stmt: simple(:v)) { Visibility.new v.to_s } rule(:throw => simple(:x)) { ThrowStmt.new x } rule(access: simple(:a), expr: simple(:x)) { AccessExpr.new a, x } rule(access: simple(:a), ident: simple(:i)) { DotName.new([a.to_s, i]) } rule(dot_expr: sequence(:x)) { DotExpr.new x } rule(dot_expr: simple(:x)) { DotExpr.new [*x] } }