mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-30 04:20:53 +00:00
Conver to regular Go vendor + dep tool
This commit is contained in:
+200
@@ -0,0 +1,200 @@
|
||||
//Copyright 2013 GoGraphviz Authors
|
||||
//
|
||||
//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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
import "github.com/awalterschulze/gographviz/token"
|
||||
|
||||
type (
|
||||
ActionTab []ActionRow
|
||||
ActionRow map[token.Type]Action
|
||||
)
|
||||
|
||||
func (R ActionRow) String() string {
|
||||
s := ""
|
||||
for t, a := range R {
|
||||
s += strconv.Itoa(int(t)) + " : " + a.String() + "\n"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type (
|
||||
Accept int
|
||||
Shift State
|
||||
Reduce int
|
||||
|
||||
Action interface {
|
||||
Act()
|
||||
String() string
|
||||
}
|
||||
)
|
||||
|
||||
func (this Accept) Act() {}
|
||||
func (this Shift) Act() {}
|
||||
func (this Reduce) Act() {}
|
||||
|
||||
func (this Accept) String() string { return "Accept(0)" }
|
||||
func (this Shift) String() string { return "Shift(" + strconv.Itoa(int(this)) + ")" }
|
||||
func (this Reduce) String() string { return "Reduce(" + strconv.Itoa(int(this)) + ")" }
|
||||
|
||||
type (
|
||||
GotoTab []GotoRow
|
||||
GotoRow map[NT]State
|
||||
State int
|
||||
NT string
|
||||
)
|
||||
|
||||
type (
|
||||
ProdTab []ProdTabEntry
|
||||
ProdTabEntry struct {
|
||||
String string
|
||||
Head NT
|
||||
NumSymbols int
|
||||
ReduceFunc func([]Attrib) (Attrib, error)
|
||||
}
|
||||
Attrib interface {
|
||||
String() string
|
||||
}
|
||||
)
|
||||
|
||||
/*** Stack ***/
|
||||
|
||||
type stack struct {
|
||||
state []State
|
||||
attrib []Attrib
|
||||
}
|
||||
|
||||
const INITIAL_STACK_SIZE = 100
|
||||
|
||||
func NewStack() *stack {
|
||||
return &stack{state: make([]State, 0, INITIAL_STACK_SIZE),
|
||||
attrib: make([]Attrib, 0, INITIAL_STACK_SIZE),
|
||||
}
|
||||
}
|
||||
|
||||
func (this *stack) Push(s State, a Attrib) {
|
||||
this.state = append(this.state, s)
|
||||
this.attrib = append(this.attrib, a)
|
||||
}
|
||||
|
||||
func (this *stack) Top() State {
|
||||
return this.state[len(this.state)-1]
|
||||
}
|
||||
|
||||
func (this *stack) PopN(items int) []Attrib {
|
||||
lo, hi := len(this.state)-items, len(this.state)
|
||||
|
||||
attrib := this.attrib[lo:hi]
|
||||
|
||||
this.state = this.state[:lo]
|
||||
this.attrib = this.attrib[:lo]
|
||||
|
||||
return attrib
|
||||
}
|
||||
|
||||
func (S *stack) String() string {
|
||||
res := "stack:\n"
|
||||
for i, st := range S.state {
|
||||
res += "\t" + strconv.Itoa(i) + ": " + strconv.Itoa(int(st))
|
||||
res += " , "
|
||||
if S.attrib[i] == nil {
|
||||
res += "nil"
|
||||
} else {
|
||||
res += S.attrib[i].String()
|
||||
}
|
||||
res += "\n"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/*** Parser ***/
|
||||
|
||||
type Parser struct {
|
||||
actTab ActionTab
|
||||
gotoTab GotoTab
|
||||
prodTab ProdTab
|
||||
stack *stack
|
||||
nextToken *token.Token
|
||||
pos token.Position
|
||||
tokenMap *token.TokenMap
|
||||
}
|
||||
|
||||
type Scanner interface {
|
||||
Scan() (*token.Token, token.Position)
|
||||
}
|
||||
|
||||
func NewParser(act ActionTab, gto GotoTab, prod ProdTab, tm *token.TokenMap) *Parser {
|
||||
p := &Parser{actTab: act, gotoTab: gto, prodTab: prod, stack: NewStack(), tokenMap: tm}
|
||||
p.stack.Push(0, nil) //TODO: which attribute should be pushed here?
|
||||
return p
|
||||
}
|
||||
|
||||
func (P *Parser) Error(err error) error {
|
||||
errmsg := "Error: " + P.TokString(P.nextToken) + " @ " + P.pos.String()
|
||||
if err != nil {
|
||||
errmsg += " " + err.Error()
|
||||
} else {
|
||||
errmsg += ", expected one of: "
|
||||
actRow := P.actTab[P.stack.Top()]
|
||||
i := 0
|
||||
for t := range actRow {
|
||||
errmsg += P.tokenMap.TokenString(t)
|
||||
if i < len(actRow)-1 {
|
||||
errmsg += " "
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return errors.New(errmsg)
|
||||
}
|
||||
|
||||
func (P *Parser) TokString(tok *token.Token) string {
|
||||
msg := P.tokenMap.TokenString(tok.Type) + "(" + strconv.Itoa(int(tok.Type)) + ")"
|
||||
msg += " " + string(tok.Lit)
|
||||
return msg
|
||||
}
|
||||
|
||||
func (this *Parser) Parse(scanner Scanner) (res interface{}, err error) {
|
||||
this.nextToken, this.pos = scanner.Scan()
|
||||
for acc := false; !acc; {
|
||||
action, ok := this.actTab[this.stack.Top()][this.nextToken.Type]
|
||||
if !ok {
|
||||
return nil, this.Error(nil)
|
||||
}
|
||||
switch act := action.(type) {
|
||||
case Accept:
|
||||
res = this.stack.PopN(1)[0]
|
||||
acc = true
|
||||
case Shift:
|
||||
this.stack.Push(State(act), this.nextToken)
|
||||
this.nextToken, this.pos = scanner.Scan()
|
||||
case Reduce:
|
||||
prod := this.prodTab[int(act)]
|
||||
attrib, err := prod.ReduceFunc(this.stack.PopN(prod.NumSymbols))
|
||||
if err != nil {
|
||||
return nil, this.Error(err)
|
||||
} else {
|
||||
this.stack.Push(this.gotoTab[this.stack.Top()][prod.Head], attrib)
|
||||
}
|
||||
default:
|
||||
panic("unknown action")
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
Reference in New Issue
Block a user