PageRenderTime 38ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/parser/parser_redux.go

https://code.google.com/p/gosandbox/
Go | 190 lines | 149 code | 22 blank | 19 comment | 16 complexity | cb42ee02e4d008b808137a923f51f338 MD5 | raw file
  1. // Reference:
  2. // -http://golang.org/src/pkg/go/ast/ast.go
  3. // -http://golang.org/src/pkg/go/ast/walk.go
  4. package main
  5. import (
  6. "go/ast"
  7. "go/parser"
  8. "go/token"
  9. "fmt"
  10. "flag"
  11. "os"
  12. "reflect"
  13. "strings"
  14. )
  15. // Avoid typing "fmt.Printf("...\n", ...) every time
  16. func printf(format string, v ...interface{}) (n int, errno os.Error) {
  17. return fmt.Printf(format + "\n", v...)
  18. }
  19. // Visitor for ast.Walk
  20. type printVisitor struct {
  21. weight float
  22. priorWeight float
  23. }
  24. func (f *printVisitor) Visit(node ast.Node) ast.Visitor {
  25. if node == nil {
  26. return f
  27. }
  28. typ := reflect.NewValue(node).Type().String()
  29. // Get rid of redundant package prefix
  30. typ = strings.Split(typ, ".", -1)[1]
  31. w := 1.0
  32. // If statement then add weight
  33. if strings.Contains(typ, "Stmt") {
  34. w = f.weight
  35. }
  36. if strings.Contains(typ, "CaseClause") || strings.Contains(typ, "CommClause") {
  37. w = f.priorWeight
  38. }
  39. printf("%s: %f", typ, w)
  40. printf("%s.Pos: %d", typ, node.Pos()) // All nodes have Pos accessor method
  41. // 3 classes of nodes: Expression & type nodes,
  42. // statement nodes, and declaration nodes
  43. switch n := node.(type) {
  44. // Comments
  45. case *ast.Comment:
  46. printf("%s.Text.Length: %d", typ, len(n.Text))
  47. case *ast.CommentGroup:
  48. printf("%s.List.Length: %d", typ, len(n.List))
  49. // Expressions
  50. case *ast.Field:
  51. printf("%s.Names.Length: %d", typ, len(n.Names))
  52. case *ast.FieldList:
  53. printf("%s.List.Length: %d", typ, len(n.List))
  54. printf("%s.Closing: %d", typ, n.Closing)
  55. printf("%s.NumFields: %d", typ, n.NumFields())
  56. case *ast.Ident:
  57. printf("%s.Name.Length: %d", typ, len(n.Name))
  58. case *ast.CompositeLit:
  59. printf("%s.Lbrace: %d", typ, n.Lbrace)
  60. printf("%s.Elts.Length: %d", typ, len(n.Elts))
  61. printf("%s.Rbrace: %d", typ, n.Rbrace)
  62. case *ast.ParenExpr:
  63. printf("%s.Lparen: %d", typ, n.Lparen)
  64. printf("%s.Rparen: %d", typ, n.Rparen)
  65. case *ast.CallExpr:
  66. printf("%s.Lparen: %d", typ, n.Lparen)
  67. printf("%s.Args.Length: %d", typ, len(n.Args))
  68. printf("%s.Ellipsis: %d", typ, n.Ellipsis)
  69. printf("%s.Rparen: %d", typ, n.Rparen)
  70. case *ast.KeyValueExpr:
  71. printf("%s.Colon: %d", typ, n.Colon)
  72. case *ast.BinaryExpr:
  73. fmt.Println("Binary expression")
  74. // Types
  75. case *ast.StructType:
  76. printf("%s.Fields.Length: %d", typ, len(n.Fields.List))
  77. case *ast.FuncType:
  78. printf("%s.Params.Length: %d", typ, n.Params.NumFields())
  79. printf("%s.Results.Length: %d", typ, n.Results.NumFields())
  80. case *ast.InterfaceType:
  81. printf("%s.Methods.Length: %d", typ, len(n.Methods.List))
  82. // Statements
  83. case *ast.AssignStmt:
  84. printf("%s.Lhs.Length: %d", typ, len(n.Lhs))
  85. // Usage of "=" vs. ":="
  86. if n.Tok == token.DEFINE {
  87. printf("%s.Tok.DEFINE: 1", typ)
  88. return f
  89. }
  90. printf("%s.Tok.ASSIGN: 1", typ)
  91. case *ast.ReturnStmt:
  92. printf("%s.Results.Length: %d", typ, len(n.Results))
  93. case *ast.BlockStmt:
  94. printf("%s.Lbrace: %d", typ, n.Lbrace)
  95. printf("%s.List.Length: %d", typ, len(n.List))
  96. printf("%s.Rbrace: %d", typ, n.Rbrace)
  97. case *ast.CaseClause:
  98. printf("%s.Colon: %d", typ, n.Colon)
  99. printf("%s.Body.Length: %d", typ, len(n.Body))
  100. case *ast.TypeCaseClause:
  101. printf("%s.Types.Length: %d", typ, len(n.Types))
  102. printf("%s.Colon: %d", typ, n.Colon)
  103. printf("%s.Body.Length: %d", typ, len(n.Body))
  104. case *ast.CommClause:
  105. printf("%s.Colon: %d", typ, n.Colon)
  106. printf("%s.Body.Length: %d", typ, len(n.Body))
  107. // Handle weighting
  108. case *ast.IfStmt:
  109. var t printVisitor
  110. t.weight = f.weight/2
  111. t.priorWeight = f.weight
  112. return &t
  113. case *ast.SwitchStmt:
  114. case *ast.SelectStmt:
  115. case *ast.TypeSwitchStmt:
  116. numCases := len(n.Body.List)
  117. var t printVisitor
  118. t.weight = f.weight/float(numCases)
  119. t.priorWeight = f.weight
  120. return &t
  121. // Declarations
  122. case *ast.ValueSpec:
  123. printf("%s.Names.Length: %d", typ, len(n.Names))
  124. case *ast.GenDecl:
  125. printf("%s.Lparen: %d", typ, n.Lparen)
  126. printf("%s.Rparen: %d", typ, n.Rparen)
  127. case *ast.FuncDecl:
  128. if n.Recv != nil {
  129. printf("%s.Recv", typ)
  130. }
  131. printf("%s.Name.Length: %d", typ, len(n.Name.Name))
  132. printf("%s.Body.List.Length: %d", typ, len(n.Body.List))
  133. // Files & packages?
  134. default:
  135. return f
  136. } // End cases
  137. return f
  138. }
  139. // File size in kB of a file
  140. func size(name string) int64 {
  141. file, _ := os.Open(name, os.O_RDONLY, 0)
  142. defer file.Close()
  143. var buf [100]byte
  144. len := 0
  145. for {
  146. n, e := file.Read(buf[0:])
  147. len += n
  148. if e == os.EOF {
  149. break
  150. }
  151. }
  152. return int64(len)
  153. }
  154. func main() {
  155. flag.Parse()
  156. filename := flag.Arg(0)
  157. file, err := parser.ParseFile(token.NewFileSet(), filename, nil, 0)
  158. if err != nil {
  159. fmt.Println(filename + "\t" + err.String())
  160. return
  161. }
  162. fmt.Printf("FileSizeKB: %d\n", size(filename)/1000)
  163. // Instance
  164. var f printVisitor
  165. f.weight = 1
  166. f.priorWeight = 1
  167. ast.Walk(&f, file)
  168. }