Skip to content

Commit

Permalink
Add trailing lookahead restriction to throw expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton committed Jul 17, 2023
1 parent e26e35c commit 472c89f
Show file tree
Hide file tree
Showing 20 changed files with 11,395 additions and 3,876 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
index.html -diff merge=ours
spec.js -diff merge=ours
spec.css -diff merge=ours
18 changes: 18 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Publish Spec to gh-pages
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install --legacy-peer-deps
- run: npm run compile
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: gh-pages
folder: docs
clean-exclude: |
pr
29 changes: 29 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Publish PR to gh-pages/pr/
on:
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
if: ${{ github.event.number }}
steps:
- uses: actions/checkout@v2
- run: npm install --legacy-peer-deps
- run: npm run compile
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: gh-pages
folder: docs
target-folder: pr/${{ github.event.number }}/
- id: get-preview-url
name: Get preview url
run: echo "::set-output name=preview-url::https://tc39.es/$(basename $GITHUB_REPOSITORY)/pr/${{ github.event.number }}"
shell: bash
- name: Post Preview Comment
uses: phulsechinmay/rewritable-pr-comment@v0.3.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMENT_IDENTIFIER: tc39_pr_preview_comment
message: |
A preview of this PR can be found at ${{ steps.get-preview-url.outputs.preview-url }}.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
~$*.pptx
coverage
docs
~$*.pptx
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"recommendations": [
"rbuckton.grammarkdown-language",
"rbuckton.grammarkdown-vscode",
"rbuckton.ecmarkup-vscode"
]
}
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
"[markdown]": {
"files.trimTrailingWhitespace": false
},
"[html]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
},
"[ecmarkup]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
},
"files.associations": {
"*.html": "ecmarkup"
// "*.html": "ecmarkup",
"*.emu": "ecmarkup"
}
}
48 changes: 43 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,52 @@ A `throw` expression *does not* replace a `throw` statement due to the differenc
in the precedence of their values. To maintain the precedence of the `throw` statement,
we must add a lookahead restriction to `ExpressionStatement` to avoid ambiguity.

Due to the difference in precedence between a `throw` expression and a _ThrowStatement_, certain operators to the right
of the expression would parse differently between the two which could cause ambiguity and confusion:

```js
throw a ? b : c; // evaluates 'a' and throws either 'b' or 'c'
(throw a ? b : c); // without restriction would throw 'a', so `?` is forbidden

throw a, b; // evaluates 'a', throws 'b'
(throw a, b); // would throw 'a', not 'b', so `,` is forbidden

throw a && b; // throws 'a' if 'a' is falsy, otherwise throws 'b'
(throw a && b); // would always throw 'a', so `&&` is forbidden

throw a || b; // throws 'a' if 'a' is truthy, otherwise throws 'b'
(throw a || b); // would always throw 'a', so `||` is forbidden

// ... etc.
```

As a result, all binary operators and the `?` operator are forbidden to the right of a `throw` expression. To use these
operators inside of a `throw` expression, the expression must be surrounded with parentheses:

```js
(throw (a, b)); // evaluates 'a', throws 'b'
(throw (a ? b : c)); // evaluates 'a' and throws either 'b' or 'c'
```

However, we do not forbid `:` so that a `throw` expression can still be easily used in a ternary:

```js
const x = a ? throw b : c; // if 'a' then throw 'b', else evaluate 'c'
```

# Grammar

```grammarkdown
UnaryExpression[Yield, Await]:
`throw` UnaryExpression[?Yield, ?Await]
```diff grammarkdown
++ThrowExpressionInvalidPunctuator : one of
`,` `<` `>` `<=` `>=` `==` `!=` `===` `!==` `+` `-` `*` `/` `%` `**` `<<` `>>` `>>>` `&` `|` `^` `&&` `||` `??`
`=` `+=` `-=` `*=` `%=` `**=` `<<=` `>>=` `>>>=` `&=` `|=` `^=` `&&=` `||=` `??=` `?`

UnaryExpression[Yield, Await] :
++ `throw` UnaryExpression[?Yield, ?Await] [lookahead ∉ ThrowExpressionInvalidPunctuator]

ExpressionStatement[Yield, Await]:
[lookahead ∉ {`{`, `function`, `async` [no |LineTerminator| here] `function`, `class`, `let [`, `throw`}] Expression[+In, ?Yield, ?Await] `;`
ExpressionStatement[Yield, Await] :
-- [lookahead ∉ {`{`, `function`, `async` [no |LineTerminator| here] `function`, `class`, `let [`}] Expression[+In, ?Yield, ?Await] `;`
++ [lookahead ∉ {`{`, `function`, `async` [no |LineTerminator| here] `function`, `class`, `let [`, `throw`}] Expression[+In, ?Yield, ?Await] `;`
```

# Other Notes
Expand Down
File renamed without changes.
Loading

0 comments on commit 472c89f

Please sign in to comment.