import { grammar , tokens , isBooleanable , isOperator , hasToken } from "./grammar" ; const rexString = `(${ Object . values ( tokens ) . join ( "|" ) })` ; const rex = new RegExp ( rexString , "g" ) ; const grammers = Object . entries ( grammar ) ; function toNode ( token ) { for ( let i = 0 ; i < grammers . length ; i ++ ) { const [ test , createNode ] = grammers [ i ] ; const testWithoutLookahead = test === tokens . GT ? "\\>" : test ; const testPassed = new RegExp ( `^${ testWithoutLookahead }$` ) . test ( token ) ; if ( testPassed ) { return createNode ( token ) ; } } } function disambiguateNotOperator ( node , index , arr ) { if ( ! ( isOperator ( node ) && hasToken ( node , "!" ) ) ) { return node ; } const nextNode = arr [ index + 1 ] ; if ( isBooleanable ( nextNode ) ) { return node ; } return grammar [ tokens . FALSY_KEYWORD ] ( "!" ) ; } export function lexer ( input ) { rex . lastIndex = 0 ; return ( input . replace ( /\/\/.*(\n|$)/g , "" ) . replace ( /((?:string|array)\[)([^\]]*)(\])/g , "$1($2)" ) . match ( rex ) . map ( toNode ) . map ( disambiguateNotOperator ) ) ; }