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