cue/parser: allow attributes before package and import clauses

This is to facilitate "build tags".

Change-Id: I8ea85d4f1339a3584e7763d342715b8fad2fe48f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7062
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/cue/parser/parser.go b/cue/parser/parser.go
index 9d96e8f..2e24158 100644
--- a/cue/parser/parser.go
+++ b/cue/parser/parser.go
@@ -1606,6 +1606,11 @@
 
 	var decls []ast.Decl
 
+	for p.tok == token.ATTRIBUTE {
+		decls = append(decls, p.parseAttribute())
+		p.consumeDeclComma()
+	}
+
 	// The package clause is not a declaration: it does not appear in any
 	// scope.
 	if p.tok == token.IDENT && p.lit == "package" {
@@ -1628,6 +1633,11 @@
 		c.closeNode(p, pkg)
 	}
 
+	for p.tok == token.ATTRIBUTE {
+		decls = append(decls, p.parseAttribute())
+		p.consumeDeclComma()
+	}
+
 	if p.mode&packageClauseOnlyMode == 0 {
 		// import decls
 		for p.tok == token.IDENT && p.lit == "import" {
diff --git a/cue/parser/parser_test.go b/cue/parser/parser_test.go
index 20d3e1b..6ec737d 100644
--- a/cue/parser/parser_test.go
+++ b/cue/parser/parser_test.go
@@ -410,6 +410,20 @@
 		`,
 		`<[l5// d] a: 1 @a() @b()>`,
 	}, {
+		"attribute declarations",
+		`
+		@foo()
+
+		package bar
+
+		@bar()
+
+		import "strings"
+
+		@baz()
+			`,
+		`@foo(), package bar, @bar(), import "strings", @baz()`,
+	}, {
 		"comprehension comments",
 		`
 		if X {
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index f7f0326..8d7f2eb 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -2899,7 +2899,7 @@
 to a data format
 
 ```
-SourceFile = [ PackageClause "," ] { ImportDecl "," } { Declaration "," } .
+SourceFile = { attribute "," } [ PackageClause "," ] { ImportDecl "," } { Declaration "," } .
 ```
 
 ```
diff --git a/internal/internal.go b/internal/internal.go
index 934c455..066d26f 100644
--- a/internal/internal.go
+++ b/internal/internal.go
@@ -131,6 +131,7 @@
 	for _, d := range f.Decls {
 		switch x := d.(type) {
 		case *ast.CommentGroup:
+		case *ast.Attribute:
 		case *ast.Package:
 			if x.Name == nil {
 				break