mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-14 11:17:52 +08:00
parse: Expose more of the parser.
This commit is contained in:
parent
65579834de
commit
7a4d7b1e54
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,19 +11,28 @@ import (
|
|||
"unicode"
|
||||
)
|
||||
|
||||
// Parse parses elvish source. If the error is not nil, it always has type
|
||||
// Parse parses Elvish source. If the error is not nil, it always has type
|
||||
// ParseError.
|
||||
func Parse(srcname, src string) (*Chunk, error) {
|
||||
ps := &parser{srcname, src, 0, 0, []map[rune]int{{}}, 0, Error{}}
|
||||
bn := parseChunk(ps)
|
||||
ps := NewParser(srcname, src)
|
||||
n := ParseChunk(ps)
|
||||
return n, GetError(ps, src, n)
|
||||
}
|
||||
|
||||
// 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{}}
|
||||
}
|
||||
|
||||
// GetError gets the parsing error after calling one of the parse* functions.
|
||||
func GetError(ps *parser, src string, n Node) error {
|
||||
if ps.pos != len(src) {
|
||||
ps.error(errUnexpectedRune)
|
||||
}
|
||||
var err error
|
||||
if len(ps.errors.Entries) > 0 {
|
||||
err = &ps.errors
|
||||
return &ps.errors
|
||||
}
|
||||
return bn, err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Errors.
|
||||
|
@ -73,7 +82,7 @@ type Chunk struct {
|
|||
func (bn *Chunk) parse(ps *parser) {
|
||||
bn.parseSeps(ps)
|
||||
for startsPipeline(ps.peek()) {
|
||||
bn.addToPipelines(parsePipeline(ps))
|
||||
bn.addToPipelines(ParsePipeline(ps))
|
||||
if bn.parseSeps(ps) == 0 {
|
||||
break
|
||||
}
|
||||
|
@ -123,14 +132,14 @@ type Pipeline struct {
|
|||
}
|
||||
|
||||
func (pn *Pipeline) parse(ps *parser) {
|
||||
pn.addToForms(parseForm(ps))
|
||||
pn.addToForms(ParseForm(ps))
|
||||
for parseSep(pn, ps, '|') {
|
||||
parseSpacesAndNewlines(pn, ps)
|
||||
if !startsForm(ps.peek()) {
|
||||
ps.error(errShouldBeForm)
|
||||
return
|
||||
}
|
||||
pn.addToForms(parseForm(ps))
|
||||
pn.addToForms(ParseForm(ps))
|
||||
}
|
||||
parseSpaces(pn, ps)
|
||||
if ps.peek() == '&' {
|
||||
|
@ -174,7 +183,7 @@ func (fn *Form) parse(ps *parser) {
|
|||
// Bad form.
|
||||
ps.error(fmt.Errorf("bad rune at form head: %q", ps.peek()))
|
||||
}
|
||||
fn.setHead(parseCompound(ps, true))
|
||||
fn.setHead(ParseCompound(ps, true))
|
||||
parseSpaces(fn, ps)
|
||||
|
||||
for {
|
||||
|
@ -188,22 +197,22 @@ func (fn *Form) parse(ps *parser) {
|
|||
// background indicator
|
||||
return
|
||||
}
|
||||
fn.addToOpts(parseMapPair(ps))
|
||||
fn.addToOpts(ParseMapPair(ps))
|
||||
case startsCompound(r, false):
|
||||
if ps.hasPrefix("?>") {
|
||||
if fn.ExitusRedir != nil {
|
||||
ps.error(errDuplicateExitusRedir)
|
||||
// Parse the duplicate redir anyway.
|
||||
addChild(fn, parseExitusRedir(ps))
|
||||
addChild(fn, ParseExitusRedir(ps))
|
||||
} else {
|
||||
fn.setExitusRedir(parseExitusRedir(ps))
|
||||
fn.setExitusRedir(ParseExitusRedir(ps))
|
||||
}
|
||||
continue
|
||||
}
|
||||
cn := parseCompound(ps, false)
|
||||
cn := ParseCompound(ps, false)
|
||||
if isRedirSign(ps.peek()) {
|
||||
// Redir
|
||||
fn.addToRedirs(parseRedir(ps, cn))
|
||||
fn.addToRedirs(ParseRedir(ps, cn))
|
||||
} else if cn.sourceText == "=" {
|
||||
// Spacey assignment.
|
||||
// Turn the equal sign into a Sep.
|
||||
|
@ -226,7 +235,7 @@ func (fn *Form) parse(ps *parser) {
|
|||
fn.addToArgs(cn)
|
||||
}
|
||||
case isRedirSign(r):
|
||||
fn.addToRedirs(parseRedir(ps, nil))
|
||||
fn.addToRedirs(ParseRedir(ps, nil))
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
@ -244,7 +253,7 @@ func (fn *Form) tryAssignment(ps *parser) bool {
|
|||
|
||||
pos := ps.pos
|
||||
errorEntries := ps.errors.Entries
|
||||
an := parseAssignment(ps)
|
||||
an := ParseAssignment(ps)
|
||||
// If errors were added, revert
|
||||
if len(ps.errors.Entries) > len(errorEntries) {
|
||||
ps.errors.Entries = errorEntries
|
||||
|
@ -268,7 +277,7 @@ type Assignment struct {
|
|||
|
||||
func (an *Assignment) parse(ps *parser) {
|
||||
ps.cut('=')
|
||||
an.setLeft(parseIndexing(ps, false))
|
||||
an.setLeft(ParseIndexing(ps, false))
|
||||
head := an.Left.Head
|
||||
if !checkVariableInAssignment(head, ps) {
|
||||
ps.errorp(head.Begin(), head.End(), errShouldBeVariableName)
|
||||
|
@ -278,7 +287,7 @@ func (an *Assignment) parse(ps *parser) {
|
|||
if !parseSep(an, ps, '=') {
|
||||
ps.error(errShouldBeEqual)
|
||||
}
|
||||
an.setRight(parseCompound(ps, false))
|
||||
an.setRight(ParseCompound(ps, false))
|
||||
}
|
||||
|
||||
func checkVariableInAssignment(p *Primary, ps *parser) bool {
|
||||
|
@ -312,7 +321,7 @@ func (ern *ExitusRedir) parse(ps *parser) {
|
|||
ps.next()
|
||||
addSep(ern, ps)
|
||||
parseSpaces(ern, ps)
|
||||
ern.setDest(parseCompound(ps, false))
|
||||
ern.setDest(ParseCompound(ps, false))
|
||||
}
|
||||
|
||||
// Redir = { Compound } { '<'|'>'|'<>'|'>>' } { Space } ( '&'? Compound )
|
||||
|
@ -353,7 +362,7 @@ func (rn *Redir) parse(ps *parser, dest *Compound) {
|
|||
if parseSep(rn, ps, '&') {
|
||||
rn.RightIsFd = true
|
||||
}
|
||||
rn.setRight(parseCompound(ps, false))
|
||||
rn.setRight(ParseCompound(ps, false))
|
||||
if len(rn.Right.Indexings) == 0 {
|
||||
if rn.RightIsFd {
|
||||
ps.error(errShouldBeFD)
|
||||
|
@ -389,7 +398,7 @@ type Compound struct {
|
|||
func (cn *Compound) parse(ps *parser, head bool) {
|
||||
cn.tilde(ps)
|
||||
for startsIndexing(ps.peek(), head) {
|
||||
cn.addToIndexings(parseIndexing(ps, head))
|
||||
cn.addToIndexings(ParseIndexing(ps, head))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,14 +428,14 @@ type Indexing struct {
|
|||
}
|
||||
|
||||
func (in *Indexing) parse(ps *parser, head bool) {
|
||||
in.setHead(parsePrimary(ps, head))
|
||||
in.setHead(ParsePrimary(ps, head))
|
||||
for parseSep(in, ps, '[') {
|
||||
if !startsArray(ps.peek()) {
|
||||
ps.error(errShouldBeArray)
|
||||
}
|
||||
|
||||
ps.pushCutset()
|
||||
in.addToIndicies(parseArray(ps, false))
|
||||
in.addToIndicies(ParseArray(ps, false))
|
||||
ps.popCutset()
|
||||
|
||||
if !parseSep(in, ps, ']') {
|
||||
|
@ -463,7 +472,7 @@ func (sn *Array) parse(ps *parser, allowSemicolon bool) {
|
|||
|
||||
parseSep()
|
||||
for startsCompound(ps.peek(), false) {
|
||||
sn.addToCompounds(parseCompound(ps, false))
|
||||
sn.addToCompounds(ParseCompound(ps, false))
|
||||
parseSep()
|
||||
}
|
||||
}
|
||||
|
@ -725,7 +734,7 @@ func (pn *Primary) exitusCapture(ps *parser) {
|
|||
pn.Type = ExceptionCapture
|
||||
|
||||
ps.pushCutset()
|
||||
pn.setChunk(parseChunk(ps))
|
||||
pn.setChunk(ParseChunk(ps))
|
||||
ps.popCutset()
|
||||
|
||||
if !parseSep(pn, ps, ')') {
|
||||
|
@ -759,7 +768,7 @@ func (pn *Primary) outputCapture(ps *parser) {
|
|||
} else {
|
||||
ps.pushCutset()
|
||||
}
|
||||
pn.setChunk(parseChunk(ps))
|
||||
pn.setChunk(ParseChunk(ps))
|
||||
ps.popCutset()
|
||||
|
||||
if !parseSep(pn, ps, closer) {
|
||||
|
@ -795,7 +804,7 @@ func (pn *Primary) lbracket(ps *parser) {
|
|||
// { MapPair { Space } } ']': Wind back
|
||||
ps.pos = amp
|
||||
for ps.peek() == '&' {
|
||||
pn.addToMapPairs(parseMapPair(ps))
|
||||
pn.addToMapPairs(ParseMapPair(ps))
|
||||
parseSpacesAndNewlines(pn, ps)
|
||||
}
|
||||
}
|
||||
|
@ -804,7 +813,7 @@ func (pn *Primary) lbracket(ps *parser) {
|
|||
ps.error(errShouldBeRBracket)
|
||||
}
|
||||
default:
|
||||
pn.setList(parseArray(ps, true))
|
||||
pn.setList(ParseArray(ps, true))
|
||||
ps.popCutset()
|
||||
|
||||
if !parseSep(pn, ps, ']') {
|
||||
|
@ -825,7 +834,7 @@ func (pn *Primary) lbracket(ps *parser) {
|
|||
func (pn *Primary) lambda(ps *parser) {
|
||||
pn.Type = Lambda
|
||||
ps.pushCutset()
|
||||
pn.setChunk(parseChunk(ps))
|
||||
pn.setChunk(ParseChunk(ps))
|
||||
ps.popCutset()
|
||||
if !parseSep(pn, ps, '}') {
|
||||
ps.error(errShouldBeRBrace)
|
||||
|
@ -850,7 +859,7 @@ func (pn *Primary) lbrace(ps *parser) {
|
|||
// XXX: The compound can be empty, which allows us to parse {,foo}.
|
||||
// Allowing compounds to be empty can be fragile in other cases.
|
||||
ps.cut(',')
|
||||
pn.addToBraced(parseCompound(ps, false))
|
||||
pn.addToBraced(ParseCompound(ps, false))
|
||||
ps.uncut(',')
|
||||
|
||||
for isBracedSep(ps.peek()) {
|
||||
|
@ -860,7 +869,7 @@ func (pn *Primary) lbrace(ps *parser) {
|
|||
parseSpacesAndNewlines(pn, ps)
|
||||
|
||||
ps.cut(',')
|
||||
pn.addToBraced(parseCompound(ps, false))
|
||||
pn.addToBraced(ParseCompound(ps, false))
|
||||
ps.uncut(',')
|
||||
}
|
||||
if !parseSep(pn, ps, '}') {
|
||||
|
@ -910,7 +919,7 @@ func (mpn *MapPair) parse(ps *parser) {
|
|||
|
||||
// Parse key part, cutting on '='.
|
||||
ps.cut('=')
|
||||
mpn.setKey(parseCompound(ps, false))
|
||||
mpn.setKey(ParseCompound(ps, false))
|
||||
if len(mpn.Key.Indexings) == 0 {
|
||||
ps.error(errShouldBeCompound)
|
||||
}
|
||||
|
@ -919,7 +928,7 @@ func (mpn *MapPair) parse(ps *parser) {
|
|||
if parseSep(mpn, ps, '=') {
|
||||
parseSpacesAndNewlines(mpn, ps)
|
||||
// Parse value part.
|
||||
mpn.setValue(parseCompound(ps, false))
|
||||
mpn.setValue(ParseCompound(ps, false))
|
||||
// The value part can be empty.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,12 @@ import (
|
|||
//
|
||||
// NOTE: The str member is assumed to be valid UF-8.
|
||||
type parser struct {
|
||||
srcName string
|
||||
src string
|
||||
pos int
|
||||
overEOF int
|
||||
cutsets []map[rune]int
|
||||
controls int
|
||||
errors Error
|
||||
srcName string
|
||||
src string
|
||||
pos int
|
||||
overEOF int
|
||||
cutsets []map[rune]int
|
||||
errors Error
|
||||
}
|
||||
|
||||
const eof rune = -1
|
||||
|
|
Loading…
Reference in New Issue
Block a user