Home Manual Reference Source

Examples

More examples in the test files.

A convoluted '010101'.replace(/0/g, 'a').replace(/1/g, 'b').

import {map} from '@iterable-iterator/map';
import {enumerate} from '@iterable-iterator/zip';
import * as tape from '@async-abstraction/tape' ;
import {asyncIterableMap} from '@async-abstraction/tape';
import { grammar , ll1 , ast } from '@formal-language/grammar' ;

const G = grammar.from( {
    "root" : "root" ,
    "start" : "start" ,
    "eof" : "$" ,
    "productions" : {
        "root" : {
            "start" : [ "&bits" , "=$" ]
        } ,
        "bits" : {
            "add" : [ "&bit" , "&bits" ] ,
            "end" : [ ] ,
        } ,
        "bit" : [
            [ "=0" ] ,
            [ "=1" ] ,
        ] ,
    } ,
} ) ;

const parser = ll1.from(G);

const replace = async input => {

    const tokens = tape.fromIterable(
        map(
            ( [ i , a ] ) => ({
                "type" : "leaf" ,
                "terminal" : a ,
                "buffer" : a ,
                "position" : i ,
            }) ,
            enumerate( input )
        )
    ) ;

    const tree = parser.parse(tokens);

    const m = ( children , match , ctx ) => ast.map( async child => child.type === 'leaf' ? child : await ast.transform( child , match , ctx ) , children ) ;

    const transform = {
        "root" : {
            "start" : ( tree , match ) => ({
                "type" : "node" ,
                "nonterminal" : "root" ,
                "production" : "start" ,
                "children" : m( tree.children , match ) ,
            }) ,
        } ,
        "bits" : {
            "add" : ( tree , match ) =>  ({
                "type" : "node" ,
                "nonterminal" : "letters" ,
                "production" : "yetanotherletter" ,
                "children" : m( tree.children , match ) ,
            }) ,
            "end" : ( ) =>  ({
                "type" : "node" ,
                "nonterminal" : "letters" ,
                "production" : "done" ,
                "children" : [ ] ,
            }) ,
        } ,
        "bit" : [
            tree => ({
                "type" : "node" ,
                "nonterminal" : "letter" ,
                "production" : "aaa" ,
                "children" : ast.map( leaf => ({
                    "type" : "leaf" ,
                    "terminal" : "a" ,
                    "buffer" : "a" ,
                    "position" : leaf.position ,
                }) , tree.children ) ,
            }) ,
            tree => ({
                "type" : "node" ,
                "nonterminal" : "letter" ,
                "production" : "bbb" ,
                "children" : ast.map( leaf => ({
                    "type" : "leaf" ,
                    "terminal" : "b" ,
                    "buffer" : "b" ,
                    "position" : leaf.position ,
                }) , tree.children ) ,
            }) ,
        ] ,
    } ;

    const transformed = await ast.transform( tree , transform ) ;

    const flattened = ast.flatten( transformed ) ;

    const chunks = asyncIterableMap( leaf => leaf.buffer , flattened ) ;

    const output = tape.fromAsyncIterable( chunks ) ;

    return await tape.toString( output ) ;

} ;

replace('010101').then( output => console.log(output) ) ; // 'ababab'