diff --git a/src/parser.ts b/src/parser.ts index 55ca4982..47d5aab9 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -18,7 +18,8 @@ import { Token, Range, CommentHandler, - IdentifierHandling + IdentifierHandling, + isIllegalVariableIdentifier } from "./tokenizer"; import { @@ -815,6 +816,12 @@ export class Parser extends DiagnosticEmitter { return null; } var identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range()); + if (isIllegalVariableIdentifier(identifier.text)) { + this.error( + DiagnosticCode.Identifier_expected, + identifier.range + ); + } var flags = parentFlags; if (tn.skip(Token.EXCLAMATION)) { flags |= CommonFlags.DEFINITE_ASSIGNMENT; @@ -1780,10 +1787,17 @@ export class Parser extends DiagnosticEmitter { var readonlyStart: i32 = 0; var readonlyEnd: i32 = 0; - if (tn.skip(Token.READONLY)) { - flags |= CommonFlags.READONLY; - readonlyStart = tn.tokenPos; - readonlyEnd = tn.pos; + if (tn.peek() == Token.READONLY) { + let state = tn.mark(); + tn.next(); + if (tn.peek() != Token.COLON) { // modifier + tn.discard(state); + flags |= CommonFlags.READONLY; + readonlyStart = tn.tokenPos; + readonlyEnd = tn.pos; + } else { // identifier + tn.reset(state); + } } // check if accessor: ('get' | 'set') ^\n Identifier @@ -3426,7 +3440,9 @@ export class Parser extends DiagnosticEmitter { ); } case Token.IDENTIFIER: { - let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range(startPos, tn.pos)); + let identifierText = tn.readIdentifier(); + if (identifierText == "null") return Node.createNullExpression(tn.range()); // special + let identifier = Node.createIdentifierExpression(identifierText, tn.range(startPos, tn.pos)); if (tn.peek(true) == Token.EQUALS_GREATERTHAN && !tn.nextTokenOnNewLine) { return this.parseFunctionExpressionCommon( tn, diff --git a/src/tokenizer.ts b/src/tokenizer.ts index d9c38b82..e55acd1e 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -355,6 +355,7 @@ export function tokenIsAlsoIdentifier(token: Token): bool { case Token.KEYOF: case Token.MODULE: case Token.NAMESPACE: + case Token.NULL: case Token.READONLY: case Token.SET: case Token.TYPE: @@ -363,6 +364,18 @@ export function tokenIsAlsoIdentifier(token: Token): bool { } } +export function isIllegalVariableIdentifier(name: string): bool { + assert(name.length); + switch (name.charCodeAt(0)) { + case CharCode.d: return name == "delete"; + case CharCode.f: return name == "for"; + case CharCode.i: return name == "instanceof"; + case CharCode.n: return name == "null"; + case CharCode.v: return name == "void"; + } + return false; +} + export function operatorTokenToString(token: Token): string { switch (token) { case Token.DELETE: return "delete"; diff --git a/tests/compiler/call-super.untouched.wat b/tests/compiler/call-super.untouched.wat index d0365d64..866c9146 100644 --- a/tests/compiler/call-super.untouched.wat +++ b/tests/compiler/call-super.untouched.wat @@ -338,8 +338,6 @@ local.get $0 ) (func $call-super/F#constructor (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) local.get $0 i32.eqz if @@ -351,16 +349,11 @@ end local.get $0 call $call-super/E#constructor - local.tee $1 local.set $0 local.get $0 i32.const 2 i32.store offset=4 local.get $0 - local.set $2 - local.get $1 - call $~lib/rt/stub/__release - local.get $2 ) (func $call-super/test3 (; 12 ;) (type $FUNCSIG$v) (local $0 i32) @@ -412,8 +405,6 @@ local.get $0 ) (func $call-super/H#constructor (; 14 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) local.get $0 i32.eqz if @@ -425,16 +416,11 @@ end local.get $0 call $call-super/G#constructor - local.tee $1 local.set $0 local.get $0 i32.const 2 i32.store offset=4 local.get $0 - local.set $2 - local.get $1 - call $~lib/rt/stub/__release - local.get $2 ) (func $call-super/test4 (; 15 ;) (type $FUNCSIG$v) (local $0 i32) @@ -486,8 +472,6 @@ local.get $0 ) (func $call-super/J#constructor (; 17 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) local.get $0 i32.eqz if @@ -499,16 +483,11 @@ end local.get $0 call $call-super/I#constructor - local.tee $1 local.set $0 local.get $0 i32.const 2 i32.store offset=4 local.get $0 - local.set $2 - local.get $1 - call $~lib/rt/stub/__release - local.get $2 ) (func $call-super/test5 (; 18 ;) (type $FUNCSIG$v) (local $0 i32) diff --git a/tests/compiler/rt/instanceof.untouched.wat b/tests/compiler/rt/instanceof.untouched.wat index acaa8057..7816af7b 100644 --- a/tests/compiler/rt/instanceof.untouched.wat +++ b/tests/compiler/rt/instanceof.untouched.wat @@ -1,7 +1,6 @@ (module (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$v (func)) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) @@ -133,12 +132,7 @@ end local.get $0 ) - (func $~lib/rt/stub/__release (; 4 ;) (type $FUNCSIG$vi) (param $0 i32) - nop - ) - (func $rt/instanceof/Cat#constructor (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) + (func $rt/instanceof/Cat#constructor (; 4 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -150,17 +144,10 @@ end local.get $0 call $rt/instanceof/Animal#constructor - local.tee $1 local.set $0 local.get $0 - local.set $2 - local.get $1 - call $~lib/rt/stub/__release - local.get $2 ) - (func $rt/instanceof/BlackCat#constructor (; 6 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) + (func $rt/instanceof/BlackCat#constructor (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -172,15 +159,10 @@ end local.get $0 call $rt/instanceof/Cat#constructor - local.tee $1 local.set $0 local.get $0 - local.set $2 - local.get $1 - call $~lib/rt/stub/__release - local.get $2 ) - (func $~lib/rt/__instanceof (; 7 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/__instanceof (; 6 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) local.get $0 @@ -217,7 +199,7 @@ end i32.const 0 ) - (func $start:rt/instanceof (; 8 ;) (type $FUNCSIG$v) + (func $start:rt/instanceof (; 7 ;) (type $FUNCSIG$v) (local $0 i32) global.get $~lib/heap/__heap_base i32.const 15 @@ -713,7 +695,7 @@ unreachable end ) - (func $start (; 9 ;) (type $FUNCSIG$v) + (func $start (; 8 ;) (type $FUNCSIG$v) global.get $~lib/started if return @@ -723,6 +705,6 @@ end call $start:rt/instanceof ) - (func $null (; 10 ;) (type $FUNCSIG$v) + (func $null (; 9 ;) (type $FUNCSIG$v) ) ) diff --git a/tests/parser/also-identifier.ts b/tests/parser/also-identifier.ts new file mode 100644 index 00000000..39b5477b --- /dev/null +++ b/tests/parser/also-identifier.ts @@ -0,0 +1,38 @@ +class Foo { + as: i32; + declare: i32; + delete: i32; + from: i32; + for: i32; + get: i32; + instanceof: i32; + is: i32; + keyof: i32; + module: i32; + namespace: i32; + null: i32; + readonly: i32; + set: i32; + type: i32; + void: i32; +} + +var as: i32; +var constructor: i32; +var declare: i32; +var from: i32; +var get: i32; +var is: i32; +var keyof: i32; +var module: i32; +var namespace: i32; +var readonly: i32; +var set: i32; + +// -- illegal -- +// var delete: i32; +// var for: i32; +// var instanceof: i32; +// var null: i32; +// var type: i32; +// var void: i32; diff --git a/tests/parser/also-identifier.ts.fixture.ts b/tests/parser/also-identifier.ts.fixture.ts new file mode 100644 index 00000000..8de8b517 --- /dev/null +++ b/tests/parser/also-identifier.ts.fixture.ts @@ -0,0 +1,29 @@ +class Foo { + as: i32; + declare: i32; + delete: i32; + from: i32; + for: i32; + get: i32; + instanceof: i32; + is: i32; + keyof: i32; + module: i32; + namespace: i32; + null: i32; + readonly: i32; + set: i32; + type: i32; + void: i32; +} +var as: i32; +var constructor: i32; +var declare: i32; +var from: i32; +var get: i32; +var is: i32; +var keyof: i32; +var module: i32; +var namespace: i32; +var readonly: i32; +var set: i32;