Add support for AssignStatement in lexical analysis and CST
This commit is contained in:
parent
af996c13fe
commit
1b918dcaf0
3 changed files with 70 additions and 2 deletions
32
src/cst.ts
32
src/cst.ts
|
@ -168,6 +168,7 @@ export const enum SyntaxKind {
|
||||||
ReturnStatement,
|
ReturnStatement,
|
||||||
ExpressionStatement,
|
ExpressionStatement,
|
||||||
IfStatement,
|
IfStatement,
|
||||||
|
AssignStatement,
|
||||||
|
|
||||||
// If statement elements
|
// If statement elements
|
||||||
IfStatementCase,
|
IfStatementCase,
|
||||||
|
@ -2235,6 +2236,36 @@ export class ReturnStatement extends SyntaxBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AssignStatement extends SyntaxBase {
|
||||||
|
|
||||||
|
public readonly kind = SyntaxKind.AssignStatement;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
public pattern: Pattern,
|
||||||
|
public operator: Assignment,
|
||||||
|
public expression: Expression,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clone(): AssignStatement {
|
||||||
|
return new AssignStatement(
|
||||||
|
this.pattern.clone(),
|
||||||
|
this.operator.clone(),
|
||||||
|
this.expression.clone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFirstToken(): Token {
|
||||||
|
return this.pattern.getFirstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLastToken(): Token {
|
||||||
|
return this.expression.getLastToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export class ExpressionStatement extends SyntaxBase {
|
export class ExpressionStatement extends SyntaxBase {
|
||||||
|
|
||||||
public readonly kind = SyntaxKind.ExpressionStatement;
|
public readonly kind = SyntaxKind.ExpressionStatement;
|
||||||
|
@ -2263,6 +2294,7 @@ export type Statement
|
||||||
= ReturnStatement
|
= ReturnStatement
|
||||||
| ExpressionStatement
|
| ExpressionStatement
|
||||||
| IfStatement
|
| IfStatement
|
||||||
|
| AssignStatement
|
||||||
|
|
||||||
export class Param extends SyntaxBase {
|
export class Param extends SyntaxBase {
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ import {
|
||||||
ClassKeyword,
|
ClassKeyword,
|
||||||
InstanceDeclaration,
|
InstanceDeclaration,
|
||||||
ClassConstraintClause,
|
ClassConstraintClause,
|
||||||
|
AssignStatement,
|
||||||
} from "./cst"
|
} from "./cst"
|
||||||
import { Stream } from "./util";
|
import { Stream } from "./util";
|
||||||
|
|
||||||
|
@ -782,6 +783,27 @@ export class Parser {
|
||||||
return new Param(pattern);
|
return new Param(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lookaheadIsAssignment(): boolean {
|
||||||
|
for (let i = 1;; i++) {
|
||||||
|
const t0 = this.peekToken(i);
|
||||||
|
switch (t0.kind) {
|
||||||
|
case SyntaxKind.LineFoldEnd:
|
||||||
|
case SyntaxKind.BlockStart:
|
||||||
|
return false;
|
||||||
|
case SyntaxKind.Assignment:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public parseAssignStatement(): AssignStatement {
|
||||||
|
const pattern = this.parsePattern();
|
||||||
|
const operator = this.expectToken(SyntaxKind.Assignment);
|
||||||
|
const expression = this.parseExpression();
|
||||||
|
this.expectToken(SyntaxKind.LineFoldEnd);
|
||||||
|
return new AssignStatement(pattern, operator, expression);
|
||||||
|
}
|
||||||
|
|
||||||
public parseLetBodyElement(): LetBodyElement {
|
public parseLetBodyElement(): LetBodyElement {
|
||||||
const t0 = this.peekTokenAfterModifiers();
|
const t0 = this.peekTokenAfterModifiers();
|
||||||
switch (t0.kind) {
|
switch (t0.kind) {
|
||||||
|
@ -792,6 +814,9 @@ export class Parser {
|
||||||
case SyntaxKind.IfKeyword:
|
case SyntaxKind.IfKeyword:
|
||||||
return this.parseIfStatement();
|
return this.parseIfStatement();
|
||||||
default:
|
default:
|
||||||
|
if (this.lookaheadIsAssignment()) {
|
||||||
|
return this.parseAssignStatement();
|
||||||
|
}
|
||||||
// TODO convert parse errors to include LetKeyword and ReturnKeyword
|
// TODO convert parse errors to include LetKeyword and ReturnKeyword
|
||||||
return this.parseExpressionStatement();
|
return this.parseExpressionStatement();
|
||||||
}
|
}
|
||||||
|
@ -1165,6 +1190,9 @@ export class Parser {
|
||||||
case SyntaxKind.IfKeyword:
|
case SyntaxKind.IfKeyword:
|
||||||
return this.parseIfStatement();
|
return this.parseIfStatement();
|
||||||
default:
|
default:
|
||||||
|
if (this.lookaheadIsAssignment()) {
|
||||||
|
return this.parseAssignStatement();
|
||||||
|
}
|
||||||
return this.parseExpressionStatement();
|
return this.parseExpressionStatement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,15 @@ export class Scanner extends BufferedStream<Token> {
|
||||||
case '{': return new LBrace(startPos);
|
case '{': return new LBrace(startPos);
|
||||||
case '}': return new RBrace(startPos);
|
case '}': return new RBrace(startPos);
|
||||||
case ',': return new Comma(startPos);
|
case ',': return new Comma(startPos);
|
||||||
case ':': return new Colon(startPos);
|
case ':':
|
||||||
|
const text = this.takeWhile(isOperatorPart);
|
||||||
|
if (text === '') {
|
||||||
|
return new Colon(startPos);
|
||||||
|
} else if (text === '=') {
|
||||||
|
return new Assignment(':', startPos);
|
||||||
|
} else {
|
||||||
|
throw new ScanError(this.file, startPos, ':' + text);
|
||||||
|
}
|
||||||
case '.': {
|
case '.': {
|
||||||
const dots = c0 + this.takeWhile(ch => ch === '.');
|
const dots = c0 + this.takeWhile(ch => ch === '.');
|
||||||
if (dots === '.') {
|
if (dots === '.') {
|
||||||
|
@ -266,7 +274,7 @@ export class Scanner extends BufferedStream<Token> {
|
||||||
} else if (text === '=') {
|
} else if (text === '=') {
|
||||||
return new Equals(startPos);
|
return new Equals(startPos);
|
||||||
} else if (text.endsWith('=') && text[text.length-2] !== '=') {
|
} else if (text.endsWith('=') && text[text.length-2] !== '=') {
|
||||||
return new Assignment(text, startPos);
|
return new Assignment(text.substring(0, text.length-1), startPos);
|
||||||
} else {
|
} else {
|
||||||
return new CustomOperator(text, startPos);
|
return new CustomOperator(text, startPos);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue