Parser-code-generation

Parser code generation

Introduction

This document has examples of parser code generation for different programming languages.

Raku class code

FunctionalParsers

In this section we generate Raku parser code that uses the functions of this package, "FunctionalParsers".

use FunctionalParsers;
use FunctionalParsers::EBNF;

my $ebnfCode = q:to/END/;
<digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
<number> = <digit> , { <digit> } <@ &{ $_.flat.join } ;
<top> = <number> ;
END

my $res = parse-ebnf($ebnfCode, <CODE>, target => 'Raku::Class');
$res.head.tail;
# class FP {
# 	method pDIGIT(@x) { alternatives(symbol('0'), symbol('1'), symbol('2'), symbol('3'), symbol('4'), symbol('5'), symbol('6'), symbol('7'), symbol('8'), symbol('9'))(@x) }
# 	method pNUMBER(@x) { apply(&{ $_.flat.join }, sequence({self.pDIGIT($_)}, many({self.pDIGIT($_)})))(@x) }
# 	method pTOP(@x) { {self.pNUMBER($_)}(@x) }
# 	has &.parser is rw = -> @x { self.pTOP(@x) };
# }

Let us get (evaluated) class of the code above:

my $class = parse-ebnf($ebnfCode, <EVAL>, target => 'Raku::Class', parser-name => 'MyFP');
# (MyFP)

Here we create an instance of the obtained class and parse with it:

$class.new.parser.('3234'.comb);
# ((() 3234) ((4) 323) ((3 4) 32) ((2 3 4) 3))

Here we generate the parser class code again, but here we place it into an "as-is" Markdown cell:

parse-ebnf($ebnfCode, <CODE>, target => 'Raku::Class').head.tail;
class FP {
	method pDIGIT(@x) { alternatives(symbol('0'), symbol('1'), symbol('2'), symbol('3'), symbol('4'), symbol('5'), symbol('6'), symbol('7'), symbol('8'), symbol('9'))(@x) }
	method pNUMBER(@x) { apply(&{ $_.flat.join }, sequence({self.pDIGIT($_)}, many({self.pDIGIT($_)})))(@x) }
	method pTOP(@x) { {self.pNUMBER($_)}(@x) }
	has &.parser is rw = -> @x { self.pTOP(@x) };
}

Grammar

In this sub-section we generate code for Raku's built-in grammars.

Here we generate grammar class and place it into an "as-is" Markdown cell:

parse-ebnf($ebnfCode, <CODE>, target => 'Raku::Grammar', parser-name => 'MyFP').head.tail;
grammar MyFP {
	rule pDIGIT { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' }
	rule pNUMBER { <pDIGIT> <pDIGIT>* }
	rule TOP { <pNUMBER> }
}

Here we generate the grammar code and evaluate it:

my $gr = parse-ebnf($ebnfCode, <EVAL>, target => 'Raku::Grammar', parser-name => 'MyGr');
# (MyGr)

Here we parse with the grammar:

$gr.parse('944'.comb);
# 「9 4 4」
#  pNUMBER => 「9 4 4」
#   pDIGIT => 「9 」
#   pDIGIT => 「4 」
#   pDIGIT => 「4」

Wolfram Language code

In this section we generate Wolfram Language (WL) parsers code. (WL is also known as "Mathematica".)

FunctionalParsers

In this sub-section generate code for the WL paclet "AntonAntonov/FunctionalParsers" (which corresponds to this Raku package "FunctionalParsers".)

Here we transform the EBNF code above to have WL function:

my $ebnfCodeWL = $ebnfCode.subst('$_.flat.join', 'StringJoin@*Flatten');
# <digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
# <number> = <digit> , { <digit> } <@ &{ StringJoin@*Flatten } ;
# <top> = <number> ;

Here we generate WL code:

parse-ebnf($ebnfCodeWL, <CODE>, target => 'WL::Code').head.tail.subst(/';' \s* /,";\n"):g;
pDIGIT = ParseAlternativeComposition[ParseSymbol["0"], ParseSymbol["1"], ParseSymbol["2"], ParseSymbol["3"], ParseSymbol["4"], ParseSymbol["5"], ParseSymbol["6"], ParseSymbol["7"], ParseSymbol["8"], ParseSymbol["9"]];
pNUMBER = ParseApply[ StringJoin@*Flatten , ParseSequentialComposition[pDIGIT, ParseMany[pDIGIT]]];
pTOP = pNUMBER;

GrammarRules

In this sub-section we generate code for WL's built-in GrammarRules.

parse-ebnf($ebnfCodeWL, <CODE>, target => 'WL::Grammar').head.tail;
# GrammarRules[{"pTOP" -> "pNUMBER"}, {"pDIGIT" -> "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9","pNUMBER" -> FixedOrder["pDIGIT", "pDIGIT"..] :>  StringJoin@*Flatten }]

FunctionalParsers v0.1.0

A system of functional parsers (combinators, transformers, generators.)

Authors

  • Anton Antonov

License

Artistic-2.0

Dependencies

Test Dependencies

Provides

  • FunctionalParsers
  • FunctionalParsers::EBNF
  • FunctionalParsers::EBNF::Actions::Common
  • FunctionalParsers::EBNF::Actions::Raku::Class
  • FunctionalParsers::EBNF::Actions::Raku::ClassAttr
  • FunctionalParsers::EBNF::Actions::Raku::Code
  • FunctionalParsers::EBNF::Actions::Raku::Grammar
  • FunctionalParsers::EBNF::Actions::Raku::Pairs
  • FunctionalParsers::EBNF::Actions::Raku::Random
  • FunctionalParsers::EBNF::Actions::WL::Code
  • FunctionalParsers::EBNF::Actions::WL::Grammar
  • FunctionalParsers::EBNF::Parser::FromCharacters
  • FunctionalParsers::EBNF::Parser::FromTokens

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.