Skip to content

Commit

Permalink
Merge be2e12f into 9d919ce
Browse files Browse the repository at this point in the history
  • Loading branch information
dragostis committed Jun 22, 2016
2 parents 9d919ce + be2e12f commit 47f074a
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 186 deletions.
10 changes: 5 additions & 5 deletions examples/calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ impl_rdp! {
}

process! {
main(&self) -> i32 { // return an i32 in the end
compute(&self) -> i32 { // return an i32 in the end
(&number: number) => { // capture number as &str
number.parse::<i32>().unwrap()
},
(_: addition, left: main(), sign, right: main()) => { // get left & right by calling
match sign.rule { // main recursively
(_: addition, left: compute(), sign, right: compute()) => { // get left & right by
match sign.rule { // calling compute
Rule::plus => left + right,
Rule::minus => left - right,
_ => unreachable!()
}
},
(_: multiplication, left: main(), sign, right: main()) => {
(_: multiplication, left: compute(), sign, right: compute()) => {
match sign.rule {
Rule::times => left * right,
Rule::slash => left / right,
Expand All @@ -48,5 +48,5 @@ fn main() {

parser.expression();

println!("{}", parser.process()); // prints 44
println!("{}", parser.compute()); // prints 44
}
44 changes: 23 additions & 21 deletions src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ macro_rules! grammar {
// handle precedence climbing
( @conv_prec $pos:ident ($_prec:expr) $_atomic:tt $slf:ident [] [] [] ) => {
{
$slf.set_pos($pos);
$slf.input_mut().set_pos($pos);

None
}
Expand Down Expand Up @@ -174,27 +174,27 @@ macro_rules! grammar {

{
let mut primary = |slf: &mut Self| {
let pos = slf.pos();
let pos = slf.input().pos();

grammar!(@skip $atomic slf);

let result = grammar!(@conv $atomic slf [ $( $primary )* ] [] []);

if !result {
slf.set_pos(pos);
slf.input_mut().set_pos(pos);
}

result
};
let mut climb = |slf: &mut Self| {
let pos = slf.pos();
let pos = slf.input().pos();

grammar!(@skip $atomic slf);

grammar!(@conv_prec pos (0u8) $atomic slf [ $( $ts )* ] [] [])
};

let mut pos = $slf.pos();
let mut pos = $slf.input().pos();
let queue_pos = $slf.queue().len();

let result = primary($slf);
Expand Down Expand Up @@ -272,8 +272,10 @@ macro_rules! grammar {
// match
( @mtc $slf:ident (( $exp:expr )) ) => (($exp));
( @mtc $slf:ident [ $left:tt .. $right:tt ]) => (grammar!(@mtc $slf [$left, $right]));
( @mtc $slf:ident [ $left:expr, $right:expr ]) => ($slf.match_range($left, $right));
( @mtc $slf:ident [ $str:expr ]) => ($slf.match_string($str));
( @mtc $slf:ident [ $left:expr, $right:expr ]) => {
$slf.input_mut().match_range($left, $right)
};
( @mtc $slf:ident [ $str:expr ]) => ($slf.input_mut().match_string($str));
( @mtc $slf:ident $rule:ident) => ($slf.$rule());

// process postfix
Expand All @@ -282,17 +284,17 @@ macro_rules! grammar {
{
grammar!(@process false $slf [(( $slf.try(false, |$slf| {
if grammar!(@mtc $slf $a) {
let original = $slf.pos();
let original = $slf.input().pos();

$slf.skip_ws();

let pos = $slf.pos();
let pos = $slf.input().pos();
let len = $slf.queue().len();

let result = grammar!(@mtc $slf $b);

if $slf.pos() == pos && !$slf.eoi_matched() {
$slf.set_pos(original);
if $slf.input().pos() == pos && !$slf.eoi_matched() {
$slf.input_mut().set_pos(original);
}

result
Expand All @@ -319,16 +321,16 @@ macro_rules! grammar {
( @process false $slf:ident [ $a:tt $( $tail:tt )* ] [ * $( $optail:tt )* ] ) => {
{
grammar!(@process false $slf [(( {
let mut pos = $slf.pos();
let mut pos = $slf.input().pos();

loop {
if !grammar!(@mtc $slf $a) {
$slf.set_pos(pos);
$slf.input_mut().set_pos(pos);

break
}

pos = $slf.pos();
pos = $slf.input().pos();

$slf.skip_ws();
}
Expand All @@ -354,12 +356,12 @@ macro_rules! grammar {
{
grammar!(@process false $slf [(( if grammar!(@mtc $slf $a) {
loop {
let pos = $slf.pos();
let pos = $slf.input().pos();

$slf.skip_ws();

if !grammar!(@mtc $slf $a) {
$slf.set_pos(pos);
$slf.input_mut().set_pos(pos);

break
}
Expand Down Expand Up @@ -455,14 +457,14 @@ macro_rules! grammar {
let slf = self;
grammar!(@skip $name slf);

let pos = slf.pos();
let pos = slf.input().pos();
let len = slf.queue().len();
let tracked_len = slf.tracked_len();

let result = grammar!(@atomic $name false slf [ $( $ts )* ]);

if result {
let new_pos = slf.pos();
let new_pos = slf.input().pos();

let token = Token {
rule: Rule::$name,
Expand Down Expand Up @@ -493,7 +495,7 @@ macro_rules! grammar {
let slf = self;
grammar!(@skip $name slf);

let pos = slf.pos();
let pos = slf.input().pos();
let len = slf.queue().len();

let toggled = slf.is_atomic();
Expand All @@ -509,7 +511,7 @@ macro_rules! grammar {
}

if result {
let new_pos = slf.pos();
let new_pos = slf.input().pos();

let token = Token {
rule: Rule::$name,
Expand Down Expand Up @@ -538,7 +540,7 @@ macro_rules! grammar {
let slf = self;
grammar!(@skip $name slf);

let pos = slf.pos();
let pos = slf.input().pos();

let result = grammar!(@atomic $name false slf [ $( $ts )* ]);

Expand Down
23 changes: 14 additions & 9 deletions src/inputs/string_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use super::super::Input;
/// ```
pub struct StringInput<'a> {
string: &'a str,
pos: usize
pos: usize,
}

impl<'a> StringInput<'a> {
Expand All @@ -43,7 +43,7 @@ impl<'a> StringInput<'a> {
pub fn new(string: &'a str) -> StringInput<'a> {
StringInput {
string: string,
pos : 0
pos: 0,
}
}
}
Expand Down Expand Up @@ -76,8 +76,10 @@ impl<'a> Input<'a> for StringInput<'a> {

#[inline]
fn line_col(&self, pos: usize) -> (usize, usize) {
fn find(chars: &mut Peekable<Chars>, pos: usize,
current: (usize, usize)) -> (usize, usize) {
fn find(chars: &mut Peekable<Chars>,
pos: usize,
current: (usize, usize))
-> (usize, usize) {
if pos == 0 {
current
} else {
Expand All @@ -94,10 +96,10 @@ impl<'a> Input<'a> for StringInput<'a> {
} else {
find(chars, pos - 1, (current.0 + 1, 1))
}
},
}
Some('\n') => find(chars, pos - 1, (current.0 + 1, 1)),
Some(_) => find(chars, pos - 1, (current.0, current.1 + 1)),
None => unreachable!()
Some(c) => find(chars, pos - c.len_utf8(), (current.0, current.1 + 1)),
None => unreachable!(),
}
}
}
Expand All @@ -106,7 +108,9 @@ impl<'a> Input<'a> for StringInput<'a> {
panic!("position out of bounds");
}

find(&mut self.string.chars().peekable(), pos, (1, 1))
let slice = &self.string[..pos];

find(&mut slice.chars().peekable(), pos, (1, 1))
}

#[inline]
Expand Down Expand Up @@ -211,7 +215,7 @@ mod tests {

#[test]
fn line_col() {
let input = StringInput::new("a\rb\nc\r\nd");
let input = StringInput::new("a\rb\nc\r\nd嗨");

assert_eq!(input.line_col(0), (1, 1));
assert_eq!(input.line_col(1), (1, 2));
Expand All @@ -222,6 +226,7 @@ mod tests {
assert_eq!(input.line_col(6), (4, 1));
assert_eq!(input.line_col(7), (4, 1));
assert_eq!(input.line_col(8), (4, 2));
assert_eq!(input.line_col(11), (4, 3));
}

#[test]
Expand Down
22 changes: 11 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,15 @@
//! ```
//!
//! To process all these `Token`s we'll use the [`process!`](macro.process!) `macro`. This `macro`
//! defines the `process` method on the `Parser` which works by defining a set of methods, called
//! matchers, that pattern match against a set of `Token`s from the front of the queue, calling
//! themselves recursively until everything matched and returned its result.
//! defines matcher methods on the `Parser` that pattern match against a set of `Token`s from the
//! front of the queue, calling themselves recursively until everything matched and returned its
//! result.
//!
//! Let's start by defining the signature of the `main` matcher which gets called by default. We
//! Let's start by defining the signature of the `compute` matcher that will do the computation. We
//! need it to return an `i32` in the end.
//!
//! ```ignore
//! main(&self) -> i32
//! compute(&self) -> i32
//! ```
//!
//! Now all we need to do is to write the three cases of interest, namely `number`, `addition`, and
Expand All @@ -490,14 +490,14 @@
//! * inside the block match `sign` and return the appropriate result
//!
//! ```ignore
//! (_: addition, left: main(), sign, right: main()) => {
//! (_: addition, left: compute(), sign, right: compute()) => {
//! match sign.rule {
//! Rule::plus => left + right,
//! Rule::minus => left - right,
//! _ => unreachable!()
//! }
//! },
//! (_: multiplication, left: main(), sign, right: main()) => {
//! (_: multiplication, left: compute(), sign, right: compute()) => {
//! match sign.rule {
//! Rule::times => left * right,
//! Rule::slash => left / right,
Expand Down Expand Up @@ -537,18 +537,18 @@
//! }
//!
//! process! {
//! main(&self) -> i32 {
//! compute(&self) -> i32 {
//! (&number: number) => {
//! number.parse::<i32>().unwrap()
//! },
//! (_: addition, left: main(), sign, right: main()) => {
//! (_: addition, left: compute(), sign, right: compute()) => {
//! match sign.rule {
//! Rule::plus => left + right,
//! Rule::minus => left - right,
//! _ => unreachable!()
//! }
//! },
//! (_: multiplication, left: main(), sign, right: main()) => {
//! (_: multiplication, left: compute(), sign, right: compute()) => {
//! match sign.rule {
//! Rule::times => left * right,
//! Rule::slash => left / right,
Expand All @@ -562,7 +562,7 @@
//! let mut parser = Rdp::new(StringInput::new("(3 + (9 + 3 * 4 + (3 + 1) / 2 - 4)) * 2"));
//!
//! assert!(parser.expression());
//! assert_eq!(parser.process(), 44);
//! assert_eq!(parser.compute(), 44);
//! # }
//! ```

Expand Down
32 changes: 13 additions & 19 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use super::Input;

/// A `trait` that defines a parser.
pub trait Parser<'a> {
pub trait Parser<'a, T: Input<'a>> {
type Rule;
type Token;

/// Matches `string`, returns whether it matched, and advances a parser with `string.len()` in
/// case it did.
fn match_string(&mut self, string: &str) -> bool;
fn input(&self) -> &T;

/// Matches `char` between `left` and `right`, and advances a parser with one `char` in case
/// it did.
fn match_range(&mut self, left: char, right: char) -> bool;
fn input_mut(&mut self) -> &mut T;

/// Tries to match `rule`, returns whether it matched, and advances a parser with in case it
/// did. If `revert` is `true`, the parser will not advance.
Expand All @@ -30,18 +28,17 @@ pub trait Parser<'a> {
/// was not silented) along with its precedence and right-associativity, or `None` if no
/// operator passes. This operator triplet is also returned by the function when it greedily
/// parses an operator useful for a higher precedence.
fn prec_climb<F, G>(&mut self, pos: usize, left: usize, min_prec: u8,
last_op: Option<(Option<Self::Rule>, u8, bool)>, primary: &mut F,
climb: &mut G) -> (Option<(Option<Self::Rule>, u8, bool)>, Option<usize>)
fn prec_climb<F, G>(&mut self,
pos: usize,
left: usize,
min_prec: u8,
last_op: Option<(Option<Self::Rule>, u8, bool)>,
primary: &mut F,
climb: &mut G)
-> (Option<(Option<Self::Rule>, u8, bool)>, Option<usize>)
where F: FnMut(&mut Self) -> bool,
G: FnMut(&mut Self) -> Option<(Option<Self::Rule>, u8, bool)>;

/// Returns the current position of a `Parser`.
fn pos(&self) -> usize;

/// Sets the position of a `Parser`.
fn set_pos(&mut self, pos: usize);

/// Returns whether a `Parser` has reached its end.
fn end(&self) -> bool;

Expand All @@ -51,9 +48,6 @@ pub trait Parser<'a> {
/// Reset a `Parser`.
fn reset(&mut self);

/// Slices a `Parser`'s `Input`.
fn slice_input(&self, start: usize, end: usize) -> &'a str;

/// Returns the queue of all matched `Token`s.
fn queue(&self) -> &Vec<Self::Token>;

Expand Down

0 comments on commit 47f074a

Please sign in to comment.