Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MatrixLit #1840

Merged
merged 5 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion ast/ast_gop.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (*EnvExpr) exprNode() {}
// A SliceLit node represents a slice literal.
type SliceLit struct {
Lbrack token.Pos // position of "["
Elts []Expr // list of composite elements; or nil
Elts []Expr // list of slice elements; or nil
Rbrack token.Pos // position of "]"
Incomplete bool // true if (source) expressions are missing in the Elts list
}
Expand All @@ -137,6 +137,28 @@ func (*SliceLit) exprNode() {}

// -----------------------------------------------------------------------------

// A MatrixLit node represents a matrix literal.
type MatrixLit struct {
Lbrack token.Pos // position of "["
Elts [][]Expr // list of matrix elements
Rbrack token.Pos // position of "]"
Incomplete bool // true if (source) expressions are missing in the Elts list
}

// Pos - position of first character belonging to the node.
func (p *MatrixLit) Pos() token.Pos {
return p.Lbrack
}

// End - position of first character immediately after the node.
func (p *MatrixLit) End() token.Pos {
return p.Rbrack + 1
}

func (*MatrixLit) exprNode() {}

// -----------------------------------------------------------------------------

// ErrWrapExpr represents `expr!`, `expr?` or `expr?: defaultValue`.
type ErrWrapExpr struct {
X Expr
Expand Down
3 changes: 3 additions & 0 deletions parser/_nofmt/matrix1/matrix.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
echo [
1, 2, 3
4, 5, 6 ]
43 changes: 43 additions & 0 deletions parser/_nofmt/matrix1/parser.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

file matrix.gop
noEntrypoint
ast.FuncDecl:
Name:
ast.Ident:
Name: main
Type:
ast.FuncType:
Params:
ast.FieldList:
Body:
ast.BlockStmt:
List:
ast.ExprStmt:
X:
ast.CallExpr:
Fun:
ast.Ident:
Name: echo
Args:
ast.MatrixLit:
Elts:
ast.BasicLit:
Kind: INT
Value: 1
ast.BasicLit:
Kind: INT
Value: 2
ast.BasicLit:
Kind: INT
Value: 3
ast.BasicLit:
Kind: INT
Value: 4
ast.BasicLit:
Kind: INT
Value: 5
ast.BasicLit:
Kind: INT
Value: 6
NElt: 2
3 changes: 3 additions & 0 deletions parser/_testdata/embedded1/embtype.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type T struct {
abc.E
}
24 changes: 24 additions & 0 deletions parser/_testdata/embedded1/parser.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

file embtype.gop
ast.GenDecl:
Tok: type
Specs:
ast.TypeSpec:
Name:
ast.Ident:
Name: T
Type:
ast.StructType:
Fields:
ast.FieldList:
List:
ast.Field:
Type:
ast.SelectorExpr:
X:
ast.Ident:
Name: abc
Sel:
ast.Ident:
Name: E
4 changes: 4 additions & 0 deletions parser/_testdata/matrix1/matrix.gop
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
echo [
1, 2, 3
4, 5, 6
]
43 changes: 43 additions & 0 deletions parser/_testdata/matrix1/parser.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

file matrix.gop
noEntrypoint
ast.FuncDecl:
Name:
ast.Ident:
Name: main
Type:
ast.FuncType:
Params:
ast.FieldList:
Body:
ast.BlockStmt:
List:
ast.ExprStmt:
X:
ast.CallExpr:
Fun:
ast.Ident:
Name: echo
Args:
ast.MatrixLit:
Elts:
ast.BasicLit:
Kind: INT
Value: 1
ast.BasicLit:
Kind: INT
Value: 2
ast.BasicLit:
Kind: INT
Value: 3
ast.BasicLit:
Kind: INT
Value: 4
ast.BasicLit:
Kind: INT
Value: 5
ast.BasicLit:
Kind: INT
Value: 6
NElt: 2
27 changes: 21 additions & 6 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ func (p *parser) parseArrayTypeOrSliceLit(state int, slice ast.Expr) (expr ast.E
case stateArrayTypeOrSliceLit:
switch p.tok {
case token.COMMA: // [a, b, c, d ...]
sliceLit := p.parseSliceLit(lbrack, len)
sliceLit := p.parseSliceOrMatrixLit(lbrack, len)
p.exprLev--
return sliceLit, resultSliceLit
case token.FOR: // [expr for k, v <- container if cond]
Expand Down Expand Up @@ -887,20 +887,35 @@ func (p *parser) parseArrayTypeOrSliceLit(state int, slice ast.Expr) (expr ast.E
return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt}, resultArrayType
}

func (p *parser) parseSliceLit(lbrack token.Pos, len ast.Expr) ast.Expr {
// [first, ...]
// [first, a2, a2, ...; b1, b2, b3, ...]
func (p *parser) parseSliceOrMatrixLit(lbrack token.Pos, first ast.Expr) ast.Expr {
var mat [][]ast.Expr
elts := make([]ast.Expr, 1, 8)
elts[0] = len
for p.tok == token.COMMA {
elts[0] = first
for {
switch p.tok {
case token.COMMA:
case token.SEMICOLON:
mat = append(mat, elts)
elts = make([]ast.Expr, 0, len(elts))
default:
goto done
}
p.next()
if p.tok != token.RBRACK {
elt := p.parseRHS()
elts = append(elts, elt)
}
}
done:
rbrack := p.expect(token.RBRACK)

if debugParseOutput {
log.Printf("ast.SliceLit{Elts: %v}\n", elts)
if mat != nil {
if len(elts) > 0 {
mat = append(mat, elts)
}
return &ast.MatrixLit{Lbrack: lbrack, Elts: mat, Rbrack: rbrack}
}
return &ast.SliceLit{Lbrack: lbrack, Elts: elts, Rbrack: rbrack}
}
Expand Down
3 changes: 3 additions & 0 deletions parser/parsertest/parsertest.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ func FprintNode(w io.Writer, lead string, v interface{}, prefix, indent string)
FprintNode(w, fmt.Sprintf("%s%v:\n", prefix, sf.Name), sfv, prefix+indent, indent)
}
}
if m, ok := v.(*ast.MatrixLit); ok {
fmt.Fprintf(w, "%sNElt: %d\n", prefix, len(m.Elts))
}
} else if lit, ok := v.(*ast.StringLitEx); ok {
fmt.Fprintf(w, "%sExtra:\n", prefix)
prefix += indent
Expand Down
25 changes: 22 additions & 3 deletions printer/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,24 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
p.print(indent, unindent, mode, x.Rbrace, token.RBRACE, mode)
p.level--

case *ast.MatrixLit:
p.level++
p.print(x.Lbrack, token.LBRACK, newline, indent)
var last = len(x.Elts) - 1
var incomplete bool
for i, elts := range x.Elts {
if i == last {
incomplete = x.Incomplete
}
p.exprList(elts[0].Pos(), elts, 1, 0, elts[len(elts)-1].End(), incomplete)
p.print(newline)
}
mode := noExtraLinebreak | noExtraBlank
// need the initial indent to print lone comments with
// the proper level of indentation
p.print(unindent, mode, x.Rbrack, token.RBRACK, mode)
p.level--

case *ast.Ellipsis:
p.print(token.ELLIPSIS)
if x.Elt != nil {
Expand Down Expand Up @@ -1034,7 +1052,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
p.print(token.LBRACK)
p.expr0(x.Elt, depth+1)
p.print(blank)
p.listForPhrase(x.Lpos, x.Fors, depth, x.Rpos)
p.listForPhrase(x.Fors)
p.print(token.RBRACK)
default: // {...}
p.print(token.LBRACE)
Expand All @@ -1048,7 +1066,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
}
p.print(blank)
}
p.listForPhrase(x.Lpos, x.Fors, depth, x.Rpos)
p.listForPhrase(x.Fors)
p.print(token.RBRACE)
}
case *ast.ErrWrapExpr:
Expand Down Expand Up @@ -1114,7 +1132,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
}
}

func (p *printer) listForPhrase(prev0 token.Pos, list []*ast.ForPhrase, depth int, next0 token.Pos) {
func (p *printer) listForPhrase(list []*ast.ForPhrase) {
for i, x := range list {
if i > 0 {
p.print(blank)
Expand Down Expand Up @@ -1906,6 +1924,7 @@ func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
// by sep. Otherwise the block's opening "{" is printed on the current line, followed by
// lines for the block's statements and its closing "}".
func (p *printer) funcBodyUnnamed(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
_, _ = headerSize, sep
if b == nil {
return
}
Expand Down
Loading