diff --git a/parse/boilerplate.go b/parse/boilerplate.go index 839da4c8..222cef05 100644 --- a/parse/boilerplate.go +++ b/parse/boilerplate.go @@ -17,7 +17,7 @@ func (n *Chunk) addToPipelines(ch *Pipeline) { addChild(n, ch) } -func ParseChunk(ps *parser) *Chunk { +func ParseChunk(ps *Parser) *Chunk { n := &Chunk{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -42,7 +42,7 @@ func (n *Pipeline) addToForms(ch *Form) { addChild(n, ch) } -func ParsePipeline(ps *parser) *Pipeline { +func ParsePipeline(ps *Parser) *Pipeline { n := &Pipeline{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -97,7 +97,7 @@ func (n *Form) setExitusRedir(ch *ExitusRedir) { addChild(n, ch) } -func ParseForm(ps *parser) *Form { +func ParseForm(ps *Parser) *Form { n := &Form{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -127,7 +127,7 @@ func (n *Assignment) setRight(ch *Compound) { addChild(n, ch) } -func ParseAssignment(ps *parser) *Assignment { +func ParseAssignment(ps *Parser) *Assignment { n := &Assignment{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -152,7 +152,7 @@ func (n *ExitusRedir) setDest(ch *Compound) { addChild(n, ch) } -func ParseExitusRedir(ps *parser) *ExitusRedir { +func ParseExitusRedir(ps *Parser) *ExitusRedir { n := &ExitusRedir{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -182,7 +182,7 @@ func (n *Redir) setRight(ch *Compound) { addChild(n, ch) } -func ParseRedir(ps *parser, dest *Compound) *Redir { +func ParseRedir(ps *Parser, dest *Compound) *Redir { n := &Redir{node: node{begin: ps.pos}} n.parse(ps, dest) n.end = ps.pos @@ -207,7 +207,7 @@ func (n *Compound) addToIndexings(ch *Indexing) { addChild(n, ch) } -func ParseCompound(ps *parser, head bool) *Compound { +func ParseCompound(ps *Parser, head bool) *Compound { n := &Compound{node: node{begin: ps.pos}} n.parse(ps, head) n.end = ps.pos @@ -237,7 +237,7 @@ func (n *Indexing) addToIndicies(ch *Array) { addChild(n, ch) } -func ParseIndexing(ps *parser, head bool) *Indexing { +func ParseIndexing(ps *Parser, head bool) *Indexing { n := &Indexing{node: node{begin: ps.pos}} n.parse(ps, head) n.end = ps.pos @@ -262,7 +262,7 @@ func (n *Array) addToCompounds(ch *Compound) { addChild(n, ch) } -func ParseArray(ps *parser, allowSemicolon bool) *Array { +func ParseArray(ps *Parser, allowSemicolon bool) *Array { n := &Array{node: node{begin: ps.pos}} n.parse(ps, allowSemicolon) n.end = ps.pos @@ -302,7 +302,7 @@ func (n *Primary) addToBraced(ch *Compound) { addChild(n, ch) } -func ParsePrimary(ps *parser, head bool) *Primary { +func ParsePrimary(ps *Parser, head bool) *Primary { n := &Primary{node: node{begin: ps.pos}} n.parse(ps, head) n.end = ps.pos @@ -332,7 +332,7 @@ func (n *MapPair) setValue(ch *Compound) { addChild(n, ch) } -func ParseMapPair(ps *parser) *MapPair { +func ParseMapPair(ps *Parser) *MapPair { n := &MapPair{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos diff --git a/parse/boilerplate.py b/parse/boilerplate.py index 7cc1c363..ba8abce1 100755 --- a/parse/boilerplate.py +++ b/parse/boilerplate.py @@ -16,7 +16,7 @@ For every node type T, it generates the following: method that sets this field and adds it to the children list. * If the type has a parse method that takes a *paser, it genertes a parseT - func that takes a *parser and returns *T. The func creates a new instance of + func that takes a *Parser and returns *T. The func creates a new instance of *T, sets its begin field, calls its parse method, and set its end and sourceText fields. @@ -52,7 +52,7 @@ func (n *X) addToG(ch *Z) { addChild(n, ch) } -func ParseX(ps *parser) *X { +func ParseX(ps *Parser) *X { n := &X{node: node{begin: ps.pos}} n.parse(ps) n.end = ps.pos @@ -103,7 +103,7 @@ func (n *{parent}) addTo{field}(ch *{child}) {{ def put_parse(out, typename, extraargs): extranames = ', '.join(a.split(' ')[0] for a in extraargs.split(', ')) if extraargs else '' print >>out, ''' -func Parse{typename}(ps *parser{extraargs}) *{typename} {{ +func Parse{typename}(ps *Parser{extraargs}) *{typename} {{ n := &{typename}{{node: node{{begin: ps.pos}}}} n.parse(ps{extranames}) n.end = ps.pos @@ -140,7 +140,7 @@ def main(): put_get(out, in_type) continue m = re.match( - r'^func \(.* \*(.*)\) parse\(ps \*parser(.*?)\) {$', line) + r'^func \(.* \*(.*)\) parse\(ps \*Parser(.*?)\) {$', line) if m: typename, extraargs = m.groups() put_parse(out, typename, extraargs) diff --git a/parse/parse.go b/parse/parse.go index add41e9b..3b8ce664 100644 --- a/parse/parse.go +++ b/parse/parse.go @@ -64,7 +64,7 @@ type Chunk struct { Pipelines []*Pipeline } -func (bn *Chunk) parse(ps *parser) { +func (bn *Chunk) parse(ps *Parser) { bn.parseSeps(ps) for startsPipeline(ps.peek()) { bn.addToPipelines(ParsePipeline(ps)) @@ -80,7 +80,7 @@ func isPipelineSep(r rune) bool { // parseSeps parses pipeline separators along with whitespaces. It returns the // number of pipeline separators parsed. -func (bn *Chunk) parseSeps(ps *parser) int { +func (bn *Chunk) parseSeps(ps *Parser) int { nseps := 0 for { r := ps.peek() @@ -116,7 +116,7 @@ type Pipeline struct { Background bool } -func (pn *Pipeline) parse(ps *parser) { +func (pn *Pipeline) parse(ps *Parser) { pn.addToForms(ParseForm(ps)) for parseSep(pn, ps, '|') { parseSpacesAndNewlines(pn, ps) @@ -153,7 +153,7 @@ type Form struct { ExitusRedir *ExitusRedir } -func (fn *Form) parse(ps *parser) { +func (fn *Form) parse(ps *Parser) { parseSpaces(fn, ps) for fn.tryAssignment(ps) { parseSpaces(fn, ps) @@ -231,7 +231,7 @@ func (fn *Form) parse(ps *parser) { // tryAssignment tries to parse an assignment. If succeeded, it adds the parsed // assignment to fn.Assignments and returns true. Otherwise it rewinds the // parser and returns false. -func (fn *Form) tryAssignment(ps *parser) bool { +func (fn *Form) tryAssignment(ps *Parser) bool { if !startsIndexing(ps.peek(), false) || ps.peek() == '=' { return false } @@ -260,7 +260,7 @@ type Assignment struct { Right *Compound } -func (an *Assignment) parse(ps *parser) { +func (an *Assignment) parse(ps *Parser) { ps.cut('=') an.setLeft(ParseIndexing(ps, false)) head := an.Left.Head @@ -275,7 +275,7 @@ func (an *Assignment) parse(ps *parser) { an.setRight(ParseCompound(ps, false)) } -func checkVariableInAssignment(p *Primary, ps *parser) bool { +func checkVariableInAssignment(p *Primary, ps *Parser) bool { if p.Type == Braced { // XXX don't check further inside braced expression return true @@ -301,7 +301,7 @@ type ExitusRedir struct { Dest *Compound } -func (ern *ExitusRedir) parse(ps *parser) { +func (ern *ExitusRedir) parse(ps *Parser) { ps.next() ps.next() addSep(ern, ps) @@ -318,7 +318,7 @@ type Redir struct { Right *Compound } -func (rn *Redir) parse(ps *parser, dest *Compound) { +func (rn *Redir) parse(ps *Parser, dest *Compound) { // The parsing of the Left part is done in Form.parse. if dest != nil { rn.setLeft(dest) @@ -380,7 +380,7 @@ type Compound struct { Indexings []*Indexing } -func (cn *Compound) parse(ps *parser, head bool) { +func (cn *Compound) parse(ps *Parser, head bool) { cn.tilde(ps) for startsIndexing(ps.peek(), head) { cn.addToIndexings(ParseIndexing(ps, head)) @@ -390,7 +390,7 @@ func (cn *Compound) parse(ps *parser, head bool) { // tilde parses a tilde if there is one. It is implemented here instead of // within Primary since a tilde can only appear as the first part of a // Compound. Elsewhere tildes are barewords. -func (cn *Compound) tilde(ps *parser) { +func (cn *Compound) tilde(ps *Parser) { if ps.peek() == '~' { ps.next() base := node{nil, ps.pos - 1, ps.pos, "~", nil} @@ -412,7 +412,7 @@ type Indexing struct { Indicies []*Array } -func (in *Indexing) parse(ps *parser, head bool) { +func (in *Indexing) parse(ps *Parser, head bool) { in.setHead(ParsePrimary(ps, head)) for parseSep(in, ps, '[') { if !startsArray(ps.peek()) { @@ -444,7 +444,7 @@ type Array struct { Semicolons []int } -func (sn *Array) parse(ps *parser, allowSemicolon bool) { +func (sn *Array) parse(ps *Parser, allowSemicolon bool) { parseSep := func() { parseSpacesAndNewlines(sn, ps) if allowSemicolon { @@ -504,7 +504,7 @@ const ( Braced ) -func (pn *Primary) parse(ps *parser, head bool) { +func (pn *Primary) parse(ps *Parser, head bool) { r := ps.peek() if !startsPrimary(r, head) { ps.error(errShouldBePrimary) @@ -545,7 +545,7 @@ func (pn *Primary) parse(ps *parser, head bool) { } } -func (pn *Primary) singleQuoted(ps *parser) { +func (pn *Primary) singleQuoted(ps *Parser) { pn.Type = SingleQuoted ps.next() var buf bytes.Buffer @@ -570,7 +570,7 @@ func (pn *Primary) singleQuoted(ps *parser) { } } -func (pn *Primary) doubleQuoted(ps *parser) { +func (pn *Primary) doubleQuoted(ps *Parser) { pn.Type = DoubleQuoted ps.next() var buf bytes.Buffer @@ -672,7 +672,7 @@ func hexToDigit(r rune) (rune, bool) { } } -func (pn *Primary) variable(ps *parser) { +func (pn *Primary) variable(ps *Parser) { pn.Type = Variable defer func() { pn.Value = ps.src[pn.begin+1 : ps.pos] }() ps.next() @@ -699,7 +699,7 @@ func allowedInVariableName(r rune) bool { r == '-' || r == '_' || r == ':' || r == '&' } -func (pn *Primary) wildcard(ps *parser) { +func (pn *Primary) wildcard(ps *Parser) { pn.Type = Wildcard for isWildcard(ps.peek()) { ps.next() @@ -711,7 +711,7 @@ func isWildcard(r rune) bool { return r == '*' || r == '?' } -func (pn *Primary) exitusCapture(ps *parser) { +func (pn *Primary) exitusCapture(ps *Parser) { ps.next() ps.next() addSep(pn, ps) @@ -727,7 +727,7 @@ func (pn *Primary) exitusCapture(ps *parser) { } } -func (pn *Primary) outputCapture(ps *parser) { +func (pn *Primary) outputCapture(ps *Parser) { pn.Type = OutputCapture var closer rune @@ -766,7 +766,7 @@ func (pn *Primary) outputCapture(ps *parser) { // Map = '[' { Space } '&' { Space } ']' // = '[' { Space } { MapPair { Space } } ']' -func (pn *Primary) lbracket(ps *parser) { +func (pn *Primary) lbracket(ps *Parser) { parseSep(pn, ps, '[') parseSpacesAndNewlines(pn, ps) @@ -816,7 +816,7 @@ func (pn *Primary) lbracket(ps *parser) { } // lambda parses a lambda expression. The opening brace has been seen. -func (pn *Primary) lambda(ps *parser) { +func (pn *Primary) lambda(ps *Parser) { pn.Type = Lambda ps.pushCutset() pn.setChunk(ParseChunk(ps)) @@ -828,7 +828,7 @@ func (pn *Primary) lambda(ps *parser) { // Braced = '{' Compound { BracedSep Compounds } '}' // BracedSep = { Space | '\n' } [ ',' ] { Space | '\n' } -func (pn *Primary) lbrace(ps *parser) { +func (pn *Primary) lbrace(ps *Parser) { parseSep(pn, ps, '{') if r := ps.peek(); r == ';' || r == '\n' || IsSpace(r) { @@ -866,7 +866,7 @@ func isBracedSep(r rune) bool { return r == ',' || IsSpaceOrNewline(r) } -func (pn *Primary) bareword(ps *parser, head bool) { +func (pn *Primary) bareword(ps *Parser, head bool) { pn.Type = Bareword defer func() { pn.Value = ps.src[pn.begin:ps.pos] }() for allowedInBareword(ps.peek(), head) { @@ -899,7 +899,7 @@ type MapPair struct { Key, Value *Compound } -func (mpn *MapPair) parse(ps *parser) { +func (mpn *MapPair) parse(ps *Parser) { parseSep(mpn, ps, '&') // Parse key part, cutting on '='. @@ -930,7 +930,7 @@ func NewSep(src string, begin, end int) *Sep { return &Sep{node{nil, begin, end, src[begin:end], nil}} } -func addSep(n Node, ps *parser) { +func addSep(n Node, ps *Parser) { var begin int ch := n.Children() if len(ch) > 0 { @@ -941,7 +941,7 @@ func addSep(n Node, ps *parser) { addChild(n, NewSep(ps.src, begin, ps.pos)) } -func parseSep(n Node, ps *parser, sep rune) bool { +func parseSep(n Node, ps *Parser, sep rune) bool { if ps.peek() == sep { ps.next() addSep(n, ps) @@ -950,7 +950,7 @@ func parseSep(n Node, ps *parser, sep rune) bool { return false } -func parseSpaces(n Node, ps *parser) { +func parseSpaces(n Node, ps *Parser) { if !IsSpace(ps.peek()) { return } @@ -961,7 +961,7 @@ func parseSpaces(n Node, ps *parser) { addSep(n, ps) } -func parseSpacesAndNewlines(n Node, ps *parser) { +func parseSpacesAndNewlines(n Node, ps *Parser) { // TODO parse comments here. if !IsSpaceOrNewline(ps.peek()) { return diff --git a/parse/parser.go b/parse/parser.go index d3d5d0da..2792dac7 100644 --- a/parse/parser.go +++ b/parse/parser.go @@ -9,10 +9,10 @@ import ( "github.com/elves/elvish/util" ) -// parser maintains some mutable states of parsing. +// Parser maintains some mutable states of parsing. // // NOTE: The str member is assumed to be valid UF-8. -type parser struct { +type Parser struct { srcName string src string pos int @@ -22,12 +22,12 @@ type parser struct { } // NewParser creates a new parser from a piece of source text and its name. -func NewParser(srcname, src string) *parser { - return &parser{srcname, src, 0, 0, []map[rune]int{{}}, Error{}} +func NewParser(srcname, src string) *Parser { + return &Parser{srcname, src, 0, 0, []map[rune]int{{}}, Error{}} } // Done tells the parser that parsing has completed. -func (ps *parser) Done() { +func (ps *Parser) Done() { if ps.pos != len(ps.src) { ps.error(errUnexpectedRune) } @@ -35,16 +35,21 @@ func (ps *parser) Done() { // Errors gets the parsing errors after calling one of the parse* functions. If // the return value is not nil, it is always of type Error. -func (ps *parser) Errors() error { +func (ps *Parser) Errors() error { if len(ps.errors.Entries) > 0 { return &ps.errors } return nil } +// Source returns the source code that is being parsed. +func (ps *Parser) Source() string { + return ps.src +} + const eof rune = -1 -func (ps *parser) peek() rune { +func (ps *Parser) peek() rune { if ps.pos == len(ps.src) { return eof } @@ -55,14 +60,14 @@ func (ps *parser) peek() rune { return r } -func (ps *parser) hasPrefix(prefix string) bool { +func (ps *Parser) hasPrefix(prefix string) bool { return strings.HasPrefix(ps.src[ps.pos:], prefix) } // findWord looks ahead for [a-z]* that is also a valid compound. If the // lookahead fails, it returns an empty string. It is useful for looking for // command leaders. -func (ps *parser) findPossibleLeader() string { +func (ps *Parser) findPossibleLeader() string { rest := ps.src[ps.pos:] i := strings.IndexFunc(rest, func(r rune) bool { return r < 'a' || r > 'z' @@ -78,7 +83,7 @@ func (ps *parser) findPossibleLeader() string { return rest[:i] } -func (ps *parser) next() rune { +func (ps *Parser) next() rune { if ps.pos == len(ps.src) { ps.overEOF++ return eof @@ -91,7 +96,7 @@ func (ps *parser) next() rune { return r } -func (ps *parser) backup() { +func (ps *Parser) backup() { if ps.overEOF > 0 { ps.overEOF-- return @@ -100,7 +105,7 @@ func (ps *parser) backup() { ps.pos -= s } -func (ps *parser) advance(c int) { +func (ps *Parser) advance(c int) { ps.pos += c if ps.pos > len(ps.src) { ps.overEOF = ps.pos - len(ps.src) @@ -108,11 +113,11 @@ func (ps *parser) advance(c int) { } } -func (ps *parser) errorp(begin, end int, e error) { +func (ps *Parser) errorp(begin, end int, e error) { ps.errors.Add(e.Error(), util.SourceContext{ps.srcName, ps.src, begin, end, nil}) } -func (ps *parser) error(e error) { +func (ps *Parser) error(e error) { end := ps.pos if end < len(ps.src) { end++ @@ -120,29 +125,29 @@ func (ps *parser) error(e error) { ps.errorp(ps.pos, end, e) } -func (ps *parser) pushCutset(rs ...rune) { +func (ps *Parser) pushCutset(rs ...rune) { ps.cutsets = append(ps.cutsets, map[rune]int{}) ps.cut(rs...) } -func (ps *parser) popCutset() { +func (ps *Parser) popCutset() { n := len(ps.cutsets) ps.cutsets[n-1] = nil ps.cutsets = ps.cutsets[:n-1] } -func (ps *parser) currentCutset() map[rune]int { +func (ps *Parser) currentCutset() map[rune]int { return ps.cutsets[len(ps.cutsets)-1] } -func (ps *parser) cut(rs ...rune) { +func (ps *Parser) cut(rs ...rune) { cutset := ps.currentCutset() for _, r := range rs { cutset[r]++ } } -func (ps *parser) uncut(rs ...rune) { +func (ps *Parser) uncut(rs ...rune) { cutset := ps.currentCutset() for _, r := range rs { cutset[r]-- diff --git a/parse/string.go b/parse/string.go index 11cc8599..dda6ab87 100644 --- a/parse/string.go +++ b/parse/string.go @@ -1,4 +1,4 @@ -// Code generated by "stringer -type=PrimaryType,RedirMode -output=string.go"; DO NOT EDIT +// Code generated by "stringer -type=PrimaryType,RedirMode -output=string.go"; DO NOT EDIT. package parse