File: cmpd.go

package info (click to toggle)
elvish 0.21.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,372 kB
  • sloc: javascript: 236; sh: 130; python: 104; makefile: 88; xml: 9
file content (66 lines) | stat: -rw-r--r-- 1,837 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Package cmpd contains utilities for working with compound nodes.
package cmpd

import (
	"fmt"

	"src.elv.sh/pkg/parse"
)

// Primary returns a primary node and true if that's the only child of the
// compound node. Otherwise it returns nil and false.
func Primary(n *parse.Compound) (*parse.Primary, bool) {
	if n != nil && len(n.Indexings) == 1 && len(n.Indexings[0].Indices) == 0 {
		return n.Indexings[0].Head, true
	}
	return nil, false
}

// StringLiteral returns the value of a string literal and true if that's the
// only child of the compound node. Otherwise it returns "" and false.
func StringLiteral(n *parse.Compound) (string, bool) {
	if pn, ok := Primary(n); ok {
		switch pn.Type {
		case parse.Bareword, parse.SingleQuoted, parse.DoubleQuoted:
			return pn.Value, true
		}
	}
	return "", false
}

// Lambda returns a lambda primary node and true if that's the only child of the
// compound node. Otherwise it returns nil and false.
func Lambda(n *parse.Compound) (*parse.Primary, bool) {
	if pn, ok := Primary(n); ok {
		if pn.Type == parse.Lambda {
			return pn, true
		}
	}
	return nil, false
}

// StringLiteralOrError is like StringLiteral, but returns an error suitable as
// a compiler error when StringLiteral would return false.
func StringLiteralOrError(n *parse.Compound, what string) (string, error) {
	s, ok := StringLiteral(n)
	if !ok {
		return "", fmt.Errorf("%s must be string literal, found %s", what, Shape(n))
	}
	return s, nil
}

// Shape describes the shape of the compound node.
func Shape(n *parse.Compound) string {
	if len(n.Indexings) == 0 {
		return "empty expression"
	}
	if len(n.Indexings) > 1 {
		return "compound expression"
	}
	in := n.Indexings[0]
	if len(in.Indices) > 0 {
		return "indexing expression"
	}
	pn := in.Head
	return "primary expression of type " + pn.Type.String()
}