Cleanup; Initial switch support; Relooper interface fwiw

This commit is contained in:
dcodeIO
2017-10-11 17:03:22 +02:00
parent 50116acede
commit 6e98c52f76
12 changed files with 646 additions and 383 deletions

View File

@ -23,10 +23,13 @@ import {
AssertionKind,
Expression,
IdentifierExpression,
StringLiteralExpression,
// statements
BlockStatement,
BreakStatement,
ClassDeclaration,
ContinueStatement,
DecoratorStatement,
DoStatement,
EnumDeclaration,
@ -55,7 +58,9 @@ import {
TypeParameter,
VariableStatement,
VariableDeclaration,
WhileStatement
WhileStatement,
hasModifier
} from "./ast";
@ -202,7 +207,7 @@ export class Parser extends DiagnosticEmitter {
finish(): Program {
if (this.backlog.length)
throw new Error("backlog is not empty");
this.backlog = new Array(0);
this.backlog = [];
this.seenlog.clear();
return this.program;
}
@ -536,7 +541,7 @@ export class Parser extends DiagnosticEmitter {
if (!typeParameters)
return null;
} else
typeParameters = new Array(0);
typeParameters = [];
if (!tn.skip(Token.OPENPAREN)) {
this.error(DiagnosticCode._0_expected, tn.range(tn.pos), "(");
return null;
@ -565,7 +570,7 @@ export class Parser extends DiagnosticEmitter {
}
} else if (!isDeclare)
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, tn.range(tn.pos));
const ret: FunctionDeclaration = Statement.createFunction(modifiers, identifier, typeParameters, <Parameter[]>parameters, returnType, statements, decorators ? <DecoratorStatement[]>decorators : new Array(0), tn.range(startPos, tn.pos));
const ret: FunctionDeclaration = Statement.createFunction(modifiers, identifier, typeParameters, <Parameter[]>parameters, returnType, statements, decorators ? <DecoratorStatement[]>decorators : [], tn.range(startPos, tn.pos));
tn.skip(Token.SEMICOLON);
return ret;
}
@ -587,7 +592,7 @@ export class Parser extends DiagnosticEmitter {
if (!typeParameters)
return null;
} else
typeParameters = new Array(0);
typeParameters = [];
let extendsType: TypeNode | null = null;
if (tn.skip(Token.EXTENDS)) {
@ -617,7 +622,7 @@ export class Parser extends DiagnosticEmitter {
members.push(<DeclarationStatement>member);
} while (!tn.skip(Token.CLOSEBRACE));
}
return Statement.createClass(modifiers, identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, decorators ? <DecoratorStatement[]>decorators : new Array(0), tn.range(startPos, tn.pos));
return Statement.createClass(modifiers, identifier, <TypeParameter[]>typeParameters, extendsType, implementsTypes, members, decorators ? <DecoratorStatement[]>decorators : [], tn.range(startPos, tn.pos));
} else
this.error(DiagnosticCode._0_expected, tn.range(), "{");
} else
@ -665,7 +670,7 @@ export class Parser extends DiagnosticEmitter {
if (!typeParameters)
return null;
} else
typeParameters = new Array(0);
typeParameters = [];
// method: '(' Parameters (':' Type)? '{' Statement* '}' ';'?
if (tn.skip(Token.OPENPAREN)) {
@ -746,10 +751,10 @@ export class Parser extends DiagnosticEmitter {
return null;
}
}
let path: string | null = null;
let path: StringLiteralExpression | null = null;
if (tn.skip(Token.FROM)) {
if (tn.skip(Token.STRINGLITERAL))
path = tn.readString();
path = Expression.createStringLiteral(tn.readString(), tn.range());
else {
this.error(DiagnosticCode.String_literal_expected, tn.range());
return null;
@ -805,7 +810,7 @@ export class Parser extends DiagnosticEmitter {
}
if (tn.skip(Token.FROM)) {
if (tn.skip(Token.STRINGLITERAL)) {
const path: string = tn.readString();
const path: StringLiteralExpression = Expression.createStringLiteral(tn.readString(), tn.range());
const ret: ImportStatement = Statement.createImport(members, path, Range.join(startRange, tn.range()));
if (!this.seenlog.has(ret.normalizedPath)) {
this.backlog.push(ret.normalizedPath);
@ -866,9 +871,15 @@ export class Parser extends DiagnosticEmitter {
const token: Token = tn.next();
switch (token) {
case Token.BREAK:
return this.parseBreak(tn);
case Token.CONST:
return this.parseVariable(tn, [ Statement.createModifier(ModifierKind.CONST, tn.range()) ]);
case Token.CONTINUE:
return this.parseContinue(tn);
case Token.DO:
return this.parseDoStatement(tn);
@ -926,6 +937,30 @@ export class Parser extends DiagnosticEmitter {
return ret;
}
parseBreak(tn: Tokenizer): BreakStatement | null {
// at 'break': Identifier? ';'?
let identifier: IdentifierExpression | null = null;
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
tn.next(true);
identifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
}
const ret: ContinueStatement = Statement.createBreak(identifier, tn.range());
tn.skip(Token.SEMICOLON);
return ret;
}
parseContinue(tn: Tokenizer): ContinueStatement | null {
// at 'continue': Identifier? ';'?
let identifier: IdentifierExpression | null = null;
if (tn.peek(true) == Token.IDENTIFIER && !tn.nextTokenOnNewLine) {
tn.next(true);
identifier = Expression.createIdentifier(tn.readIdentifier(), tn.range());
}
const ret: ContinueStatement = Statement.createContinue(identifier, tn.range());
tn.skip(Token.SEMICOLON);
return ret;
}
parseDoStatement(tn: Tokenizer): DoStatement | null {
// at 'do': Statement 'while' '(' Expression ')' ';'?
const startPos: i32 = tn.tokenPos;
@ -1027,7 +1062,7 @@ export class Parser extends DiagnosticEmitter {
return null;
if (tn.skip(Token.CLOSEPAREN)) {
if (tn.skip(Token.OPENBRACE)) {
const cases: SwitchCase[] = new Array(0);
const cases: SwitchCase[] = [];
while (!tn.skip(Token.CLOSEBRACE)) {
const case_: SwitchCase | null = this.parseSwitchCase(tn);
if (!case_)
@ -1232,8 +1267,9 @@ export class Parser extends DiagnosticEmitter {
}
// UnaryPrefixExpression
if ((<Expression>operand).kind != NodeKind.IDENTIFIER && (<Expression>operand).kind != NodeKind.ELEMENTACCESS && (<Expression>operand).kind != NodeKind.PROPERTYACCESS)
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, (<Expression>operand).range);
if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS)
if ((<Expression>operand).kind != NodeKind.IDENTIFIER && (<Expression>operand).kind != NodeKind.ELEMENTACCESS && (<Expression>operand).kind != NodeKind.PROPERTYACCESS)
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, (<Expression>operand).range);
return Expression.createUnaryPrefix(token, <Expression>operand, tn.range(startPos, tn.pos));
}
@ -1315,20 +1351,20 @@ export class Parser extends DiagnosticEmitter {
}
}
tryParseTypeArgumentsBeforeArguments(tn: Tokenizer): IdentifierExpression[] | null {
tryParseTypeArgumentsBeforeArguments(tn: Tokenizer): TypeNode[] | null {
// at '<': Identifier (',' Identifier)* '>' '('
tn.mark();
if (!tn.skip(Token.LESSTHAN))
return null;
const typeArguments: IdentifierExpression[] = new Array();
const typeArguments: TypeNode[] = [];
do {
const token: Token = tn.next();
if (token != Token.IDENTIFIER) {
const type: TypeNode | null = this.parseType(tn);
if (!type) {
tn.reset();
return null;
}
typeArguments.push(Expression.createIdentifier(tn.readIdentifier(), tn.range()));
typeArguments.push(type);
} while (tn.skip(Token.COMMA));
if (!(tn.skip(Token.GREATERTHAN) && tn.skip(Token.OPENPAREN))) {
tn.reset();
@ -1360,16 +1396,16 @@ export class Parser extends DiagnosticEmitter {
if (!expr)
return null;
const startPos: i32 = expr.range.start;
const startPos: i32 = expr.range.start;
// CallExpression
const typeArguments: IdentifierExpression[] | null = this.tryParseTypeArgumentsBeforeArguments(tn);
// there might be better ways to distinguish a LESSTHAN from a CALL
const typeArguments: TypeNode[] | null = this.tryParseTypeArgumentsBeforeArguments(tn);
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
if (typeArguments || tn.skip(Token.OPENPAREN)) {
const args: Expression[] | null = this.parseArguments(tn);
if (!args)
return null;
expr = Expression.createCall(expr, typeArguments ? <IdentifierExpression[]>typeArguments : new Array(0), args, tn.range(startPos, tn.pos));
expr = Expression.createCall(expr, <TypeNode[]>(typeArguments ? typeArguments : []), args, tn.range(startPos, tn.pos));
}
let token: Token;
@ -1625,14 +1661,6 @@ function addModifier(modifier: Modifier, modifiers: Modifier[] | null): Modifier
return modifiers;
}
export function hasModifier(kind: ModifierKind, modifiers: Modifier[] | null): bool {
if (modifiers != null)
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i)
if (modifiers[i].modifierKind == kind)
return true;
return false;
}
function getModifier(kind: ModifierKind, modifiers: Modifier[]): Modifier {
for (let i: i32 = 0, k: i32 = modifiers.length; i < k; ++i)
if (modifiers[i].modifierKind == kind)