nl_tokens: to create a push parser pass in a callback function and omit the context parameter to create a pull parser pass in null for the callback function and initially provide an empty object as the context
pl_tokens: function jgeParse ( s , <mask> , context ) { if ( context && context . newState ) { if ( ! context . keepToken ) context . token = '' ; context . state = context . newState ; } else { context = { } ; reset ( context ) ; } var c ; for ( var i = context . position ; i < s . length ; i ++ ) { c = s . charAt ( i ) ; if ( ( c . charCodeAt ( 0 ) < 32 ) && ( context . validControlChars . indexOf ( c ) < 0 ) ) { context . newState = context . state = sError ; } if ( context . state != sContent ) { if ( context . validControlChars . indexOf ( c ) >= 0 ) { //other unicode spaces are not treated as whitespace c = ' ' ; } } context . bIndex = - 1 ; for ( var b = 0 ; b < context . boundary . length ; b ++ ) { if ( s . substr ( i , context . boundary [ b ] . length ) == context . boundary [ b ] ) { context . bIndex = b ; if ( context . boundary [ context . bIndex ] . length > 1 ) { i = i + context . boundary [ context . bIndex ] . length - 1 ; } break ; } } if ( context . bIndex >= 0 ) { if ( ( context . state != sValue ) && ( context . state != sComment ) ) { // && (context.state != sContent) context . token = context . token . trim ( ) ; } context . keepToken = false ; if ( ( ( context . state & 1 ) == 1 ) && ( ( context . token . trim ( ) !== '' ) || context . state == sValue ) ) { // TODO test element names for validity (using regex?) if ( context . state != sCData ) { context . token = context . token . replaceAll ( '&amp;' , '&' ) ; context . token = context . token . replaceAll ( '&quot;' , '"' ) ; context . token = context . token . replaceAll ( '&apos;' , "'" ) ; context . token = context . token . replaceAll ( '&gt;' , '>' ) ; context . token = context . token . replaceAll ( '&lt;' , '<' ) ; if ( context . token . indexOf ( '&#' ) >= 0 ) { context . token = context . token . replace ( / &(?:#([0-9]+)|#x([0-9a-fA-F]+)); / g , function ( match , group1 , group2 ) { var e ; if ( group2 ) { e = String . fromCharCode ( parseInt ( group2 , 16 ) ) ; if ( ( e . charCodeAt ( 0 ) < 32 ) && ( context . validControlChars . indexOf ( e ) < 0 ) ) { context . newState = context . state = sError ; } return e ; } else { e = String . fromCharCode ( group1 ) ; if ( ( e . charCodeAt ( 0 ) < 32 ) && ( context . validControlChars . indexOf ( e ) < 0 ) ) { context . newState = context . state = sError ; } return e ; } } ) ; } } if ( context . state == sElement ) context . depth ++ ; else if ( context . state == sEndElement ) { context . depth -- ; if ( context . depth < 0 ) { context . newState = context . state = sError ; } } if ( context . state == sError ) { context . error = true ; } if ( callback ) { callback ( context . state , context . token ) ; } if ( context . state == sError ) { context . boundary = [ ] ; } } if ( context . state == sInitial ) { if ( context . boundary [ context . bIndex ] == '<?' ) { context . newState = sDeclaration ; context . boundary = [ '?>' ] ; } else { context . newState = sElement ; context . boundary = [ '>' , ' ' , '/' , '!--' , '?' , '!DOCTYPE' , '![CDATA[' ] ; context . boundary = context . boundary . concat ( context . validControlChars ) ; } } else if ( context . state == sDeclaration ) { context . newState = sPreElement ; context . boundary = [ '<' ] ; if ( context . token . indexOf ( '1.1' ) > 0 ) { context . validControlChars . push ( '\u2028' , '\u0085' , '\u0015' ) ; } } else if ( context . state == sPreElement ) { context . newState = sElement ; context . boundary = [ '>' , ' ' , '/' , '!--' , '?' , '!DOCTYPE' , '![CDATA[' ] ; context . boundary = context . boundary . concat ( context . validControlChars ) ; } else if ( context . state == sElement ) { context . lastElement = context . token ; if ( c == '>' ) { context . newState = sContent ; context . boundary = [ '<!DOCTYPE' , '<' ] ; } else if ( c == ' ' ) { context . newState = sAttribute ; context . boundary = [ '/' , '=' , '>' ] ; } else if ( c == '/' ) { context . newState = sEndElement ; context . boundary = [ '>' ] ; context . keepToken = true ; } else if ( c == '?' ) { context . newState = sProcessingInstruction ; context . boundary = [ '?>' ] ; } else if ( context . boundary [ context . bIndex ] == '!--' ) { context . newState = sComment ; context . boundary = [ '-->' ] ; } else if ( context . boundary [ context . bIndex ] == '![CDATA[' ) { context . newState = sCData ; context . boundary = [ ']]>' ] ; } else if ( context . boundary [ context . bIndex ] == '!DOCTYPE' ) { context . newState = sDocType ; context . boundary = [ '>' , '[' ] ; } } else if ( context . state == sAttribute ) { if ( c == '=' ) { context . newState = sAttrNML ; context . boundary = [ '\'' , '"' ] ; } else if ( c == '>' ) { context . newState = sContent ; context . boundary = [ '<!DOCTYPE' , '<' ] ; } else if ( c == '/' ) { context . newState = sEndElement ; context . keepToken = true ; context . state = sAttributeSpacer ; // to stop dummy attributes being emitted to pullparser context . token = context . lastElement ; } } else if ( context . state == sAttrNML ) { context . newState = sValue ; context . boundary = [ c ] ; } else if ( context . state == sValue ) { context . newState = sAttribute ; context . boundary = [ '=' , '/' , '>' ] ; } else if ( context . state == sEndElement ) { if ( context . depth !== 0 ) context . newState = sContent ; context . boundary = [ '<' ] ; // don't allow DOCTYPE's after the first sEndElement } else if ( context . state == sContent ) { if ( context . boundary [ context . bIndex ] == '<!DOCTYPE' ) { context . newState = sDocType ; context . boundary = [ '>' , '[' ] ; } else { context . newState = sElement ; context . boundary = [ '>' , ' ' , '/' , '!--' , '?' , '![CDATA[' ] ; context . boundary = context . boundary . concat ( context . validControlChars ) ; } } else if ( context . state == sComment ) { context . newState = sContent ; context . boundary = [ '<!DOCTYPE' , '<' ] ; } else if ( context . state == sProcessingInstruction ) { context . newState = sContent ; context . boundary = [ '<!DOCTYPE' , '<' ] ; } else if ( context . state == sCData ) { context . newState = sContent ; context . boundary = [ '<!DOCTYPE' , '<' ] ; } else if ( context . state == sDocType ) { if ( context . boundary [ context . bIndex ] == '[' ) { context . newState = sDTD ; context . boundary = [ ']>' ] ; } else { context . newState = sPreElement ; context . boundary = [ '<' ] ; } } else if ( context . state == sDTD ) { context . newState = sPreElement ; context . boundary = [ '<' ] ; } if ( ! callback ) { if ( ( ( context . state & 1 ) == 1 ) && ( ( context . token . trim ( ) !== '' ) || context . state == sValue ) ) { context . position = i + 1 ; return context ; } } context . state = context . newState ; if ( ! context . keepToken ) context . token = '' ; } else { context . token += c ; } } if ( ( context . state == sEndElement ) && ( context . depth === 0 ) && ( context . token . trim ( ) === '' ) ) { context . wellFormed = true ; } if ( ( ! context . wellFormed ) && ( ! context . error ) ) { if ( callback ) { // generate a final error, only for pushparsers though callback ( sError , context . token ) ; } } context . state = sEndDocument ; if ( callback ) { callback ( context . state , context . token ) ; return context . wellFormed ; } else { return context ; } }