lib/cast/parse.rb in cast-0.1.0 vs lib/cast/parse.rb in cast-0.2.0

- old
+ new

@@ -1,69 +1,67 @@ -### -### ################################################################## -### -### C.default_parser and the parse_* methods. -### -### Yeah, this could be so much faster. -### -### ################################################################## -### +###################################################################### +# +# C.default_parser and the parse_* methods. +# +# Yeah, this could be so much faster. +# +###################################################################### module C @@default_parser = Parser.new def self.default_parser @@default_parser end - def self.default_parser= val + def self.default_parser=(val) @@default_parser = val end class Node - ### - ### Return true if `str' is parsed to something `==' to this Node. - ### str is first converted to a String using #to_s, then given to - ### self.class.parse (along with the optional `parser'). - ### - def match? str, parser=nil + # + # Return true if `str' is parsed to something `==' to this Node. + # str is first converted to a String using #to_s, then given to + # self.class.parse (along with the optional `parser'). + # + def match?(str, parser=nil) node = self.class.parse(str.to_s, parser) rescue (return false) self == node end - ### - ### Same as #match?. - ### - def =~ *args - match? *args + # + # Same as #match?. + # + def =~(*args) + match?(*args) end private end class NodeList - ### - ### As defined in Node. - ### - def match? arr, parser=nil + # + # As defined in Node. + # + def match?(arr, parser=nil) arr = arr.to_a return false if arr.length != self.length each_with_index do |node, i| node.match?(arr[i], parser) or return false end return true end end - def self.parse s, parser=nil + def self.parse(s, parser=nil) TranslationUnit.parse(s, parser) end class TranslationUnit - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser parser.parse(s) end end class Declaration - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse(s).entities if ents.length == 1 && # int i; int j; ents[0].is_a?(Declaration) # void f() {} return ents[0].detach @@ -72,11 +70,11 @@ end end end class Parameter - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("void f(#{s}) {}").entities if ents.length == 1 && # ) {} void ( ents[0].is_a?(FunctionDef) && # ); void( ents[0].type.params && # @@ -92,24 +90,33 @@ end end end class Declarator - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser - ents = parser.parse("int #{s};").entities - if ents.length == 1 && # f; int f; - ents[0].declarators.length == 1 # i,j - return ents[0].declarators[0].detach + # if there's a ':', declare in a struct so we can populate num_bits + if s =~ /:/ + ents = parser.parse("struct {int #{s};};").entities + if ents.length == 1 && # i:1;}; struct {int i + ents[0].type.members.length == 1 && # i:1; int j + ents[0].type.members[0].declarators.length == 1 # i:1,j + return ents[0].type.members[0].declarators[0].detach + end else - raise ParseError, "invalid Declarator" + ents = parser.parse("int #{s};").entities + if ents.length == 1 && # f; int f; + ents[0].declarators.length == 1 # i,j + return ents[0].declarators[0].detach + end end + raise ParseError, "invalid Declarator" end end class FunctionDef - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse(s).entities if ents.length == 1 && # void f(); void g(); ents[0].is_a?(FunctionDef) # int i; return ents[0].detach @@ -118,11 +125,11 @@ end end end class Enumerator - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("enum {#{s}};").entities if ents.length == 1 && # } enum { ents[0].is_a?(Declaration) && # } f() { ents[0].type.members.length == 1 # X, Y @@ -132,11 +139,11 @@ end end end class MemberInit - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("int f() {struct s x = {#{s}};}").entities if ents.length == 1 && # } int f() { ents[0].def.stmts.length == 1 && # }} f() {{ ents[0].def.stmts[0].declarators.length == 1 && # 1}, y @@ -147,46 +154,46 @@ end end end class Member - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser - ents = parser.parse("int f() {struct s x = {#{s} = 1;};}").entities - if ents.length == 1 && # };} int f() {struct s x = {a - ents[0].def.stmts.length == 1 && # }; x - #ents[0].def.stmts[0].length == 1 && # 1}, x = {.a - ents[0].def.stmts[0].declarators.length == 1 && # 1}, x = {.a - ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 && # x = 1, y - ents[0].def.stmts[0].declarators[0].init.member_inits[0].member.length == 1 && # .a .b - ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].is_a?(C::Member) # [0] + ents = parser.parse("int f() {struct s x = {.#{s} = 1};}").entities + if ents.length == 1 && # a = 1};} int f() {struct s x = {a + ents[0].def.stmts.length == 1 && # a = 1}; struct s y = {.a + #ents[0].def.stmts[0].length == 1 && # a = 1}, x = {.a + ents[0].def.stmts[0].declarators.length == 1 && # a = 1}, x = {.a + ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 && # x = 1, y + ents[0].def.stmts[0].declarators[0].init.member_inits[0].member && # 1 + ents[0].def.stmts[0].declarators[0].init.member_inits[0].member.length == 1 # a .b return ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].detach else raise ParseError, "invalid Member" end end end class Statement - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("void f() {#{s}}").entities - if ents.length == 1 && # } void f() { + if ents.length == 1 && # } void f() { ents[0].def.stmts.length == 1 && # ;; - ents[0].def.stmts[0].is_a?(self) # int i; + ents[0].def.stmts[0].is_a?(self) # int i; return ents[0].def.stmts[0].detach else raise ParseError, "invalid #{self}" end end end class Label - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("void f() {switch (0) #{s};}").entities - if ents.length == 1 && # } void f() { + if ents.length == 1 && # } void f() { ents[0].def.stmts.length == 1 && # ; ents[0].def.stmts[0].stmt && # ents[0].def.stmts[0].stmt.labels.length == 1 && # x ents[0].def.stmts[0].stmt.labels[0].is_a?(self) return ents[0].def.stmts[0].stmt.labels[0].detach @@ -195,39 +202,53 @@ end end end class Expression - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser - ents = parser.parse("void f() {#{s};}").entities - if ents.length == 1 && # } void f() { - ents[0].def.stmts.length == 1 && # ; - ents[0].def.stmts[0].is_a?(ExpressionStatement) && # int i - ents[0].def.stmts[0].expr.is_a?(self) - return ents[0].def.stmts[0].expr.detach + if s =~ /\A(\s*(\/\*.*?\*\/)?)*\{/ + # starts with a brace -- must be a CompoundLiteral. in this + # case, use a Declarator since only those can handle typeless + # CompoundLiterals. + ents = parser.parse("int i = #{s};").entities + if ents.length == 1 && # 1; int i = 1 + ents[0].declarators.length == 1 && # 1, j = 2 + ents[0].declarators[0].init.is_a?(self) + return ents[0].declarators[0].init.detach + else + raise ParseError, "invalid #{self}" + end else - raise ParseError, "invalid #{self}" + ents = parser.parse("void f() {#{s};}").entities + if ents.length == 1 && # } void f() { + ents[0].def.stmts.length == 1 && # ; + ents[0].def.stmts[0].is_a?(ExpressionStatement) && # int i + ents[0].def.stmts[0].expr.is_a?(self) + return ents[0].def.stmts[0].expr.detach + else + raise ParseError, "invalid #{self}" + end end end end class Type - def self.parse s, parser=nil + def self.parse(s, parser=nil) parser ||= C.default_parser ents = parser.parse("void f() {(#{s})x;}").entities - if ents.length == 1 && # 1);} void f() {(int + if ents.length == 1 && # 1);} void f() {(int ents[0].def.stmts.length == 1 && # 1); (int ents[0].def.stmts[0].expr.type.is_a?(self) return ents[0].def.stmts[0].expr.type.detach else raise ParseError, "invalid #{self}" end end end - #### Make sure we didn't miss any + # Make sure we didn't miss any CORE_C_NODE_CLASSES.each do |c| - c.methods.include? 'parse' or - raise "#{c}#parse not defined" + c.respond_to? :parse or + raise "#{c}.parse not defined" end end