Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add syntax highlighting to README #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 40 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,51 +15,53 @@ it's not actually useable without copying large chunks of the code into your cra

## Example
Here is an example of a simple parser which can be used to evaluate mathematical expressions.
```rust

use rparse::*; // but see https://github.com/mozilla/rust/issues/3781
use rparse::*; // but see https://github.com/mozilla/rust/issues/3781

fn expr_parser() -> Parser<int>
{
let int_literal = decimal_number().err("number").s0();

// Parenthesized expressions require a forward reference to the expr parser
// so we initialize a function pointer to something of the right type, create
// a parser using the parser expr_ptr points to, and fixup expr_ptr later.
let expr_ptr = @mut ret(0i);
let expr_ref = forward_ref(expr_ptr);
fn expr_parser() -> Parser<int>
{
let int_literal = decimal_number().err("number").s0();

// sub_expr := [-+]? '(' expr ')'
// The err function provides better error messages if the factor parser fails
// on the very first character.
let sub_expr = or_v(@~[
seq4_ret2("+".s0(), "(".s0(), expr_ref, ")".s0()),
seq4_ret2("-".s0(), "(".s0(), expr_ref, ")".s0()).thene(|v| ret(-v) ),
seq3_ret1( "(".s0(), expr_ref, ")".s0())]).err("sub-expression");
// Parenthesized expressions require a forward reference to the expr parser
// so we initialize a function pointer to something of the right type, create
// a parser using the parser expr_ptr points to, and fixup expr_ptr later.
let expr_ptr = @mut ret(0i);
let expr_ref = forward_ref(expr_ptr);

// factor := integer | sub_expr
let factor = int_literal.or(sub_expr);
// sub_expr := [-+]? '(' expr ')'
// The err function provides better error messages if the factor parser fails
// on the very first character.
let sub_expr = or_v(@~[
seq4_ret2("+".s0(), "(".s0(), expr_ref, ")".s0()),
seq4_ret2("-".s0(), "(".s0(), expr_ref, ")".s0()).thene(|v| ret(-v) ),
seq3_ret1( "(".s0(), expr_ref, ")".s0())]).err("sub-expression");

// term := factor ([*/] factor)*
let term = do factor.chainl1("*".s0().or("/".s0()))
|lhs, op, rhs| {if op == @~"*" {lhs*rhs} else {lhs/rhs}};
// factor := integer | sub_expr
let factor = int_literal.or(sub_expr);

// expr := term ([+-] term)*
let expr = term.chainl1("+".s0().or("-".s0()),
|lhs, op, rhs| {if op == @~"+" {lhs + rhs} else {lhs - rhs}}).err("expression");
*expr_ptr = expr;
// term := factor ([*/] factor)*
let term = do factor.chainl1("*".s0().or("/".s0()))
|lhs, op, rhs| {if op == @~"*" {lhs*rhs} else {lhs/rhs}};

// start := s0 expr EOT
let s = ret(0).s0();
expr.everything(s)
}

// expr := term ([+-] term)*
let expr = term.chainl1("+".s0().or("-".s0()),
|lhs, op, rhs| {if op == @~"+" {lhs + rhs} else {lhs - rhs}}).err("expression");
*expr_ptr = expr;

// start := s0 expr EOT
let s = ret(0).s0();
expr.everything(s)
}
```
Usage looks like this:

fn test_usage()
```rust
fn test_usage()
{
match expr_parser().parse(@~"test", ~"2+3*5")
{
match expr_parser().parse(@~"test", ~"2+3*5")
{
result::Ok(value) => assert value == 17,
result::Err(_) => assert false,
}
result::Ok(value) => assert value == 17,
result::Err(_) => assert false,
}
}
```