|  | // Copyright 2017 Google Inc. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | package parser | 
|  |  | 
|  | type Pos int | 
|  |  | 
|  | const NoPos Pos = 0 | 
|  |  | 
|  | type Node interface { | 
|  | Dump() string | 
|  | Pos() Pos | 
|  | End() Pos | 
|  | } | 
|  |  | 
|  | type Assignment struct { | 
|  | Target *MakeString | 
|  | Name   *MakeString | 
|  | Value  *MakeString | 
|  | Type   string | 
|  | } | 
|  |  | 
|  | func (x *Assignment) Dump() string { | 
|  | target := "" | 
|  | if x.Target != nil { | 
|  | target = x.Target.Dump() + ": " | 
|  | } | 
|  | return target + x.Name.Dump() + " " + x.Type + " " + x.Value.Dump() | 
|  | } | 
|  |  | 
|  | func (x *Assignment) Pos() Pos { | 
|  | if x.Target != nil { | 
|  | return x.Target.Pos() | 
|  | } | 
|  | return x.Name.Pos() | 
|  | } | 
|  |  | 
|  | func (x *Assignment) End() Pos { return x.Value.End() } | 
|  |  | 
|  | type Comment struct { | 
|  | CommentPos Pos | 
|  | Comment    string | 
|  | } | 
|  |  | 
|  | func (x *Comment) Dump() string { | 
|  | return "#" + x.Comment | 
|  | } | 
|  |  | 
|  | func (x *Comment) Pos() Pos { return x.CommentPos } | 
|  | func (x *Comment) End() Pos { return Pos(int(x.CommentPos) + len(x.Comment)) } | 
|  |  | 
|  | type Directive struct { | 
|  | NamePos Pos | 
|  | Name    string | 
|  | Args    *MakeString | 
|  | EndPos  Pos | 
|  | } | 
|  |  | 
|  | func (x *Directive) Dump() string { | 
|  | return x.Name + " " + x.Args.Dump() | 
|  | } | 
|  |  | 
|  | func (x *Directive) Pos() Pos { return x.NamePos } | 
|  | func (x *Directive) End() Pos { | 
|  | if x.EndPos != NoPos { | 
|  | return x.EndPos | 
|  | } | 
|  | return x.Args.End() | 
|  | } | 
|  |  | 
|  | type Rule struct { | 
|  | Target        *MakeString | 
|  | Prerequisites *MakeString | 
|  | RecipePos     Pos | 
|  | Recipe        string | 
|  | } | 
|  |  | 
|  | func (x *Rule) Dump() string { | 
|  | recipe := "" | 
|  | if x.Recipe != "" { | 
|  | recipe = "\n" + x.Recipe | 
|  | } | 
|  | return "rule:       " + x.Target.Dump() + ": " + x.Prerequisites.Dump() + recipe | 
|  | } | 
|  |  | 
|  | func (x *Rule) Pos() Pos { return x.Target.Pos() } | 
|  | func (x *Rule) End() Pos { return Pos(int(x.RecipePos) + len(x.Recipe)) } | 
|  |  | 
|  | type Variable struct { | 
|  | Name *MakeString | 
|  | } | 
|  |  | 
|  | func (x *Variable) Pos() Pos { return x.Name.Pos() } | 
|  | func (x *Variable) End() Pos { return x.Name.End() } | 
|  |  | 
|  | func (x *Variable) Dump() string { | 
|  | return "$(" + x.Name.Dump() + ")" | 
|  | } | 
|  |  | 
|  | // Sort interface for []Node by position | 
|  | type byPosition []Node | 
|  |  | 
|  | func (s byPosition) Len() int { | 
|  | return len(s) | 
|  | } | 
|  |  | 
|  | func (s byPosition) Swap(i, j int) { | 
|  | s[i], s[j] = s[j], s[i] | 
|  | } | 
|  |  | 
|  | func (s byPosition) Less(i, j int) bool { | 
|  | return s[i].Pos() < s[j].Pos() | 
|  | } |