README-work
FunctionalParsers Raku package
Raku package with a system of functional parsers.
Installation
From Zef ecosystem:
zef install FunctionalParsers;
From GitHub:
zef install https://github.com/antononcube/Raku-FunctionalParsers.git
Examples
Make a parser for a family of (two) simple sentences:
use FunctionalParsers :ALL;
my &p1 = (symbol('numerical') «|» symbol('symbolic')) «&» symbol('integration');
Here we parse sentences adhering to the grammar of the defined parser:
.say for ("numerical integration", "symbolic integration")>>.words.map({ $_ => &p1($_)});
These sentences are not be parsed:
("numeric integration", "symbolic summation")>>.words.map({ $_ => &p1($_)});
Infix operators
Several notation alternatives are considered for the infix operations corresponding to the different combinators and transformers. Here is a table with different notation styles:
Description | set | double | n-ary |
sequential combination | (&) | «&» | ⨂ |
left sequential pick | (<&) | «& | ◁ |
right sequential pick | (&>) | &» | ▷ |
alternatives combination | (⎸) | «⎸» | ⨁ |
function application | (^) | «o | ⨀ |
Consider the parsers:
my &p1 = apply( {1}, symbol('one'));
my &p2 = apply( {2}, symbol('two'));
my &p3 = apply( {3}, symbol('three'));
my &p4 = apply( {4}, symbol('four'));
my &pM = symbol('million');
my &pTh = symbol('things');
Here are spec examples for each style of infix operators:
# set
my &p = (&p1 (|) &p2 (|) &p3 (|) &p4) (&) (&pM (^) {10**6}) (&) &pTh;
&p('three million things'.words.List).head.tail;
# double
(&p1 «|» &p2 «|» &p3 «|» &p4) «&» &pM «o {10**6} «&» &pTh;
# n-ary
(&p1 ⨁ &p2 ⨁ &p3 ⨁ &p4) ⨂ {10**6} ⨀ &pM ⨂ &pTh
Remark: The arguments of the apply operator ⨀
are "reversed" when compared to the arguments of the operators (^)
and «0
.
For ⨀
the function to be applied is the first argument.
Parser generation
Here is an Extended Backus-Naur Form (EBNF) grammar:
my $ebnfCode = q:to/END/;
<digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
<number> = <digit> , { <digit> } ;
<top> = <number> ;
END
Here generation is the corresponding functional parsers code:
use FunctionalParsers::EBNF;
.say for parse-ebnf($ebnfCode, target => 'Raku::Code').head.tail;
For more detailed examples see "Parser-code-generation.md".
Random sentence generation
Here is an EBNF grammar:
my $ebnfCode = q:to/END/;
<top> = <who> , <verb> , <lang> ;
<who> = 'I' | 'We' ;
<verb> = 'love' | 'hate' | { '♥️' } | '🤮';
<lang> = 'Julia' | 'Perl' | 'Python' | 'R' | 'WL' ;
END
Here is generation of random sentences with the grammar above:
.say for random-sentence($ebnfCode, 12);
CLI
The package provides a Command Line Interface (CLI) script for parsing EBNF. Here is its usage message:
fp-parse-ebnf --help
References
Articles
[JF1] Jeroen Fokker, "Function Parsers", (1997), Conference: Advanced Functional Programming, First International Spring School on Advanced Functional Programming Techniques-Tutorial Text. 10.1007/3-540-59451-5_1.
[WV1] Wim Vanderbauwhede, List-based parser combinators in Haskell and Raku, (2020), Musings of an Accidental Computing Scientist at codeberg.page.
Packages, repositories
[AAp1] Anton Antonov, "FunctionalParsers.m", (2014), MathematicaForPrediction at GitHub.
[WV1] Wim Vanderbauwhede, List-based parser combinator library in Raku, (2020), GitHub/wimvanderbauwhede.
[WV2] Wim Vanderbauwhede, Parser::Combinators Perl package, (2013-2015), GitHub/wimvanderbauwhede.