text = lexeme[+(char_ - '<') [_val += _1]];
node = (xml | text) [_val = _1];
start_tag =
'<'
>> !lit('/')
>> lexeme[+(char_ - '>') [_val += _1]]
>> '>'
;
end_tag =
"</"
>> string(_r1)
>> '>'
;
xml =
start_tag [at_c<0>(_val) = _1]
>> *node [push_back(at_c<1>(_val), _1)]
>> end_tag(at_c<0>(_val))
;
The (>>) operator here is defined in the same as the Applicative/Monad bind: (>>).
For the effect of full monadic bind (>>=), the explicit assignment into "val" is used.Here is the same example encoded using Monadic Parsec:
text = many (notChar '<')
node = xml <|> text
start_tag = do
char '<'
notChar '/'
val <- many (notChar '>')
char '>'
return val
end_tag name = do
string "</"
string name
char ">"
xml = do
name <- start_tag
val <- node
end_tag name
return (name, val)
Now, one interesting difference between Parsec and the spirit framework, is that Parsec instantiated the Monad class to allow composition of Parsers, whereas spirit defines its own ad-hoc combinators.This means that with parsec, I can use all of the existing monadic functions.
For example, I can use the "replicateM" function, which replicates a monadic action N times to say I want 3 XML elements in sequence:
replicateM 3 xml
Or I can use one of the hundreds of others of available combinators.Of course boost spirit can also encode these combinators on top of their own ad-hoc operators, but they would be:
* Duplicate code with every other monadic framework
* Another vocabulary to learn in order to compose parsers
* Cannot re-use any third party code that works with every monad in existence