# Copyright 2017 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Elementary building blocks:

# Empty
" "

# Tokens
"("
")"
"["
"]"
"{"
"}"
":"
";"
"."
"..."
"?"
"++"
"--"
"=>"
"!"
"="
"|="
"^="
"&="
"<<="
">>="
">>>="
"+="
"-="
"*="
"/="
"%="
"**="
","
"||"
"&&"
"|"
"^"
"&"
"<<"
">>"
">>>"
"+"
"-"
"*"
"/"
"%"
"**"
"=="
"!="
"==="
"!=="
"<"
">"
"<="
">="
"!"
"~"
"#"
".#"

# Keywords, contextual keywords, literals, reserved words.
"__proto__"
"anonymous"
"arguments"
"as"
"async"
"await"
"break"
"case"
"catch"
"class"
"const"
"constructor"
"continue"
"debugger"
"default"
"delete"
"do"
"else"
"enum"
"eval"
"export"
"extends"
"false"
"finally"
"for"
"from"
"function"
"get"
"if"
"import"
"in"
"instanceof"
"let"
"name"
"new"
"null"
"of"
"prototype"
"return"
"sent"
"set"
"static"
"super"
"switch"
"target"
"this"
"throw"
"true"
"try"
"typeof"
"undefined"
"var"
"void"
"while"
"with"

# TODO(marja): Add names of known classes.

# Separators
"\n"
"; "
$0 "\n"
$0 "; "

$0 "," $1
"(" $0 ")"

# Identifiers
"foo"
"bar"
"a"
"b"
"c"

# Other literals
"0"
"0.0"

# TODO(marja): Add strings and numbers! And quotes.

# Other meaningful words from the spec
"new.target"

# More complicated building blocks

# Block, object, or binding pattern
"{" $0 "}"
"{" $0 ": " $1 "}"

# Array or array binding pattern
"[" $0 "]"

# Rest element or rest parameter
"..."
"..." $0

# Variable declarations
"let" $0 "=" $1 ";"
"const " $0 "=" $1 ";"
"var" $0 "=" $1 ";"

# Return statements
"return" $0
"return" $0 ";"

# If statements
"if (" $0 ")" $1
"if (" $0 ") {" $1 "}"
"if (" $0 ") {" $1 "} else {" $2 "}"
"if (" $0 ")" $1 "else" $2

# Iteration statements
"do" $0 "while (" $1 ");"
"for (" $0 ")" $1
"for (" $0 ") {" $1 " }"
"for (" $0 "in" $1 ")" $2
"for (" $0 "in" $1 ") {" $2 "}"
"for (" $0 "of" $1 ")" $2
"for (" $0 "of" $1 ") {" $2 "}"
"for (" $0 ";" $1 ";" $2 ")" $3
"for (" $0 ";" $1 ";" $2 ") {" $3 "}"
"for await (" $0 ")" $1
"for await (" $0 ") {" $1 " }"
"for await (" $0 "in" $1 ")" $2
"for await (" $0 "in" $1 ") {" $2 "}"
"for await (" $0 "of" $1 ")" $2
"for await (" $0 "of" $1 ") {" $2 "}"
"for await (" $0 ";" $1 ";" $2 ")" $3
"for await (" $0 ";" $1 ";" $2 ") {" $3 "}"
"while (" $0 ")" $1
"while (" $0 ") {" $1 "}"
"continue"
"continue;"
"continue" $0
"break"
"break;"
"break" $0

# With statements
"with (" $0 ")" $1
"with (" $0 ") {" $1 "}"

# Switch statements
"switch (" $0 ")" $1
"switch (" $0 ") {" $1 "}"
"case" $0 ": " $1
"case" $0 ": {" $1 "}"
"default :" $0

# Try-catch statements
"try" $0 "catch (" $1 ")" $2
"try {" $0 "} catch (" $1 ") {" $2 "}"
"try" $0 "finally (" $1 ")" $2
"try {" $0 "} finally (" $1 ") {" $2 "}"
"try" $0 "catch (" $1 ")" $2 "finally" $3
"try {" $0 "} catch (" $1 ") {" $2 "} finally {" $3 "}"

# Functions and arrow functions
"function" $0 "(" $1 ") {" $2 "}"
"function" "(" $0 ") {" $1 "}"
$0 "=>" $1
$0 "=> {" $1 "}"
"(" $0 ") => {" $1 "}"
"(" $0 ") =>" $1

# Strict functions and arrow functions
"function" $0 "(" $1 ") { 'use strict';" $2 "}"
"function" "(" $0 ") { 'use strict';" $1 "}"
$0 "=> { 'use strict';" $1 "}"
"(" $0 ") => { 'use strict'; " $1 "}"

# Methods
$0 "(" $1 ") {" $1 "}"
"get" $0 "(" $1 ") {" $1 "}"
"set" $0 "(" $1 ") {" $1 "}"
"static" $0 "(" $1 ") {" $1 "}"
"static get" $0 "(" $1 ") {" $1 "}"
"static set" $0 "(" $1 ") {" $1 "}"

# Generators
"*" $0 "(" $1 ") {" $2 "}"
"function *" $0 "(" $1 ") {" $2 "}"
"function * (" $1 ") {" $2 "}"
"yield" $0
"yield *" $0

# Strict generators
"function *" $0 "(" $1 ") {'use strict'; " $2 "}"
"function * (" $1 ") { 'use strict'; " $2 "}"

# Classes
"class" $0 "{" $1 "}"
"class" $0 "extends" $1 "{" $2 "}"

# Async functions, async methods, async arrow functions
"async function" $0 "(" $1 ") {" $2 "}"
"async function" "(" $0 ") {" $1 "}"
"async" $0 "(" $1 ") {" $2 "}"
"async" $0 "=>" $1
"async" $0 "=> {" $1 "}"
"async(" $0 ") => {" $1 "}"
"async(" $0 ") =>" $1
"await" $0

# Strict async functions.
"async function" $0 "(" $1 ") { 'use strict'; " $2 "}"
"async function" "(" $0 ") { 'use strict'; " $1 "}"
"async" $0 "(" $1 ") { 'use strict'; " $2 "}"
"async" $0 "=> { 'use strict'; " $1 "}"
"async(" $0 ") => { 'use strict';" $1 "}"

# Call expressions
$0 "[" $1 "]"
$0 "(" $1 ")"

# Template literals
"`foo`"
$0 "`foo`"
# TODO(marja): add more

# Strict directive
"'use strict';"

# Regexps
"/foo/"
# TODO(marja): add more

# Conditional expression
$0 "?" $1 ":" $2
$0 "?" $1 ":" $2 ";"

# Assignment expressions
$0 "=" $1
$0 "=" $1 ";"

# Import / export (for modules)
"import" $0 ";"
"export" $0 ";"

# Misc.
"eval('');"

