Colin Cross | 3f40fa4 | 2015-01-30 17:27:36 -0800 | [diff] [blame^] | 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 | } |