strscan |
|
---|---|
StringScanner is a simple string tokenizer that provides for lexical scanning operations on a string. It’s a JavaScript port of the Ruby library with the same name. Scanning a string means keeping track of and advancing a position (a zero-based index into the source string) and matching regular expressions against the portion of the source string after the position. StringScanner is written in CoffeeScript and distributed via npm as a CommonJS module. Clone, fork, or file bugs at GitHub. Quick start
|
|
Creating a scanner |
|
Create a new |
(exports ? this).StringScanner = class StringScanner
constructor: (source) ->
@source = source.toString()
@reset() |
Scanning for matches The |
|
Matches |
scan: (regexp) ->
if (matches = regexp.exec @getRemainder()) and matches.index is 0
@setState matches,
head: @head + matches[0].length
last: @head
else
@setState [] |
Matches |
scanUntil: (regexp) ->
if matches = regexp.exec @getRemainder()
@setState matches,
head: @head + matches.index + matches[0].length
last: @head
@source.slice @last, @head
else
@setState [] |
Scans one character, returns it, and advances the scanner’s position. |
scanChar: ->
@scan /./ |
Skips over the given |
skip: (regexp) ->
@match.length if @scan regexp |
Skips over the given |
skipUntil: (regexp) ->
@head - @last if @scanUntil regexp |
Looking ahead The |
|
Checks to see if |
check: (regexp) ->
if (matches = regexp.exec @getRemainder()) and matches.index is 0
@setState matches
else
@setState [] |
Checks to see if |
checkUntil: (regexp) ->
if matches = regexp.exec @getRemainder()
@setState matches
@source.slice @head, @head + matches.index + matches[0].length
else
@setState [] |
Returns the next |
peek: (length) ->
@source.substr @head, length ? 1 |
Accessing scanner data The |
|
Returns the scanner’s source string. |
getSource: ->
@source |
Returns the portion of the source string from the scanner’s position onward. |
getRemainder: ->
@source.slice @head |
Returns the scanner’s position. In the reset position, this value is zero. In the terminated position, this value is the length of the source string. |
getPosition: ->
@head |
Checks to see if the scanner has reached the end of the string. |
hasTerminated: ->
@head is @source.length |
Accessing match data The |
|
Returns the portion of the source string leading up to, but not
including, the most recent match. (Returns |
getPreMatch: ->
@source.slice 0, @head - @match.length if @match |
Returns the most recently matched portion of the source string (or
|
getMatch: ->
@match |
Returns the portion of the source string immediately following the most
recent match. (Returns |
getPostMatch: ->
@source.slice @head if @match |
Returns the |
getCapture: (index) ->
@captures[index] |
Modifying the scanner’s state The |
|
Resets the scanner back to its original position and clears its match data. |
reset: ->
@setState [], head: 0, last: 0 |
Advances the scanner position to the end of the string and clears its match data. |
terminate: ->
@setState [], head: @source.length, last: @head |
Appends |
concat: (string) ->
@source += string |
Sets the scanner’s position to its previous position and clears its match data. Only one previous position is stored. Throws an exception if there is no previous position. |
unscan: ->
if @match
@setState [], head: @last, last: 0
else
throw "nothing to unscan" |
Private methods |
|
Sets the state of the scanner (for internal use only). |
setState: (matches, values) ->
@head = values?.head ? @head
@last = values?.last ? @last
@captures = matches.slice 1
@match = matches[0] |