65 lines
2.8 KiB
TypeScript
65 lines
2.8 KiB
TypeScript
function makeSticky( re: RegExp ): RegExp
|
|
{
|
|
if ( re.sticky ) return re;
|
|
const flags = re.flags.includes( 'y' ) ? re.flags : re.flags + 'y';
|
|
return new RegExp( re.source, flags );
|
|
}
|
|
|
|
export class BrowserMatcher
|
|
{
|
|
readonly type: string;
|
|
private _re: RegExp;
|
|
|
|
constructor( type: string, re: RegExp )
|
|
{
|
|
this.type = type;
|
|
this._re = makeSticky( re );
|
|
}
|
|
|
|
matchLength( source: string, offset: number ): number
|
|
{
|
|
this._re.lastIndex = offset;
|
|
const result = this._re.exec( source );
|
|
if ( result && result.index === offset ) return result[ 0 ].length;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
export class BrowserLexer
|
|
{
|
|
readonly modes = new Map<string, BrowserMatcher[]>();
|
|
|
|
addMatchers( ...matchers: BrowserMatcher[] ): void
|
|
{
|
|
const list = this.modes.get( 'default' ) ?? [];
|
|
list.push( ...matchers );
|
|
this.modes.set( 'default', list );
|
|
}
|
|
}
|
|
|
|
export function cLikeLexer(): BrowserLexer
|
|
{
|
|
const l = new BrowserLexer();
|
|
l.addMatchers(
|
|
new BrowserMatcher( 'SINGLE_LINE_COMMENT', /\/\/.*/ ),
|
|
new BrowserMatcher( 'MULTI_LINE_COMMENT', /\/\*[\s\S]*?\*\// ),
|
|
new BrowserMatcher( 'DOUBLE_QUOTED_STRING', /"(?:[^"\\]|\\.)*"/ ),
|
|
new BrowserMatcher( 'SINGLE_QUOTED_STRING', /'(?:[^'\\]|\\.)*'/ ),
|
|
new BrowserMatcher( 'C_INSTRUCTION', /\#.*/ ),
|
|
new BrowserMatcher( 'NUMBER', /(?=\.\d|\d)(?:\d+)?(?:\.?\d*)(?:[eE][+-]?\d+)?/ ),
|
|
new BrowserMatcher( 'NULL', /\bnull\b/ ),
|
|
new BrowserMatcher( 'BOOL', /\b(?:true|false)\b/ ),
|
|
new BrowserMatcher( 'BREAK', /\r\n|\r|\n/ ),
|
|
new BrowserMatcher( 'WHITESPACE', /\s+/ ),
|
|
new BrowserMatcher( 'LOGIC', /\b(?:if|else|switch|do|while|for|break|continue|return|case)\b/ ),
|
|
new BrowserMatcher( 'BRACKET', /[()[\]{}]/ ),
|
|
new BrowserMatcher( 'ACCESS_MODIFIER', /\b(?:public|protected|private)\b/ ),
|
|
new BrowserMatcher( 'CLASS', /\bclass\b/ ),
|
|
new BrowserMatcher( 'OPERATOR', /==|\+\+|--|[+\-*\/^|~&%<>=!.:,;]/ ),
|
|
new BrowserMatcher( 'CFUNCTION', /[a-zA-Z_]\w*(?=\s*\()/ ),
|
|
new BrowserMatcher( 'CWORD', /[a-zA-Z_]\w*/ ),
|
|
new BrowserMatcher( 'ANY_SYMBOL', /./ ),
|
|
);
|
|
return l;
|
|
}
|