-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
draft: stateful parser is too stateful
- Loading branch information
Showing
10 changed files
with
344 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Exporting declarations | ||
export let name1, name2/*, … */; // also var | ||
export const name1 = 1, name2 = 2/*, … */; // also var, let | ||
export function functionName() { /* … */ } | ||
export class ClassName { /* … */ } | ||
export function* generatorFunctionName() { /* … */ } | ||
export const { name1, name2: bar } = o; | ||
export const [ name1, name2 ] = array; | ||
|
||
const nameN = 0 | ||
const variable1 = 0 | ||
const variable2 = 0 | ||
|
||
// Export list | ||
export { name1, /* …, */ nameN }; | ||
export { variable1 as name1, variable2 as name2, /* …, */ nameN }; | ||
export { name1 as default /*, … */ }; | ||
|
||
// Default exports | ||
export default expression; | ||
export default function functionName() { /* … */ } | ||
export default class ClassName { /* … */ } | ||
export default function* generatorFunctionName() { /* … */ } | ||
export default function () { /* … */ } | ||
export default class { /* … */ } | ||
export default function* () { /* … */ } | ||
|
||
// Aggregating modules | ||
export * from "module-name"; | ||
export * as name1 from "module-name"; | ||
export { name1, /* …, */ nameN } from "module-name"; | ||
export { import1 as name1, import2 as name2, /* …, */ nameN } from "module-name"; | ||
export { default, /* …, */ } from "module-name"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
//nolint:govet | ||
package grammar | ||
|
||
import ( | ||
"github.com/alecthomas/participle/v2/lexer" | ||
) | ||
|
||
type ExportDeconstruction struct { | ||
Names []string `"{" ((Ident "as" @Ident) | @Ident) ("," ((Ident "as" @Ident) | @Ident))* "}"` | ||
} | ||
|
||
type DeclarationExport struct { | ||
Default bool `"export" ("let"|"const"|"var"|"function"|"class")` | ||
Name string `@Ident` | ||
} | ||
|
||
type ListExport struct { | ||
ExportDeconstruction *ExportDeconstruction `"export" @@` | ||
} | ||
|
||
type DefaultExport struct { | ||
Default bool `"export" "default"` | ||
} | ||
|
||
type ProxyExport struct { | ||
ExportDeconstruction *ExportDeconstruction `"export" @@` | ||
From string `"from" @String` | ||
} | ||
|
||
var exportLexer = lexer.Rules{ | ||
"CommonExport": { | ||
{"ALL", `\*`, nil}, | ||
{"Comment", commentRe, nil}, | ||
{"Whitespace", `\s+`, nil}, | ||
{"Punct", punctuationRe, nil}, | ||
}, | ||
"DeclarationExport": { | ||
{Name: "String", Pattern: stringRe}, | ||
{Name: "Ident", Pattern: identRe, Action: lexer.Pop()}, | ||
lexer.Include("CommonExport"), | ||
}, | ||
"ListExport": { | ||
{Name: "ClosingBracket", Pattern: `}`, Action: lexer.Pop()}, | ||
{Name: "String", Pattern: stringRe}, | ||
{Name: "Ident", Pattern: identRe}, | ||
lexer.Include("CommonExport"), | ||
}, | ||
"DefaultExport": { | ||
{Name: "Default", Pattern: `default`, Action: lexer.Pop()}, | ||
{Name: "String", Pattern: stringRe}, | ||
{Name: "Ident", Pattern: identRe}, | ||
lexer.Include("CommonExport"), | ||
}, | ||
"ProxyExport": { | ||
{Name: "String", Pattern: stringRe, Action: lexer.Pop()}, | ||
{Name: "Ident", Pattern: identRe}, | ||
lexer.Include("CommonExport"), | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package grammar | ||
|
||
import ( | ||
"os" | ||
"path" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestExport(t *testing.T) { | ||
tests := []struct { | ||
Name string | ||
ExpectedDeclaration []string | ||
ExpectedProxy []string | ||
}{ | ||
{ | ||
Name: `export let name1, name2;`, | ||
ExpectedDeclaration: []string{"name1"}, | ||
}, | ||
{ | ||
Name: `export const name1 = 1`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export function functionName() { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export class ClassName { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export function* generatorFunctionName() { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export const { name1, name2: bar } = o;`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export const [ name1, name2 ] = array;`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { name1, /* …, */ nameN };`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { variable1 as name1, variable2 as name2, /* …, */ nameN };`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { variable1 as "string name" };`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { name1 as default /*, … */ };`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default expression;`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default function functionName() { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default class ClassName { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default function* generatorFunctionName() { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default function () { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default class { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export default function* () { /* … */ }`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export * from "module-name";`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export * as name1 from "module-name";`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { name1, /* …, */ nameN } from "module-name";`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { import1 as name1, import2 as name2, /* …, */ nameN } from "module-name";`, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: `export { default, /* …, */ } from "module-name"; `, | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
{ | ||
Name: "export.js", | ||
ExpectedDeclaration: []string{}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.Name, func(t *testing.T) { | ||
a := require.New(t) | ||
var content []byte | ||
if strings.HasSuffix(tt.Name, ".js") { | ||
var err error | ||
content, err = os.ReadFile(path.Join(".export_test", tt.Name)) | ||
a.NoError(err) | ||
} else { | ||
content = []byte(tt.Name) | ||
} | ||
parsed, err := parser.ParseBytes("", content) | ||
a.NoError(err) | ||
|
||
var declarationResults []string | ||
var proxyResults []string | ||
for _, stmt := range parsed.Statements { | ||
if stmt.DeclarationExport != nil { | ||
declarationResults = append(declarationResults, stmt.StaticImport.Path) | ||
} else if stmt.DynamicImport != nil { | ||
proxyResults = append(proxyResults, stmt.DynamicImport.Path) | ||
} | ||
} | ||
a.Equal(tt.ExpectedDeclaration, declarationResults) | ||
a.Equal(tt.ExpectedProxy, proxyResults) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
//nolint:govet | ||
package grammar | ||
|
||
import "github.com/alecthomas/participle/v2/lexer" | ||
|
||
type ImportDeconstruction struct { | ||
Names []string `"{" @Ident ("as" Ident)? ("," (@Ident ("as" Ident)?)?)* "}"` | ||
} | ||
|
||
type AllImport struct { | ||
Alias string `ALL ("as" @Ident)?` | ||
} | ||
|
||
type SelectionImport struct { | ||
AllImport *AllImport `(@@?` | ||
Deconstruction *ImportDeconstruction ` @@?)!` | ||
} | ||
|
||
type Imported struct { | ||
Default bool `(@Ident? ","?` | ||
SelectionImport *SelectionImport ` @@?)!` | ||
} | ||
|
||
type StaticImport struct { | ||
Imported *Imported `"import" (@@ "from")?` | ||
Path string `@String` | ||
} | ||
|
||
type DynamicImport struct { | ||
Path string `"import" "(" @String ")"` | ||
} | ||
|
||
var importLexer = lexer.Rules{ | ||
"Import": { | ||
{"ALL", `\*`, nil}, | ||
{"Punct", `[,{}()]`, nil}, | ||
{"Ident", `[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*`, nil}, | ||
{"String", `'[^']*'|"[^"]*"`, lexer.Pop()}, | ||
{"Comment", `//.*|/\*.*?\*/`, nil}, | ||
{"Whitespace", `\s+`, nil}, | ||
}, | ||
} |
Oops, something went wrong.