Stream Manipulation

DaeDaLus parsers operate on an input stream, which by default is the input data to the parser. However, the input stream can be manipulated directly. For example, we can write a parser function which runs two different parsers on the same stream.

def ParseTwice P1 P2 =
  block
    let cur = GetStream
    p1result = P1
    SetStream cur
    p2result = P2

By manipulating the stream, we can also run a parser on a fixed-size sub-stream. The following parser parses a size-n chunk which begins with a sequence of letters, and then is filled with spaces:

def LetterFill n =
  block
    let cur  = GetStream
    let this = Take n cur
    let next = Drop n cur
    SetStream this
    $$ = block
           $$ = Many $[ 'A'..'Z' ]
           Many $[ ' ' ]
           END
    SetStream next

It is also possible to directly access the current position in the stream using Offset. This can be used to calculate how many characters were read by a particular parser:

def OffsetTest =
  block
    a = Offset
    Match "AA"
    b = Offset
    Match "AAA"
    c = Offset

-- Result: { a:0, b:2, c:5 }

The arrayStream operator converts an array into a stream:

def CatStream a b =
  block
    SetStream (arrayStream (concat [a, b]))
    Match "AA"
    Match "BBB"
    ^ {}
}

This example will succeed if the concatenation of the arrays a and b starts with the string "AABBB".