mirror of
https://github.com/jasonwilliams/vscode-helix.git
synced 2024-09-19 04:37:39 +03:00
Remove namespace
I don't think namespaces are technically deprecated, but they're an unnecessary typescript-only feature that we're using in exactly one place, so let's stop.
This commit is contained in:
parent
bb56b499fa
commit
9487360e59
@ -8,7 +8,7 @@ export function lex(input: string): Token[] {
|
||||
// We use a character scanner as state for the lexer.
|
||||
const state = new Scanner(input);
|
||||
const tokens: Token[] = [];
|
||||
let f: ILexFunction | null = LexerFunctions.lexRange;
|
||||
let f: ILexFunction | null = lexRange;
|
||||
while (f) {
|
||||
// Each lexing function returns the next lexing function or null.
|
||||
f = f(state, tokens);
|
||||
@ -22,213 +22,211 @@ function emitToken(type: TokenType, state: Scanner): Token | null {
|
||||
return content.length > 0 ? new Token(type, content) : null;
|
||||
}
|
||||
|
||||
namespace LexerFunctions {
|
||||
// Starts lexing a Vim command line and delegates on other lexer functions as needed.
|
||||
export function lexRange(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
break;
|
||||
}
|
||||
const c = state.next();
|
||||
switch (c) {
|
||||
case ',':
|
||||
case ';':
|
||||
tokens.push(emitToken(TokenType.Comma, state)!);
|
||||
continue;
|
||||
case '%':
|
||||
tokens.push(emitToken(TokenType.Percent, state)!);
|
||||
continue;
|
||||
case '$':
|
||||
tokens.push(emitToken(TokenType.Dollar, state)!);
|
||||
continue;
|
||||
case '.':
|
||||
tokens.push(emitToken(TokenType.Dot, state)!);
|
||||
continue;
|
||||
case '/':
|
||||
return lexForwardSearch;
|
||||
case '?':
|
||||
return lexReverseSearch;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (tokens.length < 1) {
|
||||
// special case - first digitey token is always a line number
|
||||
return lexDigits(TokenType.LineNumber);
|
||||
} else {
|
||||
// otherwise, use previous token to determine which flavor of digit lexer should be used
|
||||
const previousTokenType = tokens[tokens.length - 1].type;
|
||||
if (previousTokenType === TokenType.Plus || previousTokenType === TokenType.Minus) {
|
||||
return lexDigits(TokenType.Offset);
|
||||
} else {
|
||||
return lexDigits(TokenType.LineNumber);
|
||||
}
|
||||
}
|
||||
case '+':
|
||||
tokens.push(emitToken(TokenType.Plus, state)!);
|
||||
continue;
|
||||
case '-':
|
||||
tokens.push(emitToken(TokenType.Minus, state)!);
|
||||
continue;
|
||||
case '*':
|
||||
state.ignore();
|
||||
tokens.push(new Token(TokenType.SelectionFirstLine, '<'));
|
||||
tokens.push(new Token(TokenType.Comma, ','));
|
||||
tokens.push(new Token(TokenType.SelectionLastLine, '>'));
|
||||
continue;
|
||||
case "'":
|
||||
return lexMark;
|
||||
case '!':
|
||||
tokens.push(emitToken(TokenType.CommandName, state)!);
|
||||
return lexCommandArgs;
|
||||
case ' ':
|
||||
state.ignore();
|
||||
continue;
|
||||
default:
|
||||
return lexCommand;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexMark(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
// The first token has already been lexed.
|
||||
// Starts lexing a Vim command line and delegates on other lexer functions as needed.
|
||||
function lexRange(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
return null;
|
||||
break;
|
||||
}
|
||||
|
||||
const c = state.next();
|
||||
switch (c) {
|
||||
case '<':
|
||||
tokens.push(emitToken(TokenType.SelectionFirstLine, state)!);
|
||||
break;
|
||||
case '>':
|
||||
tokens.push(emitToken(TokenType.SelectionLastLine, state)!);
|
||||
break;
|
||||
default:
|
||||
if (/[a-zA-Z]/.test(c)) {
|
||||
state.emit();
|
||||
tokens.push(new Token(TokenType.Mark, c));
|
||||
} else {
|
||||
state.backup();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return lexRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* when we're lexing digits, it could either be a line number or an offset, depending on whether
|
||||
* our previous token was a + or a -
|
||||
*
|
||||
* so it's lexRange's job to specify which token to emit.
|
||||
*/
|
||||
function lexDigits(tokenType: TokenType) {
|
||||
return (state: Scanner, tokens: Token[]): ILexFunction | null => {
|
||||
// The first digit has already been lexed.
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
tokens.push(emitToken(tokenType, state)!);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!/[0-9]/.test(state.next())) {
|
||||
state.backup();
|
||||
tokens.push(emitToken(tokenType, state)!);
|
||||
return lexRange;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function lexCommand(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
// The first character of the command's name has already been lexed.
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
tokens.push(emitToken(TokenType.CommandName, state)!);
|
||||
break;
|
||||
}
|
||||
const c = state.next().toLowerCase();
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
case ',':
|
||||
case ';':
|
||||
tokens.push(emitToken(TokenType.Comma, state)!);
|
||||
continue;
|
||||
} else {
|
||||
state.backup();
|
||||
case '%':
|
||||
tokens.push(emitToken(TokenType.Percent, state)!);
|
||||
continue;
|
||||
case '$':
|
||||
tokens.push(emitToken(TokenType.Dollar, state)!);
|
||||
continue;
|
||||
case '.':
|
||||
tokens.push(emitToken(TokenType.Dot, state)!);
|
||||
continue;
|
||||
case '/':
|
||||
return lexForwardSearch;
|
||||
case '?':
|
||||
return lexReverseSearch;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (tokens.length < 1) {
|
||||
// special case - first digitey token is always a line number
|
||||
return lexDigits(TokenType.LineNumber);
|
||||
} else {
|
||||
// otherwise, use previous token to determine which flavor of digit lexer should be used
|
||||
const previousTokenType = tokens[tokens.length - 1].type;
|
||||
if (previousTokenType === TokenType.Plus || previousTokenType === TokenType.Minus) {
|
||||
return lexDigits(TokenType.Offset);
|
||||
} else {
|
||||
return lexDigits(TokenType.LineNumber);
|
||||
}
|
||||
}
|
||||
case '+':
|
||||
tokens.push(emitToken(TokenType.Plus, state)!);
|
||||
continue;
|
||||
case '-':
|
||||
tokens.push(emitToken(TokenType.Minus, state)!);
|
||||
continue;
|
||||
case '*':
|
||||
state.ignore();
|
||||
tokens.push(new Token(TokenType.SelectionFirstLine, '<'));
|
||||
tokens.push(new Token(TokenType.Comma, ','));
|
||||
tokens.push(new Token(TokenType.SelectionLastLine, '>'));
|
||||
continue;
|
||||
case "'":
|
||||
return lexMark;
|
||||
case '!':
|
||||
tokens.push(emitToken(TokenType.CommandName, state)!);
|
||||
return lexCommandArgs;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexCommandArgs(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
while (!state.isAtEof) {
|
||||
state.next();
|
||||
}
|
||||
// TODO(guillermooo): We need to parse multiple commands.
|
||||
const args = emitToken(TokenType.CommandArgs, state);
|
||||
if (args) {
|
||||
tokens.push(args);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexForwardSearch(state: Scanner, tokens: Token[]): ILexFunction {
|
||||
// The first slash has already been lexed.
|
||||
state.skip('/'); // XXX: really?
|
||||
let escaping = false;
|
||||
let searchTerm = '';
|
||||
while (!state.isAtEof) {
|
||||
const c = state.next();
|
||||
if (c === '/' && !escaping) {
|
||||
break;
|
||||
}
|
||||
if (c === '\\') {
|
||||
escaping = true;
|
||||
case ' ':
|
||||
state.ignore();
|
||||
continue;
|
||||
} else {
|
||||
escaping = false;
|
||||
}
|
||||
searchTerm += c !== '\\' ? c : '\\\\';
|
||||
default:
|
||||
return lexCommand;
|
||||
}
|
||||
tokens.push(new Token(TokenType.ForwardSearch, searchTerm));
|
||||
state.ignore();
|
||||
if (!state.isAtEof) {
|
||||
state.skip('/');
|
||||
}
|
||||
return lexRange;
|
||||
}
|
||||
|
||||
function lexReverseSearch(state: Scanner, tokens: Token[]): ILexFunction {
|
||||
// The first question mark has already been lexed.
|
||||
state.skip('?'); // XXX: really?
|
||||
let escaping = false;
|
||||
let searchTerm = '';
|
||||
while (!state.isAtEof) {
|
||||
const c = state.next();
|
||||
if (c === '?' && !escaping) {
|
||||
break;
|
||||
}
|
||||
if (c === '\\') {
|
||||
escaping = true;
|
||||
continue;
|
||||
} else {
|
||||
escaping = false;
|
||||
}
|
||||
searchTerm += c !== '\\' ? c : '\\\\';
|
||||
}
|
||||
tokens.push(new Token(TokenType.ReverseSearch, searchTerm));
|
||||
state.ignore();
|
||||
if (!state.isAtEof) {
|
||||
state.skip('?');
|
||||
}
|
||||
return lexRange;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexMark(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
// The first token has already been lexed.
|
||||
if (state.isAtEof) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const c = state.next();
|
||||
switch (c) {
|
||||
case '<':
|
||||
tokens.push(emitToken(TokenType.SelectionFirstLine, state)!);
|
||||
break;
|
||||
case '>':
|
||||
tokens.push(emitToken(TokenType.SelectionLastLine, state)!);
|
||||
break;
|
||||
default:
|
||||
if (/[a-zA-Z]/.test(c)) {
|
||||
state.emit();
|
||||
tokens.push(new Token(TokenType.Mark, c));
|
||||
} else {
|
||||
state.backup();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return lexRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* when we're lexing digits, it could either be a line number or an offset, depending on whether
|
||||
* our previous token was a + or a -
|
||||
*
|
||||
* so it's lexRange's job to specify which token to emit.
|
||||
*/
|
||||
function lexDigits(tokenType: TokenType) {
|
||||
return (state: Scanner, tokens: Token[]): ILexFunction | null => {
|
||||
// The first digit has already been lexed.
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
tokens.push(emitToken(tokenType, state)!);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!/[0-9]/.test(state.next())) {
|
||||
state.backup();
|
||||
tokens.push(emitToken(tokenType, state)!);
|
||||
return lexRange;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function lexCommand(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
// The first character of the command's name has already been lexed.
|
||||
while (true) {
|
||||
if (state.isAtEof) {
|
||||
tokens.push(emitToken(TokenType.CommandName, state)!);
|
||||
break;
|
||||
}
|
||||
const c = state.next().toLowerCase();
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
continue;
|
||||
} else {
|
||||
state.backup();
|
||||
tokens.push(emitToken(TokenType.CommandName, state)!);
|
||||
return lexCommandArgs;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexCommandArgs(state: Scanner, tokens: Token[]): ILexFunction | null {
|
||||
while (!state.isAtEof) {
|
||||
state.next();
|
||||
}
|
||||
// TODO(guillermooo): We need to parse multiple commands.
|
||||
const args = emitToken(TokenType.CommandArgs, state);
|
||||
if (args) {
|
||||
tokens.push(args);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function lexForwardSearch(state: Scanner, tokens: Token[]): ILexFunction {
|
||||
// The first slash has already been lexed.
|
||||
state.skip('/'); // XXX: really?
|
||||
let escaping = false;
|
||||
let searchTerm = '';
|
||||
while (!state.isAtEof) {
|
||||
const c = state.next();
|
||||
if (c === '/' && !escaping) {
|
||||
break;
|
||||
}
|
||||
if (c === '\\') {
|
||||
escaping = true;
|
||||
continue;
|
||||
} else {
|
||||
escaping = false;
|
||||
}
|
||||
searchTerm += c !== '\\' ? c : '\\\\';
|
||||
}
|
||||
tokens.push(new Token(TokenType.ForwardSearch, searchTerm));
|
||||
state.ignore();
|
||||
if (!state.isAtEof) {
|
||||
state.skip('/');
|
||||
}
|
||||
return lexRange;
|
||||
}
|
||||
|
||||
function lexReverseSearch(state: Scanner, tokens: Token[]): ILexFunction {
|
||||
// The first question mark has already been lexed.
|
||||
state.skip('?'); // XXX: really?
|
||||
let escaping = false;
|
||||
let searchTerm = '';
|
||||
while (!state.isAtEof) {
|
||||
const c = state.next();
|
||||
if (c === '?' && !escaping) {
|
||||
break;
|
||||
}
|
||||
if (c === '\\') {
|
||||
escaping = true;
|
||||
continue;
|
||||
} else {
|
||||
escaping = false;
|
||||
}
|
||||
searchTerm += c !== '\\' ? c : '\\\\';
|
||||
}
|
||||
tokens.push(new Token(TokenType.ReverseSearch, searchTerm));
|
||||
state.ignore();
|
||||
if (!state.isAtEof) {
|
||||
state.skip('?');
|
||||
}
|
||||
return lexRange;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
"max-classes-per-file": false,
|
||||
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
|
||||
"no-duplicate-variable": true,
|
||||
"no-namespace": false,
|
||||
"no-parameter-properties": true,
|
||||
"no-return-await": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
|
Loading…
Reference in New Issue
Block a user