Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Parse BNF grammar definitions

License

NotificationsYou must be signed in to change notification settings

shnewto/bnf

Repository files navigation

.github/workflows/ci.ymlcoverallsCrates.io VersionCrates.ioLICENSE

A library for parsing Backus–Naur form context-free grammars.

What does a parsable BNF grammar look like?

The following grammar from theWikipedia page on Backus-Naur formexemplifies a compatible grammar. (*Note: parser allows for an optional ';'to indicate the end of a production)

 <postal-address> ::= <name-part> <street-address> <zip-part>      <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>                    | <personal-part> <name-part>  <personal-part> ::= <initial> "." | <first-name> <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>       <zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL><opt-suffix-part> ::= "Sr." | "Jr." | <roman-numeral> | ""    <opt-apt-num> ::= <apt-num> | ""

Output

Take the following grammar for DNA sequences to be input to this library'sparse function.

<dna> ::= <base> | <base> <dna><base> ::= "A" | "C" | "G" | "T"

The output is aGrammar object representing a tree that looks like this:

Grammar {    productions: [        Production {            lhs: Nonterminal(                "dna"            ),            rhs: [                Expression {                    terms: [                        Nonterminal(                            "base"                        )                    ]                },                Expression {                    terms: [                        Nonterminal(                            "base"                        ),                        Nonterminal(                            "dna"                        )                    ]                }            ]        },        Production {            lhs: Nonterminal(                "base"            ),            rhs: [                Expression {                    terms: [                        Terminal(                            "A"                        )                    ]                },                Expression {                    terms: [                        Terminal(                            "C"                        )                    ]                },                Expression {                    terms: [                        Terminal(                            "G"                        )                    ]                },                Expression {                    terms: [                        Terminal(                            "T"                        )                    ]                }            ]        }    ]}

Once theGrammar object is populated, to generate a random sentence from itcall the object's generate function.grammar.generate(). For the above grammaryou could expect something likeTGGC orAG.

If the generate function can't find a production for a nonterminal it triesto evaluate it will print the identifer as a nonterminal, i.e.<identifier>.

The generate function will return an error if it detects an infinite loop causedby a production such as<PATTERN> ::= <PATTERN>.

Parse Example

use bnf::Grammar;let input ="<postal-address> ::= <name-part> <street-address> <zip-part>        <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>                        | <personal-part> <name-part>    <personal-part> ::= <initial> '.' | <first-name>    <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>        <zip-part> ::= <town-name> ',' <state-code> <ZIP-code> <EOL>    <opt-suffix-part> ::= 'Sr.' | 'Jr.' | <roman-numeral> | ''        <opt-apt-num> ::= <apt-num> | ''";let grammar:Result<Grammar,_> = input.parse();match grammar{Ok(g) =>println!("{:#?}", g),Err(e) =>println!("Failed to make grammar from String: {}", e),}

Generate Example

use bnf::Grammar;let input ="<dna> ::= <base> | <base> <dna>    <base> ::= 'A' | 'C' | 'G' | 'T'";let grammar:Grammar = input.parse().unwrap();let sentence = grammar.generate();match sentence{Ok(s) =>println!("random sentence: {}", s),Err(e) =>println!("something went wrong: {}!", e)}

Parse Sentence via Grammar

use bnf::Grammar;let input ="<dna> ::= <base> | <base> <dna>    <base> ::= 'A' | 'C' | 'G' | 'T'";let grammar:Grammar = input.parse().unwrap();let sentence ="GATTACA";letmut parse_trees = grammar.parse_input(sentence);match parse_trees.next(){Some(parse_tree) =>println!("{}", parse_tree),    _ =>println!("Grammar could not parse sentence"),}

[8]ページ先頭

©2009-2025 Movatter.jp