Created
October 24, 2017 01:06
-
-
Save ShayCichocki/5c41f357425dd1dd364f38020b5f552d to your computer and use it in GitHub Desktop.
BNF form parser, exampled with story generating bnf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class BNFParserGenerator { | |
private $defs = []; | |
/** | |
* This converts the BNF string into a set of generator definitions | |
* that we can use later | |
* @param string $string | |
*/ | |
public function parseString(string $string) { | |
$string = str_replace("\\n", 'NEW_LINE', $string); | |
$split = array_filter(explode("\n", $string)); | |
$exploded = array_map(function($gen) { | |
$gen = str_replace("NEW_LINE", "\n", $gen); | |
return explode("::=", trim($gen)); | |
}, $split); | |
foreach ($exploded as $item) { | |
$matches = []; | |
preg_match('/<([A-z\-]+)>/', $item[0], $matches); | |
$generators = explode("|", $item[1]); | |
$generators = array_map(function($gen) { | |
return trim($gen); | |
}, $generators); | |
$this->defs[$matches[1]] = $generators; | |
} | |
} | |
/** | |
* This creates whole new strings based on the grammar | |
* @param string $startGeneratorName | |
* @return string | |
*/ | |
public function generateString(string $startGeneratorName): string { | |
if(!isset($this->defs[$startGeneratorName])) { | |
return 'Generator Doesnt Exist'; | |
} | |
//get a random key from the set of tokens that the generator can make | |
$key = array_rand($this->defs[$startGeneratorName]); | |
$phrase = $this->defs[$startGeneratorName][$key]; | |
//regex to potentially find replaceable elements in the selected token | |
$re = '/(?<!\\\\)<(.*?)(?<!\\\\)>/'; | |
//Does a callback on all regex matches and replaces them with the generator | |
//aka recurse recurse | |
$result = preg_replace_callback($re, function($match) { | |
return $this->generateString($match[1]); | |
}, $phrase); | |
//dont need this and could fix grammar to not have '' but pfft | |
$result = str_replace("'", "", $result); | |
return $result; | |
} | |
} | |
$bnfString = " | |
<plot> ::= <plot-point>. <plot> | <plot-point>. <transition><plot-point>.<plot> | <plot-point>. | |
<plot-point> ::= <char-action><necessities><character><about> | <char-action> | |
<char-action> ::= <character><action><about> | |
<necessities> ::= '-' | '->' | <about> | '+' | '*' | |
<action> ::= '1' | '2' | '3' | '4' |'5' | '' | |
<about> ::= [<character>] | [<character>+<character>] | '' | |
<character> ::= 'A'|'B'|'C'|'D'|'E'|'Z' | |
<transition> ::= '\\n=\\n' | '\\n...\\n' | '' | |
"; | |
$parser = new BNFParserGenerator(); | |
$parser->parseString($bnfString); | |
$result = ''; | |
echo $parser->generateString('plot')."\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment