1 package parser 2 3 import ( 4 "text/scanner" 5 ) 6 7 type MakeThing interface { 8 AsAssignment() (Assignment, bool) 9 AsComment() (Comment, bool) 10 AsDirective() (Directive, bool) 11 AsRule() (Rule, bool) 12 AsVariable() (Variable, bool) 13 Dump() string 14 Pos() scanner.Position 15 EndPos() scanner.Position 16 } 17 18 type Assignment struct { 19 makeThing 20 Name *MakeString 21 Value *MakeString 22 Target *MakeString 23 Type string 24 } 25 26 type Comment struct { 27 makeThing 28 Comment string 29 } 30 31 type Directive struct { 32 makeThing 33 Name string 34 Args *MakeString 35 } 36 37 type Rule struct { 38 makeThing 39 Target *MakeString 40 Prerequisites *MakeString 41 Recipe string 42 } 43 44 type Variable struct { 45 makeThing 46 Name *MakeString 47 } 48 49 type makeThing struct { 50 pos scanner.Position 51 endPos scanner.Position 52 } 53 54 func (m makeThing) Pos() scanner.Position { 55 return m.pos 56 } 57 58 func (m makeThing) EndPos() scanner.Position { 59 return m.endPos 60 } 61 62 func (makeThing) AsAssignment() (a Assignment, ok bool) { 63 return 64 } 65 66 func (a Assignment) AsAssignment() (Assignment, bool) { 67 return a, true 68 } 69 70 func (a Assignment) Dump() string { 71 target := "" 72 if a.Target != nil { 73 target = a.Target.Dump() + ": " 74 } 75 return target + a.Name.Dump() + a.Type + a.Value.Dump() 76 } 77 78 func (makeThing) AsComment() (c Comment, ok bool) { 79 return 80 } 81 82 func (c Comment) AsComment() (Comment, bool) { 83 return c, true 84 } 85 86 func (c Comment) Dump() string { 87 return "#" + c.Comment 88 } 89 90 func (makeThing) AsDirective() (d Directive, ok bool) { 91 return 92 } 93 94 func (d Directive) AsDirective() (Directive, bool) { 95 return d, true 96 } 97 98 func (d Directive) Dump() string { 99 return d.Name + " " + d.Args.Dump() 100 } 101 102 func (makeThing) AsRule() (r Rule, ok bool) { 103 return 104 } 105 106 func (r Rule) AsRule() (Rule, bool) { 107 return r, true 108 } 109 110 func (r Rule) Dump() string { 111 recipe := "" 112 if r.Recipe != "" { 113 recipe = "\n" + r.Recipe 114 } 115 return "rule: " + r.Target.Dump() + ": " + r.Prerequisites.Dump() + recipe 116 } 117 118 func (makeThing) AsVariable() (v Variable, ok bool) { 119 return 120 } 121 122 func (v Variable) AsVariable() (Variable, bool) { 123 return v, true 124 } 125 126 func (v Variable) Dump() string { 127 return "$(" + v.Name.Dump() + ")" 128 } 129 130 type byPosition []MakeThing 131 132 func (s byPosition) Len() int { 133 return len(s) 134 } 135 136 func (s byPosition) Swap(i, j int) { 137 s[i], s[j] = s[j], s[i] 138 } 139 140 func (s byPosition) Less(i, j int) bool { 141 return s[i].Pos().Offset < s[j].Pos().Offset 142 } 143