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