<commit_before>use lr1::core::*;
use grammar::repr::*;
use petgraph::{EdgeDirection, Graph};
use petgraph::graph::{Edges, NodeIndex};
use std::fmt::{Debug, Formatter, Error};
use util::{Map, map};

#[cfg(test)] mod test;

/// Trace graphs are used to summarize how it is that we came to be in
/// a state where we can take some particular shift/reduce action; put
/// another way, how it is that we came to be in a state with some
/// particular LR(1) item.
///
/// The nodes in the graph are each labeled with a TraceGraphNode and
/// hence take one of two forms:
///
/// - TraceGraphNode::Item -- represents an LR0 item. These nodes are
///   used for the starting/end points in the graph only.  Basically a
///   complete trace stretches from the start item to some end item,
///   and all intermediate nodes are nonterminals.
/// - TraceGraphNode::Nonterminal -- if this graph is for a shift,
///   then these represent items where the cursor is at the beginning:
///   `X = (*) ...`. If the graph is for a reduce, they represent
///   items where a reduce is possible without shifting any more
///   terminals (though further reductions may be needed): `X =
///   ... (*) ...s` where `FIRST(...s)` includes `\epsilon`.
///
/// The edges in the graph are also important. They are labeled with
/// `SymbolSets` instances, meaning that each carries a (prefix,
/// cursor, and suffix) tuple. The label on an edge `A -> B` means
/// that transitioning from a state containing `A` to a state
/// containing `B` is possible if you:
///
/// - shift the symbols in `prefix`
/// - `B` will produce the symbol in `cursor`
/// - shift the symbols in `suffix` after `B` is popped
pub struct TraceGraph<'grammar> {
    // A -L-> B means:
    //
    //     Transition from a state containing A to a state containing
    //     B by (pushing|popping) the symbols L.
    //
    // If this trace graph represents a shift backtrace, then the
    // labels are symbols that are pushed. Otherwise they are labels
    // that are popped.
    graph: Graph<TraceGraphNode<'grammar>, SymbolSets<'grammar>>,
    indices: Map<TraceGraphNode<'grammar>, NodeIndex>,
}

#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum TraceGraphNode<'grammar> {
    Nonterminal(NonterminalString),
    Item(LR0Item<'grammar>),
}

impl<'grammar> TraceGraph<'grammar> {
    pub fn new() -> TraceGraph<'grammar> {
        TraceGraph {
            graph: Graph::new(),
            indices: map(),
        }
    }

    pub fn add_node<T>(&mut self, node: T) -> NodeIndex
        where T: Into<TraceGraphNode<'grammar>>
    {
        let node = node.into();
        let graph = &mut self.graph;
        *self.indices.entry(node)
                     .or_insert_with(|| graph.add_node(node))
    }

    pub fn add_edge<F,T>(&mut self,
                         from: F,
                         to: T,
                         labels: SymbolSets<'grammar>)
        where F: Into<TraceGraphNode<'grammar>>,
              T: Into<TraceGraphNode<'grammar>>,
    {
        let from = self.add_node(from.into());
        let to = self.add_node(to.into());
        println!("add_edge({:?} -{:?}-> {:?})",
                 self.graph[from], labels, self.graph[to]);
        if !self.graph.edges_directed(from, EdgeDirection::Outgoing)
                      .any(|(t, &l)| t == to && l == labels)
        {
            self.graph.add_edge(from, to, labels);
        }
    }

    pub fn enumerate_paths_from<'graph>(&'graph self,
                                        lr0_item: LR0Item<'grammar>)
                                        -> PathEnumerator<'graph, 'grammar>
    {
        PathEnumerator::new(self, lr0_item)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for NonterminalString {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Nonterminal(self)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for LR0Item<'grammar> {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Item(self)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for Item<'grammar> {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Item(self.to_lr0())
    }
}

// This just exists to help with the `Debug` impl
struct TraceGraphEdge<'grammar> {
    from: TraceGraphNode<'grammar>,
    to: TraceGraphNode<'grammar>,
    label: (&'grammar [Symbol], Option<&'grammar Symbol>, &'grammar [Symbol]),
}

impl<'grammar> Debug for TraceGraphEdge<'grammar> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "({:?} -{:?}-> {:?})", self.from, self.label, self.to)
    }
}

impl<'grammar> Debug for TraceGraph<'grammar> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let mut s = fmt.debug_list();
        for (&node, &index) in &self.indices {
            for (target, label) in
                self.graph.edges_directed(index, EdgeDirection::Outgoing)
            {
                s.entry(&TraceGraphEdge { from: node,
                                          to: self.graph[target],
                                          label: (label.prefix,
                                                  label.cursor,
                                                  label.suffix) });
            }
        }
        s.finish()
    }
}

///////////////////////////////////////////////////////////////////////////
// PathEnumerator
//
// The path enumerater walks a trace graph searching for paths that
// start at a given item and terminate at another item. If such a path
// is found, you can then find the complete list of symbols by calling
// `symbols_and_cursor` and also get access to the state.

pub struct PathEnumerator<'graph, 'grammar: 'graph> {
    graph: &'graph TraceGraph<'grammar>,
    stack: Vec<EnumeratorState<'graph, 'grammar>>,

    // The list of symbols for the current item.
    symbols: Vec<Symbol>,

    cursor: usize,
}

struct EnumeratorState<'graph, 'grammar: 'graph> {
    index: NodeIndex,
    symbol_sets: SymbolSets<'grammar>,
    edges: Edges<'graph, SymbolSets<'grammar>>,
}

impl<'graph, 'grammar> PathEnumerator<'graph, 'grammar> {
    fn new(graph: &'graph TraceGraph<'grammar>,
           lr0_item: LR0Item<'grammar>)
           -> Self {
        let start_state = graph.indices[&TraceGraphNode::Item(lr0_item)];
        let mut enumerator = PathEnumerator {
            graph: graph,
            stack: vec![],
            symbols: vec![],
            cursor: 0,
        };
        let edges = enumerator.incoming_edges(start_state);
        enumerator.stack.push(EnumeratorState {
            index: start_state,
            symbol_sets: SymbolSets::new(),
            edges: edges,
        });
        enumerator.find_next_trace();
        enumerator
    }

    /// Advance to the next example. Returns false if there are no more
    /// examples.
    pub fn advance(&mut self) -> bool {
        // while advancing, we keep the symbols reversed so that we
        // can push onto the back rather than inserting in the front
        self.find_next_trace()
    }

    fn incoming_edges(&self, index: NodeIndex) -> Edges<'graph, SymbolSets<'grammar>> {
        self.graph.graph.edges_directed(index, EdgeDirection::Incoming)
    }

    /// This is the main operation, written in CPS style and hence it
    /// can seem a bit confusing. The idea is that `find_next_trace`
    /// is called when we are ready to consider the next child of
    /// whatever is on the top of the stack. It simply withdraws
    /// that next child (if any) and hands it to `push_next`.
    fn find_next_trace(&mut self) -> bool {
        println!("proceed()");
        if !self.stack.is_empty() {
            let next_edge = {
                let top_of_stack = self.stack.last_mut().unwrap();
                top_of_stack.edges.next()
            };
            self.push_next_child_if_any(next_edge)
        } else {
            false
        }
    }

    /// Invoked with the next child (if any) of the node on the top of
    /// the stack.
    ///
    /// If `next` is `Some`, we simply call `push_next_child`.
    ///
    /// If `next` is `None`, then the node on the top of
    /// the stack *has* no next child, and so it is popped, and then
    /// we call `find_next_trace` again to start with the next child
    /// of the new top of the stack.
    fn push_next_child_if_any(&mut self,
                              next: Option<(NodeIndex, &'graph SymbolSets<'grammar>)>)
                              -> bool {
        if let Some((index, &symbol_sets)) = next {
            self.push_next_child(index, symbol_sets)
        } else {
            self.stack.pop();
            self.find_next_trace()
        }
    }

    /// Push the next child of the top of the stack onto the stack,
    /// making the child the new top.
    ///
    /// If the child is an `Item` node, we have found the next trace,
    /// and hence our search terminates. We push the symbols from this
    /// item node into the symbols vector and then call `found_trace`
    /// (which will ultimately return `true`).
    ///
    /// Otherwise, we check whether this new node would cause a cycle.
    /// If so, we do *not* push it, and instead just call
    /// `find_next_trace` again to proceed to the next child of the
    /// current top.
    ///
    /// Finally, if the new node would NOT cause a cycle, then we can
    /// push it onto the stack so that it becomes the new top, and
    /// call `find_next_trace` to start searching its children.
    fn push_next_child(&mut self,
                       index: NodeIndex,
                       symbol_sets: SymbolSets<'grammar>)
                       -> bool {
        println!("push(index={:?}, symbol_sets={:?}",
                 self.graph.graph[index], symbol_sets);

        match self.graph.graph[index] {
            TraceGraphNode::Item(item) => {
                // If we reached an item like
                //
                //     X = ...p (*) ...s
                //
                // then we are done, but we still need to push on the
                // symbols `...p`.
                self.found_trace(item, symbol_sets)
            }
            TraceGraphNode::Nonterminal(_) => {
                // If this node already appears on the stack, do not
                // visit its children.
                if !self.stack.iter().any(|state| state.index == index) {
                    let edges = self.incoming_edges(index);
                    self.stack.push(EnumeratorState {
                        index: index,
                        symbol_sets: symbol_sets,
                        edges: edges,
                    });
                }
                self.find_next_trace()
            }
        }
    }

    /// In between iterations, we keep the symbols in reverse order so
    /// that people can read from them.
    fn found_trace(&mut self,
                   item: LR0Item<'grammar>,
                   item_sets: SymbolSets<'grammar>)
                   -> bool {
        println!("found_trace(item={:?})", item);

        self.symbols.truncate(0);

        self.symbols.extend(item_sets.prefix);

        self.symbols.extend(
            self.stack.iter()
                      .rev()
                      .flat_map(|s| s.symbol_sets.prefix));

        self.cursor = self.symbols.len();

        self.symbols.extend(
            self.stack[1].symbol_sets.cursor);

        self.symbols.extend(
            self.stack.iter()
                      .flat_map(|s| s.symbol_sets.suffix));

        self.symbols.extend(item_sets.suffix);

        println!("found_trace: symbols={:?} cursor={:?}",
                 self.symbols, self.cursor);
        true
    }

    /// Return the symbols of the current trace, or None if there is
    /// no current trace.
    pub fn symbols_and_cursor(&self) -> Option<(&[Symbol], usize)> {
        if self.stack.is_empty() {
            None
        } else {
            Some((&self.symbols[..], self.cursor))
        }
    }

    fn stack(&self) -> &[EnumeratorState<'graph, 'grammar>] {
        &self.stack
    }
}

impl<'graph, 'grammar> Iterator for PathEnumerator<'graph, 'grammar> {
    type Item = (Vec<Symbol>, usize);

    fn next(&mut self) -> Option<Self::Item> {
        let this =
            self.symbols_and_cursor()
                .map(|(symbols, cursor)| (symbols.to_vec(), cursor));
        self.advance();
        this
    }
}

///////////////////////////////////////////////////////////////////////////
// ExampleEnumerator
//
// Wraps a path enumerater and builds examples.
//
//pub struct ExampleEnumerator<'graph, 'grammar: 'graph> {
//    paths: PathEnumerator<'graph, 'grammar>,
//}
//
//impl<'graph, 'grammar> Iterator for PathEnumerator<'graph, 'grammar> {
//    type Item = (Vec<Symbol>, usize);
//
//    fn next(&mut self) -> Option<Self::Item> {
//        let this =
//            self.paths
//                .symbols_and_cursor()
//                .map(|(symbols, cursor)| {
//                    // The bottom of the path enumerator stack (index
//                    // 0) is the starting item, but all the other
//                    // entries are nonterminal intermediate nodes that
//                    // represent reductions. Convert those into the
//                    // reductions vector.
//                    let reductions =
//                        self.paths
//                            .stack()
//                            .iter()
//                            .skip(1)
//                            .map(|stack_elem| {
//                                Reduction
//                            });
//
//                    Example {
//                        symbols: symbols.to_vec(),
//                        cursor: cursor,
//                        reductions:
//                    }
//                });
//
//        self.paths.advance();
//        this
//    }
//}
<commit_msg>Make trace graph iter push target node on stack<commit_after>use lr1::core::*;
use grammar::repr::*;
use petgraph::{EdgeDirection, Graph};
use petgraph::graph::{Edges, NodeIndex};
use std::fmt::{Debug, Formatter, Error};
use util::{Map, map};

#[cfg(test)] mod test;

/// Trace graphs are used to summarize how it is that we came to be in
/// a state where we can take some particular shift/reduce action; put
/// another way, how it is that we came to be in a state with some
/// particular LR(1) item.
///
/// The nodes in the graph are each labeled with a TraceGraphNode and
/// hence take one of two forms:
///
/// - TraceGraphNode::Item -- represents an LR0 item. These nodes are
///   used for the starting/end points in the graph only.  Basically a
///   complete trace stretches from the start item to some end item,
///   and all intermediate nodes are nonterminals.
/// - TraceGraphNode::Nonterminal -- if this graph is for a shift,
///   then these represent items where the cursor is at the beginning:
///   `X = (*) ...`. If the graph is for a reduce, they represent
///   items where a reduce is possible without shifting any more
///   terminals (though further reductions may be needed): `X =
///   ... (*) ...s` where `FIRST(...s)` includes `\epsilon`.
///
/// The edges in the graph are also important. They are labeled with
/// `SymbolSets` instances, meaning that each carries a (prefix,
/// cursor, and suffix) tuple. The label on an edge `A -> B` means
/// that transitioning from a state containing `A` to a state
/// containing `B` is possible if you:
///
/// - shift the symbols in `prefix`
/// - `B` will produce the symbol in `cursor`
/// - shift the symbols in `suffix` after `B` is popped
pub struct TraceGraph<'grammar> {
    // A -L-> B means:
    //
    //     Transition from a state containing A to a state containing
    //     B by (pushing|popping) the symbols L.
    //
    // If this trace graph represents a shift backtrace, then the
    // labels are symbols that are pushed. Otherwise they are labels
    // that are popped.
    graph: Graph<TraceGraphNode<'grammar>, SymbolSets<'grammar>>,
    indices: Map<TraceGraphNode<'grammar>, NodeIndex>,
}

#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum TraceGraphNode<'grammar> {
    Nonterminal(NonterminalString),
    Item(LR0Item<'grammar>),
}

impl<'grammar> TraceGraph<'grammar> {
    pub fn new() -> TraceGraph<'grammar> {
        TraceGraph {
            graph: Graph::new(),
            indices: map(),
        }
    }

    pub fn add_node<T>(&mut self, node: T) -> NodeIndex
        where T: Into<TraceGraphNode<'grammar>>
    {
        let node = node.into();
        let graph = &mut self.graph;
        *self.indices.entry(node)
                     .or_insert_with(|| graph.add_node(node))
    }

    pub fn add_edge<F,T>(&mut self,
                         from: F,
                         to: T,
                         labels: SymbolSets<'grammar>)
        where F: Into<TraceGraphNode<'grammar>>,
              T: Into<TraceGraphNode<'grammar>>,
    {
        let from = self.add_node(from.into());
        let to = self.add_node(to.into());
        println!("add_edge({:?} -{:?}-> {:?})",
                 self.graph[from], labels, self.graph[to]);
        if !self.graph.edges_directed(from, EdgeDirection::Outgoing)
                      .any(|(t, &l)| t == to && l == labels)
        {
            self.graph.add_edge(from, to, labels);
        }
    }

    pub fn enumerate_paths_from<'graph>(&'graph self,
                                        lr0_item: LR0Item<'grammar>)
                                        -> PathEnumerator<'graph, 'grammar>
    {
        PathEnumerator::new(self, lr0_item)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for NonterminalString {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Nonterminal(self)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for LR0Item<'grammar> {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Item(self)
    }
}

impl<'grammar> Into<TraceGraphNode<'grammar>> for Item<'grammar> {
    fn into(self) -> TraceGraphNode<'grammar> {
        TraceGraphNode::Item(self.to_lr0())
    }
}

// This just exists to help with the `Debug` impl
struct TraceGraphEdge<'grammar> {
    from: TraceGraphNode<'grammar>,
    to: TraceGraphNode<'grammar>,
    label: (&'grammar [Symbol], Option<&'grammar Symbol>, &'grammar [Symbol]),
}

impl<'grammar> Debug for TraceGraphEdge<'grammar> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "({:?} -{:?}-> {:?})", self.from, self.label, self.to)
    }
}

impl<'grammar> Debug for TraceGraph<'grammar> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let mut s = fmt.debug_list();
        for (&node, &index) in &self.indices {
            for (target, label) in
                self.graph.edges_directed(index, EdgeDirection::Outgoing)
            {
                s.entry(&TraceGraphEdge { from: node,
                                          to: self.graph[target],
                                          label: (label.prefix,
                                                  label.cursor,
                                                  label.suffix) });
            }
        }
        s.finish()
    }
}

///////////////////////////////////////////////////////////////////////////
// PathEnumerator
//
// The path enumerater walks a trace graph searching for paths that
// start at a given item and terminate at another item. If such a path
// is found, you can then find the complete list of symbols by calling
// `symbols_and_cursor` and also get access to the state.

pub struct PathEnumerator<'graph, 'grammar: 'graph> {
    graph: &'graph TraceGraph<'grammar>,
    stack: Vec<EnumeratorState<'graph, 'grammar>>,

    // The list of symbols for the current item.
    symbols: Vec<Symbol>,

    cursor: usize,
}

struct EnumeratorState<'graph, 'grammar: 'graph> {
    index: NodeIndex,
    symbol_sets: SymbolSets<'grammar>,
    edges: Edges<'graph, SymbolSets<'grammar>>,
}

impl<'graph, 'grammar> PathEnumerator<'graph, 'grammar> {
    fn new(graph: &'graph TraceGraph<'grammar>,
           lr0_item: LR0Item<'grammar>)
           -> Self {
        let start_state = graph.indices[&TraceGraphNode::Item(lr0_item)];
        let mut enumerator = PathEnumerator {
            graph: graph,
            stack: vec![],
            symbols: vec![],
            cursor: 0,
        };
        let edges = enumerator.incoming_edges(start_state);
        enumerator.stack.push(EnumeratorState {
            index: start_state,
            symbol_sets: SymbolSets::new(),
            edges: edges,
        });
        enumerator.find_next_trace();
        enumerator
    }

    /// Advance to the next example. Returns false if there are no more
    /// examples.
    pub fn advance(&mut self) -> bool {
        // If we have not yet exhausted all the examples, then the top
        // of the stack should be the last target item that we
        // found. Pop it off.
        match self.stack.pop() {
            Some(top_state) => {
                assert!(match self.graph.graph[top_state.index] {
                    TraceGraphNode::Item(_) => true,
                    TraceGraphNode::Nonterminal(_) => false,
                });

                self.find_next_trace()
            }
            None => {
                false
            }
        }
    }

    fn incoming_edges(&self, index: NodeIndex) -> Edges<'graph, SymbolSets<'grammar>> {
        self.graph.graph.edges_directed(index, EdgeDirection::Incoming)
    }

    /// This is the main operation, written in CPS style and hence it
    /// can seem a bit confusing. The idea is that `find_next_trace`
    /// is called when we are ready to consider the next child of
    /// whatever is on the top of the stack. It simply withdraws
    /// that next child (if any) and hands it to `push_next`.
    fn find_next_trace(&mut self) -> bool {
        println!("proceed()");
        if !self.stack.is_empty() {
            let next_edge = {
                let top_of_stack = self.stack.last_mut().unwrap();
                top_of_stack.edges.next()
            };
            self.push_next_child_if_any(next_edge)
        } else {
            false
        }
    }

    /// Invoked with the next child (if any) of the node on the top of
    /// the stack.
    ///
    /// If `next` is `Some`, we simply call `push_next_child`.
    ///
    /// If `next` is `None`, then the node on the top of
    /// the stack *has* no next child, and so it is popped, and then
    /// we call `find_next_trace` again to start with the next child
    /// of the new top of the stack.
    fn push_next_child_if_any(&mut self,
                              next: Option<(NodeIndex, &'graph SymbolSets<'grammar>)>)
                              -> bool {
        if let Some((index, &symbol_sets)) = next {
            self.push_next_child(index, symbol_sets)
        } else {
            self.stack.pop();
            self.find_next_trace()
        }
    }

    /// Push the next child of the top of the stack onto the stack,
    /// making the child the new top.
    ///
    /// If the child is an `Item` node, we have found the next trace,
    /// and hence our search terminates. We push the symbols from this
    /// item node into the symbols vector and then call `found_trace`
    /// (which will ultimately return `true`).
    ///
    /// Otherwise, we check whether this new node would cause a cycle.
    /// If so, we do *not* push it, and instead just call
    /// `find_next_trace` again to proceed to the next child of the
    /// current top.
    ///
    /// Finally, if the new node would NOT cause a cycle, then we can
    /// push it onto the stack so that it becomes the new top, and
    /// call `find_next_trace` to start searching its children.
    fn push_next_child(&mut self,
                       index: NodeIndex,
                       symbol_sets: SymbolSets<'grammar>)
                       -> bool {
        println!("push(index={:?}, symbol_sets={:?}",
                 self.graph.graph[index], symbol_sets);

        match self.graph.graph[index] {
            TraceGraphNode::Item(_) => {
                // If we reached an item like
                //
                //     X = ...p (*) ...s
                //
                // then we are done, but we still need to push on the
                // symbols `...p`.
                let edges = self.incoming_edges(index);
                self.stack.push(EnumeratorState {
                    index: index,
                    symbol_sets: symbol_sets,
                    edges: edges,
                });
                self.found_trace()
            }
            TraceGraphNode::Nonterminal(_) => {
                // If this node already appears on the stack, do not
                // visit its children.
                if !self.stack.iter().any(|state| state.index == index) {
                    let edges = self.incoming_edges(index);
                    self.stack.push(EnumeratorState {
                        index: index,
                        symbol_sets: symbol_sets,
                        edges: edges,
                    });
                }
                self.find_next_trace()
            }
        }
    }

    // Assemble the `symbols` vector and `cursor`
    fn found_trace(&mut self)
                   -> bool {
        println!("found_trace()");

        self.symbols.truncate(0);

        self.symbols.extend(
            self.stack.iter()
                      .rev()
                      .flat_map(|s| s.symbol_sets.prefix));

        self.cursor = self.symbols.len();

        self.symbols.extend(
            self.stack[1].symbol_sets.cursor);

        self.symbols.extend(
            self.stack.iter()
                      .flat_map(|s| s.symbol_sets.suffix));

        println!("found_trace: symbols={:?} cursor={:?}",
                 self.symbols, self.cursor);
        true
    }

    /// Return the symbols of the current trace, or None if there is
    /// no current trace.
    pub fn symbols_and_cursor(&self) -> Option<(&[Symbol], usize)> {
        if self.stack.is_empty() {
            None
        } else {
            Some((&self.symbols[..], self.cursor))
        }
    }

    fn stack(&self) -> &[EnumeratorState<'graph, 'grammar>] {
        &self.stack
    }
}

impl<'graph, 'grammar> Iterator for PathEnumerator<'graph, 'grammar> {
    type Item = (Vec<Symbol>, usize);

    fn next(&mut self) -> Option<Self::Item> {
        let this =
            self.symbols_and_cursor()
                .map(|(symbols, cursor)| (symbols.to_vec(), cursor));
        self.advance();
        this
    }
}

///////////////////////////////////////////////////////////////////////////
// ExampleEnumerator
//
// Wraps a path enumerater and builds examples.
//
//pub struct ExampleEnumerator<'graph, 'grammar: 'graph> {
//    paths: PathEnumerator<'graph, 'grammar>,
//}
//
//impl<'graph, 'grammar> Iterator for PathEnumerator<'graph, 'grammar> {
//    type Item = (Vec<Symbol>, usize);
//
//    fn next(&mut self) -> Option<Self::Item> {
//        let this =
//            self.paths
//                .symbols_and_cursor()
//                .map(|(symbols, cursor)| {
//                    // The bottom of the path enumerator stack (index
//                    // 0) is the starting item, but all the other
//                    // entries are nonterminal intermediate nodes that
//                    // represent reductions. Convert those into the
//                    // reductions vector.
//                    let reductions =
//                        self.paths
//                            .stack()
//                            .iter()
//                            .skip(1)
//                            .map(|stack_elem| {
//                                Reduction
//                            });
//
//                    Example {
//                        symbols: symbols.to_vec(),
//                        cursor: cursor,
//                        reductions:
//                    }
//                });
//
//        self.paths.advance();
//        this
//    }
//}
<|endoftext|>


<commit_before>extern crate serde_json;
extern crate regex;

pub mod common;
pub mod did;
pub mod pool;
pub mod wallet;
pub mod ledger;
pub mod payment_address;

use self::regex::Regex;

use command_executor::{CommandContext, CommandParams};

use std;

pub fn get_str_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<&'a str, ()> {
    match params.get(name) {
        Some(v) if v == "" => {
            println_err!("Required \"{}\" parameter is empty.", name);
            Err(())
        }
        Some(v) => Ok(v.as_str()),
        None => {
            println_err!("No required \"{}\" parameter present.", name);
            Err(())
        }
    }
}

pub fn get_opt_str_param<'a>(key: &'a str, params: &'a CommandParams) -> Result<Option<&'a str>, ()> {
    match params.get(key) {
        Some(v) if v == "" => {
            println_err!("Optional parameter \"{}\" is empty.", key);
            Err(())
        }
        Some(v) => Ok(Some(v.as_str())),
        None => Ok(None)
    }
}

pub fn get_opt_empty_str_param<'a>(key: &'a str, params: &'a CommandParams) -> Result<Option<&'a str>, ()> {
    Ok(params.get(key).map(|v| v.as_str()))
}

pub fn _get_int_param<T>(name: &str, params: &CommandParams) -> Result<T, ()>
    where T: std::str::FromStr, <T as std::str::FromStr>::Err: std::fmt::Display {
    match params.get(name) {
        Some(v) => {
            Ok(v.parse::<T>().map_err(|err|
                println_err!("Can't parse integer parameter \"{}\": err {}", name, err))?)
        }
        None => {
            println_err!("No required \"{}\" parameter present", name);
            Err(())
        }
    }
}

pub fn get_opt_number_param<T>(key: &str, params: &CommandParams) -> Result<Option<T>, ()>
    where T: std::str::FromStr, <T as std::str::FromStr>::Err: std::fmt::Display {
    let res = match params.get(key) {
        Some(value) => Some(value.parse::<T>().map_err(|err|
            println_err!("Can't parse integer parameter \"{}\": err {}", key, err))?),
        None => None
    };
    Ok(res)
}

pub fn get_bool_param(key: &str, params: &CommandParams) -> Result<bool, ()> {
    match params.get(key) {
        Some(value) => Ok(value.parse::<bool>().map_err(|err|
            println_err!("Can't parse bool parameter \"{}\": err {}", key, err))?),
        None => {
            println_err!("No required \"{}\" parameter present", key);
            Err(())
        }
    }
}

pub fn get_opt_bool_param(key: &str, params: &CommandParams) -> Result<Option<bool>, ()> {
    match params.get(key) {
        Some(value) => Ok(Some(value.parse::<bool>().map_err(|err|
            println_err!("Can't parse bool parameter \"{}\": err {}", key, err))?)),
        None => Ok(None)
    }
}

pub fn get_str_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Vec<&'a str>, ()> {
    match params.get(name) {
        None => Err(println_err!("No required \"{}\" parameter present", name)),
        Some(v) if v.is_empty() => Err(println_err!("No required \"{}\" parameter present", name)),
        Some(v) => Ok(v.split(",").collect::<Vec<&'a str>>())
    }
}

pub fn get_opt_str_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Option<Vec<&'a str>>, ()> {
    match params.get(name) {
        Some(v) =>
            if v.is_empty() {
                Ok(Some(Vec::<&'a str>::new()))
            } else {
                Ok(Some(v.split(",").collect::<Vec<&'a str>>()))
            },
        None => Ok(None)
    }
}

pub fn get_object_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<serde_json::Value, ()> {
    match params.get(name) {
        Some(v) => Ok(serde_json::from_str(v).map_err(|err|
            println_err!("Can't parse object parameter \"{}\": err {}", name, err))?),
        None => {
            println_err!("No required \"{}\" parameter present", name);
            Err(())
        }
    }
}

fn extract_array_tuples<'a>(param: &'a str) -> Vec<String> {
    let re = Regex::new(r#"\(([\w\d:;\-_, ]+)\),?"#).unwrap();
    re.captures_iter(param).map(|c| c[1].to_string()).collect::<Vec<String>>()
}

pub fn get_str_tuple_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Vec<String>, ()> {
    match params.get(name) {
        Some(v) => Ok(extract_array_tuples(v)),
        None => Err(println_err!("No required \"{}\" parameter present", name))
    }
}

pub fn get_opt_str_tuple_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Option<Vec<String>>, ()> {
    match params.get(name) {
        Some(v) =>
            if v.is_empty() {
                Ok(Some(Vec::<String>::new()))
            } else {
                Ok(Some(extract_array_tuples(v)))
            },
        None => Ok(None)
    }
}

pub fn ensure_active_did(ctx: &CommandContext) -> Result<String, ()> {
    match ctx.get_string_value("ACTIVE_DID") {
        Some(did) => Ok(did),
        None => Err(println_err!("There is no active did"))
    }
}

pub fn get_active_did(ctx: &CommandContext) -> Option<String> {
    ctx.get_string_value("ACTIVE_DID")
}

pub fn set_active_did(ctx: &CommandContext, did: Option<String>) {
    ctx.set_string_value("ACTIVE_DID", did.clone());
    ctx.set_sub_prompt(3, did.map(|did| format!("did({}...{})", &did[..3], &did[did.len() - 3..])));
}

pub fn ensure_opened_wallet_handle(ctx: &CommandContext) -> Result<i32, ()> {
    match ctx.get_int_value("OPENED_WALLET_HANDLE") {
        Some(wallet_handle) => Ok(wallet_handle),
        None => Err(println_err!("There is no opened wallet now"))
    }
}

pub fn ensure_opened_wallet(ctx: &CommandContext) -> Result<(i32, String), ()> {
    let handle = ctx.get_int_value("OPENED_WALLET_HANDLE");
    let name = ctx.get_string_value("OPENED_WALLET_NAME");

    match (handle, name) {
        (Some(handle), Some(name)) => Ok((handle, name)),
        _ => Err(println_err!("There is no opened wallet now"))
    }
}

pub fn get_opened_wallet(ctx: &CommandContext) -> Option<(i32, String)> {
    let handle = ctx.get_int_value("OPENED_WALLET_HANDLE");
    let name = ctx.get_string_value("OPENED_WALLET_NAME");

    if let (Some(handle), Some(name)) = (handle, name) {
        Some((handle, name))
    } else {
        None
    }
}

pub fn set_opened_wallet(ctx: &CommandContext, value: Option<(i32, String)>) {
    ctx.set_int_value("OPENED_WALLET_HANDLE", value.as_ref().map(|value| value.0.to_owned()));
    ctx.set_string_value("OPENED_WALLET_NAME", value.as_ref().map(|value| value.1.to_owned()));
    ctx.set_sub_prompt(2, value.map(|value| format!("wallet({})", value.1)));
}

pub fn ensure_connected_pool_handle(ctx: &CommandContext) -> Result<i32, ()> {
    match ctx.get_int_value("CONNECTED_POOL_HANDLE") {
        Some(pool_handle) => Ok(pool_handle),
        None => Err(println_err!("There is no opened pool now"))
    }
}

pub fn ensure_connected_pool(ctx: &CommandContext) -> Result<(i32, String), ()> {
    let handle = ctx.get_int_value("CONNECTED_POOL_HANDLE");
    let name = ctx.get_string_value("CONNECTED_POOL_NAME");

    match (handle, name) {
        (Some(handle), Some(name)) => Ok((handle, name)),
        _ => Err(println_err!("There is no opened pool now"))
    }
}

pub fn get_connected_pool(ctx: &CommandContext) -> Option<(i32, String)> {
    let handle = ctx.get_int_value("CONNECTED_POOL_HANDLE");
    let name = ctx.get_string_value("CONNECTED_POOL_NAME");

    if let (Some(handle), Some(name)) = (handle, name) {
        Some((handle, name))
    } else {
        None
    }
}

pub fn set_connected_pool(ctx: &CommandContext, value: Option<(i32, String)>) {
    ctx.set_int_value("CONNECTED_POOL_HANDLE", value.as_ref().map(|value| value.0.to_owned()));
    ctx.set_string_value("CONNECTED_POOL_NAME", value.as_ref().map(|value| value.1.to_owned()));
    ctx.set_sub_prompt(1, value.map(|value| format!("pool({})", value.1)));
}<commit_msg>Corrected outputs parser<commit_after>extern crate serde_json;
extern crate regex;

pub mod common;
pub mod did;
pub mod pool;
pub mod wallet;
pub mod ledger;
pub mod payment_address;

use self::regex::Regex;

use command_executor::{CommandContext, CommandParams};

use std;

pub fn get_str_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<&'a str, ()> {
    match params.get(name) {
        Some(v) if v == "" => {
            println_err!("Required \"{}\" parameter is empty.", name);
            Err(())
        }
        Some(v) => Ok(v.as_str()),
        None => {
            println_err!("No required \"{}\" parameter present.", name);
            Err(())
        }
    }
}

pub fn get_opt_str_param<'a>(key: &'a str, params: &'a CommandParams) -> Result<Option<&'a str>, ()> {
    match params.get(key) {
        Some(v) if v == "" => {
            println_err!("Optional parameter \"{}\" is empty.", key);
            Err(())
        }
        Some(v) => Ok(Some(v.as_str())),
        None => Ok(None)
    }
}

pub fn get_opt_empty_str_param<'a>(key: &'a str, params: &'a CommandParams) -> Result<Option<&'a str>, ()> {
    Ok(params.get(key).map(|v| v.as_str()))
}

pub fn _get_int_param<T>(name: &str, params: &CommandParams) -> Result<T, ()>
    where T: std::str::FromStr, <T as std::str::FromStr>::Err: std::fmt::Display {
    match params.get(name) {
        Some(v) => {
            Ok(v.parse::<T>().map_err(|err|
                println_err!("Can't parse integer parameter \"{}\": err {}", name, err))?)
        }
        None => {
            println_err!("No required \"{}\" parameter present", name);
            Err(())
        }
    }
}

pub fn get_opt_number_param<T>(key: &str, params: &CommandParams) -> Result<Option<T>, ()>
    where T: std::str::FromStr, <T as std::str::FromStr>::Err: std::fmt::Display {
    let res = match params.get(key) {
        Some(value) => Some(value.parse::<T>().map_err(|err|
            println_err!("Can't parse integer parameter \"{}\": err {}", key, err))?),
        None => None
    };
    Ok(res)
}

pub fn get_bool_param(key: &str, params: &CommandParams) -> Result<bool, ()> {
    match params.get(key) {
        Some(value) => Ok(value.parse::<bool>().map_err(|err|
            println_err!("Can't parse bool parameter \"{}\": err {}", key, err))?),
        None => {
            println_err!("No required \"{}\" parameter present", key);
            Err(())
        }
    }
}

pub fn get_opt_bool_param(key: &str, params: &CommandParams) -> Result<Option<bool>, ()> {
    match params.get(key) {
        Some(value) => Ok(Some(value.parse::<bool>().map_err(|err|
            println_err!("Can't parse bool parameter \"{}\": err {}", key, err))?)),
        None => Ok(None)
    }
}

pub fn get_str_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Vec<&'a str>, ()> {
    match params.get(name) {
        None => Err(println_err!("No required \"{}\" parameter present", name)),
        Some(v) if v.is_empty() => Err(println_err!("No required \"{}\" parameter present", name)),
        Some(v) => Ok(v.split(",").collect::<Vec<&'a str>>())
    }
}

pub fn get_opt_str_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Option<Vec<&'a str>>, ()> {
    match params.get(name) {
        Some(v) =>
            if v.is_empty() {
                Ok(Some(Vec::<&'a str>::new()))
            } else {
                Ok(Some(v.split(",").collect::<Vec<&'a str>>()))
            },
        None => Ok(None)
    }
}

pub fn get_object_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<serde_json::Value, ()> {
    match params.get(name) {
        Some(v) => Ok(serde_json::from_str(v).map_err(|err|
            println_err!("Can't parse object parameter \"{}\": err {}", name, err))?),
        None => {
            println_err!("No required \"{}\" parameter present", name);
            Err(())
        }
    }
}

fn extract_array_tuples<'a>(param: &'a str) -> Vec<String> {
    let re = Regex::new(r#"\(([^\(\)]+)\),?"#).unwrap();
    re.captures_iter(param).map(|c| c[1].to_string()).collect::<Vec<String>>()
}

pub fn get_str_tuple_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Vec<String>, ()> {
    match params.get(name) {
        Some(v) if !v.is_empty() => {
            let tuples = extract_array_tuples(v);
            if tuples.len() == 0 {
                Err(println_err!("Parameter \"{}\" has invalid format", name))
            } else {
                Ok(tuples)
            }
        }
        _ => Err(println_err!("No required \"{}\" parameter present", name))
    }
}

pub fn get_opt_str_tuple_array_param<'a>(name: &'a str, params: &'a CommandParams) -> Result<Option<Vec<String>>, ()> {
    match params.get(name) {
        Some(v) =>
            if v.is_empty() {
                Ok(Some(Vec::<String>::new()))
            } else {
                Ok(Some(extract_array_tuples(v)))
            },
        None => Ok(None)
    }
}

pub fn ensure_active_did(ctx: &CommandContext) -> Result<String, ()> {
    match ctx.get_string_value("ACTIVE_DID") {
        Some(did) => Ok(did),
        None => Err(println_err!("There is no active did"))
    }
}

pub fn get_active_did(ctx: &CommandContext) -> Option<String> {
    ctx.get_string_value("ACTIVE_DID")
}

pub fn set_active_did(ctx: &CommandContext, did: Option<String>) {
    ctx.set_string_value("ACTIVE_DID", did.clone());
    ctx.set_sub_prompt(3, did.map(|did| format!("did({}...{})", &did[..3], &did[did.len() - 3..])));
}

pub fn ensure_opened_wallet_handle(ctx: &CommandContext) -> Result<i32, ()> {
    match ctx.get_int_value("OPENED_WALLET_HANDLE") {
        Some(wallet_handle) => Ok(wallet_handle),
        None => Err(println_err!("There is no opened wallet now"))
    }
}

pub fn ensure_opened_wallet(ctx: &CommandContext) -> Result<(i32, String), ()> {
    let handle = ctx.get_int_value("OPENED_WALLET_HANDLE");
    let name = ctx.get_string_value("OPENED_WALLET_NAME");

    match (handle, name) {
        (Some(handle), Some(name)) => Ok((handle, name)),
        _ => Err(println_err!("There is no opened wallet now"))
    }
}

pub fn get_opened_wallet(ctx: &CommandContext) -> Option<(i32, String)> {
    let handle = ctx.get_int_value("OPENED_WALLET_HANDLE");
    let name = ctx.get_string_value("OPENED_WALLET_NAME");

    if let (Some(handle), Some(name)) = (handle, name) {
        Some((handle, name))
    } else {
        None
    }
}

pub fn set_opened_wallet(ctx: &CommandContext, value: Option<(i32, String)>) {
    ctx.set_int_value("OPENED_WALLET_HANDLE", value.as_ref().map(|value| value.0.to_owned()));
    ctx.set_string_value("OPENED_WALLET_NAME", value.as_ref().map(|value| value.1.to_owned()));
    ctx.set_sub_prompt(2, value.map(|value| format!("wallet({})", value.1)));
}

pub fn ensure_connected_pool_handle(ctx: &CommandContext) -> Result<i32, ()> {
    match ctx.get_int_value("CONNECTED_POOL_HANDLE") {
        Some(pool_handle) => Ok(pool_handle),
        None => Err(println_err!("There is no opened pool now"))
    }
}

pub fn ensure_connected_pool(ctx: &CommandContext) -> Result<(i32, String), ()> {
    let handle = ctx.get_int_value("CONNECTED_POOL_HANDLE");
    let name = ctx.get_string_value("CONNECTED_POOL_NAME");

    match (handle, name) {
        (Some(handle), Some(name)) => Ok((handle, name)),
        _ => Err(println_err!("There is no opened pool now"))
    }
}

pub fn get_connected_pool(ctx: &CommandContext) -> Option<(i32, String)> {
    let handle = ctx.get_int_value("CONNECTED_POOL_HANDLE");
    let name = ctx.get_string_value("CONNECTED_POOL_NAME");

    if let (Some(handle), Some(name)) = (handle, name) {
        Some((handle, name))
    } else {
        None
    }
}

pub fn set_connected_pool(ctx: &CommandContext, value: Option<(i32, String)>) {
    ctx.set_int_value("CONNECTED_POOL_HANDLE", value.as_ref().map(|value| value.0.to_owned()));
    ctx.set_string_value("CONNECTED_POOL_NAME", value.as_ref().map(|value| value.1.to_owned()));
    ctx.set_sub_prompt(1, value.map(|value| format!("pool({})", value.1)));
}<|endoftext|>


<commit_before>use super::super::error::Result;
use lazy_static::lazy_static;
use regex::Regex;
use tree_sitter::Point;

// TODO: It would be cooler to do this with a comments query rather than with a regex
// directly.
lazy_static! {
    static ref METADATA_PAIR_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+)"#).unwrap();
    static ref NUMBER_REGEX: Regex = Regex::new(r#"\d+"#).unwrap();
}

pub struct CaptureInfo {
    pub name: String,
}

#[derive(Debug, Eq, PartialEq)]
struct Assertion {
    position: Point,
    line_numbers: Vec<usize>,
    capture_type: String,
}

pub fn assert_expected_captures(_captures: Vec<CaptureInfo>, _path: String) -> Result<()> {
    Ok(())
}
<commit_msg>reading in the source correctly<commit_after>use super::super::error::Result;
use lazy_static::lazy_static;
use regex::Regex;
use std::fs;
use tree_sitter::Point;

// TODO: It would be cooler to do this with a comments query rather than with a regex
// directly.
lazy_static! {
    static ref METADATA_PAIR_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+)"#).unwrap();
    static ref NUMBER_REGEX: Regex = Regex::new(r#"\d+"#).unwrap();
}

pub struct CaptureInfo {
    pub name: String,
}

#[derive(Debug, Eq, PartialEq)]
struct Assertion {
    position: Point,
    line_numbers: Vec<usize>,
    capture_type: String,
}

pub fn assert_expected_captures(_captures: Vec<CaptureInfo>, path: String) -> Result<()> {
    let contents = fs::read_to_string(path)?;
    for m in METADATA_PAIR_REGEX.captures_iter(&contents) {
        println!("pair: {:?}", m);
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate rustyard;

use std::env;

fn main() {
    match env::args().nth(1) {
        Some(input) => {
            let mut shunting_yard = rustyard::ShuntingYard::new();

            println!("Input is: {}", input);

            match shunting_yard.calculate(&input[..]) {
                Ok(n) => {
                    println!("Lexer result: {}", shunting_yard.to_string_ast());
                    println!("Shunting Yard result: {}", shunting_yard.to_string());
                    println!("Equation equals: {}", n);
                },
                Err(errors) =>  {
                    for err in errors {
                        println!("ERR: {}", err);
                    }
                }
            }

            match shunting_yard.calculate("4 * 4") {
                Ok(n) => {
                    println!("Lexer result: {}", shunting_yard.to_string_ast());
                    println!("Shunting Yard result: {}", shunting_yard.to_string());
                    println!("Equation equals: {}", n);
                },
                Err(errors) =>  {
                    for err in errors {
                        println!("ERR: {}", err);
                    }
                }
            }
        },
        None => println!("Please supply an expression")
    };
}
<commit_msg>Removed the double up in the main example<commit_after>extern crate rustyard;

use std::env;

fn main() {
    match env::args().nth(1) {
        Some(input) => {
            let mut shunting_yard = rustyard::ShuntingYard::new();

            println!("Input is: {}", input);

            match shunting_yard.calculate(&input[..]) {
                Ok(n) => {
                    println!("Lexer result: {}", shunting_yard.to_string_ast());
                    println!("Shunting Yard result: {}", shunting_yard.to_string());
                    println!("Equation equals: {}", n);
                },
                Err(errors) =>  {
                    for err in errors {
                        println!("ERR: {}", err);
                    }
                }
            }
        },
        None => println!("Please supply an expression")
    };
}
<|endoftext|>


<commit_before>use vqa_parser::audio::CodecState;
use vqa_parser::{form_chunk, snd2_chunk, vqa_header};
use vqa_parser::{SND2Chunk, VQAHeader};

use cpal::traits::{EventLoopTrait, HostTrait};

use nom::bytes::complete::{tag, take_until};
use nom::multi::many0;
use nom::IResult;

use cpal::StreamData;
use std::collections::VecDeque;
use std::fs::File;
use std::io::Read;

fn parse_vqaheader(input: &[u8]) -> IResult<&[u8], VQAHeader> {
    let (input, _) = form_chunk(input)?;
    let (input, _) = tag(b"WVQA")(input)?;
    let (input, vqaheader) = vqa_header(input)?;

    Ok((input, vqaheader))
}

fn next_snd2_chunk(input: &[u8]) -> IResult<&[u8], SND2Chunk> {
    let (input, _) = take_until("SND2")(input)?;
    let (input, chunk) = snd2_chunk(input)?;

    Ok((input, chunk))
}

fn all_snd2_chunks(input: &[u8]) -> IResult<&[u8], Vec<SND2Chunk>> {
    let (input, chunks) = many0(next_snd2_chunk)(input)?;

    Ok((input, chunks))
}

fn main() {
    let mut args = std::env::args();
    if args.len() != 2 {
        println!("usage: {} <vqa file>", args.nth(0).unwrap());
        return;
    }

    let mut input = File::open(args.nth(1).unwrap()).expect("Failed to open file");
    let mut buffer = Vec::new();
    input.read_to_end(&mut buffer).expect("Failed to read file");

    let vqa = parse_vqaheader(&buffer).unwrap().1;
    let snd2_chunks = all_snd2_chunks(&buffer).unwrap().1;

    println!("{:#?}", vqa);
    play_chunks(&snd2_chunks);
}

fn get_samples(chunks: &[SND2Chunk]) -> VecDeque<i16> {
    let mut samples = VecDeque::new();

    let mut ch1_state = CodecState::new();
    let mut ch2_state = CodecState::new();
    for chunk in chunks {
        let left =
            vqa_parser::audio::decompress(&mut ch1_state, &chunk.data[..chunk.data.len() / 2]);
        let right =
            vqa_parser::audio::decompress(&mut ch2_state, &chunk.data[..chunk.data.len() / 2]);

        // interleave data
        for i in 0..left.len() {
            samples.push_back(left[i] as i16);
            samples.push_back(right[i] as i16);
        }
    }

    samples
}

fn play_chunks(chunks: &[SND2Chunk]) {
    let format = cpal::Format {
        channels: 2,
        sample_rate: cpal::SampleRate(22050),
        data_type: cpal::SampleFormat::I16,
    };

    let mut sampledata = get_samples(chunks);

    let host = cpal::default_host();
    let event_loop = host.event_loop();
    let device = host
        .default_output_device()
        .expect("no output device available");
    let stream_id = event_loop.build_output_stream(&device, &format).unwrap();

    event_loop
        .play_stream(stream_id)
        .expect("failed to play_stream");
    event_loop.run(move |_stream_id, _stream_result| {
        let stream_data = _stream_result.expect("an error occurred on stream");

        match stream_data {
            StreamData::Output {
                buffer: cpal::UnknownTypeOutputBuffer::I16(mut buffer),
            } => {
                for sample in buffer.chunks_mut(2) {
                    for out in sample.iter_mut() {
                        *out = sampledata
                            .pop_front()
                            .unwrap_or_else(|| std::process::exit(0));
                    }
                }
            }
            _ => (),
        }
    });
}
<commit_msg>play.rs: consistent tagging type<commit_after>use vqa_parser::audio::CodecState;
use vqa_parser::{form_chunk, snd2_chunk, vqa_header};
use vqa_parser::{SND2Chunk, VQAHeader};

use cpal::traits::{EventLoopTrait, HostTrait};

use nom::bytes::complete::{tag, take_until};
use nom::multi::many0;
use nom::IResult;

use cpal::StreamData;
use std::collections::VecDeque;
use std::fs::File;
use std::io::Read;

fn parse_vqaheader(input: &[u8]) -> IResult<&[u8], VQAHeader> {
    let (input, _) = form_chunk(input)?;
    let (input, _) = tag("WVQA")(input)?;
    let (input, vqaheader) = vqa_header(input)?;

    Ok((input, vqaheader))
}

fn next_snd2_chunk(input: &[u8]) -> IResult<&[u8], SND2Chunk> {
    let (input, _) = take_until("SND2")(input)?;
    let (input, chunk) = snd2_chunk(input)?;

    Ok((input, chunk))
}

fn all_snd2_chunks(input: &[u8]) -> IResult<&[u8], Vec<SND2Chunk>> {
    let (input, chunks) = many0(next_snd2_chunk)(input)?;

    Ok((input, chunks))
}

fn main() {
    let mut args = std::env::args();
    if args.len() != 2 {
        println!("usage: {} <vqa file>", args.nth(0).unwrap());
        return;
    }

    let mut input = File::open(args.nth(1).unwrap()).expect("Failed to open file");
    let mut buffer = Vec::new();
    input.read_to_end(&mut buffer).expect("Failed to read file");

    let vqa = parse_vqaheader(&buffer).unwrap().1;
    let snd2_chunks = all_snd2_chunks(&buffer).unwrap().1;

    println!("{:#?}", vqa);
    play_chunks(&snd2_chunks);
}

fn get_samples(chunks: &[SND2Chunk]) -> VecDeque<i16> {
    let mut samples = VecDeque::new();

    let mut ch1_state = CodecState::new();
    let mut ch2_state = CodecState::new();
    for chunk in chunks {
        let left =
            vqa_parser::audio::decompress(&mut ch1_state, &chunk.data[..chunk.data.len() / 2]);
        let right =
            vqa_parser::audio::decompress(&mut ch2_state, &chunk.data[..chunk.data.len() / 2]);

        // interleave data
        for i in 0..left.len() {
            samples.push_back(left[i] as i16);
            samples.push_back(right[i] as i16);
        }
    }

    samples
}

fn play_chunks(chunks: &[SND2Chunk]) {
    let format = cpal::Format {
        channels: 2,
        sample_rate: cpal::SampleRate(22050),
        data_type: cpal::SampleFormat::I16,
    };

    let mut sampledata = get_samples(chunks);

    let host = cpal::default_host();
    let event_loop = host.event_loop();
    let device = host
        .default_output_device()
        .expect("no output device available");
    let stream_id = event_loop.build_output_stream(&device, &format).unwrap();

    event_loop
        .play_stream(stream_id)
        .expect("failed to play_stream");
    event_loop.run(move |_stream_id, _stream_result| {
        let stream_data = _stream_result.expect("an error occurred on stream");

        match stream_data {
            StreamData::Output {
                buffer: cpal::UnknownTypeOutputBuffer::I16(mut buffer),
            } => {
                for sample in buffer.chunks_mut(2) {
                    for out in sample.iter_mut() {
                        *out = sampledata
                            .pop_front()
                            .unwrap_or_else(|| std::process::exit(0));
                    }
                }
            }
            _ => (),
        }
    });
}
<|endoftext|>


<commit_before>use libimagerror::trace::trace_error;
use libimagutil::iter::FoldResult;

use store::FileLockEntry;
use storeid::StoreId;
use hook::Hook;
use hook::result::HookResult;
use hook::accessor::{StoreIdAccessor, MutableHookDataAccessor, NonMutableHookDataAccessor};
use hook::accessor::HookDataAccessor as HDA;

use hook::error::HookError as HE;
use hook::error::HookErrorKind as HEK;
use configuration::AspectConfig;

#[derive(Debug)]
pub struct Aspect {
    cfg: Option<AspectConfig>,
    name: String,
    hooks: Vec<Box<Hook>>,
}

impl Aspect {

    pub fn new(name: String, cfg: Option<AspectConfig>) -> Aspect {
        Aspect {
            cfg: cfg,
            name: name,
            hooks: vec![],
        }
    }

    pub fn name(&self) -> &String {
        &self.name
    }

    pub fn register_hook(&mut self, h: Box<Hook>) {
        self.hooks.push(h);
    }

}

impl StoreIdAccessor for Aspect {
    fn access(&self, id: &StoreId) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| {
            let x = is_match!(*a, HDA::StoreIdAccess(_));
            if !x {
                warn!("Denied execution of None-StoreId-Accessing Hook");
                debug!("Accessor: {:?}", a);
                debug!("in StoreIdAccess-Aspect execution: {:?}", self);
            }
            x
        }) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(accessor) => accessor.access(id),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

impl MutableHookDataAccessor for Aspect {
    fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
        debug!("Checking whether mutable hooks are allowed");
        debug!("-> config = {:?}", self.cfg);
        if !self.cfg.as_ref().map(|c| c.allow_mutable_hooks()).unwrap_or(false) {
            debug!("Apparently mutable hooks are not allowed... failing now.");
            return Err(HE::new(HEK::MutableHooksNotAllowed, None));
        }

        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();

        // TODO: Naiive implementation.
        // More sophisticated version would check whether there are _chunks_ of
        // NonMutableAccess accessors and execute these chunks in parallel. We do not have
        // performance concerns yet, so this is okay.
        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(ref accessor)    => accessor.access(fle.get_location()),
                &HDA::MutableAccess(ref accessor)    => accessor.access_mut(fle),
                &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
            };
            trace_hook_errors(res)
        })
    }
}

impl NonMutableHookDataAccessor for Aspect {
    fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| {
            let x = is_match!(*a, HDA::NonMutableAccess(_));
            if !x {
                warn!("Denied execution of Non-Mutable-Accessing Hook");
                debug!("Accessor: {:?}", a);
                debug!("in StoreIdAccess-Aspect execution: {:?}", self);
            }
            x
        }) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::NonMutableAccess(accessor) => accessor.access(fle),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

fn trace_hook_errors(res: HookResult<()>) -> HookResult<()> {
    res.or_else(|e| {
        if !e.is_aborting() {
            trace_error(&e);
            // ignore error if it is not aborting, as we printed it already
            Ok(())
        } else {
            Err(e)
        }
    })
}

<commit_msg>Just do not execute mutable hooks, but let pass the nonmutables<commit_after>use libimagerror::trace::trace_error;
use libimagutil::iter::FoldResult;

use store::FileLockEntry;
use storeid::StoreId;
use hook::Hook;
use hook::result::HookResult;
use hook::accessor::{StoreIdAccessor, MutableHookDataAccessor, NonMutableHookDataAccessor};
use hook::accessor::HookDataAccessor as HDA;

use hook::error::HookError as HE;
use hook::error::HookErrorKind as HEK;
use configuration::AspectConfig;

#[derive(Debug)]
pub struct Aspect {
    cfg: Option<AspectConfig>,
    name: String,
    hooks: Vec<Box<Hook>>,
}

impl Aspect {

    pub fn new(name: String, cfg: Option<AspectConfig>) -> Aspect {
        Aspect {
            cfg: cfg,
            name: name,
            hooks: vec![],
        }
    }

    pub fn name(&self) -> &String {
        &self.name
    }

    pub fn register_hook(&mut self, h: Box<Hook>) {
        self.hooks.push(h);
    }

}

impl StoreIdAccessor for Aspect {
    fn access(&self, id: &StoreId) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| {
            let x = is_match!(*a, HDA::StoreIdAccess(_));
            if !x {
                warn!("Denied execution of None-StoreId-Accessing Hook");
                debug!("Accessor: {:?}", a);
                debug!("in StoreIdAccess-Aspect execution: {:?}", self);
            }
            x
        }) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(accessor) => accessor.access(id),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

impl MutableHookDataAccessor for Aspect {
    fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
        debug!("Checking whether mutable hooks are allowed");
        debug!("-> config = {:?}", self.cfg);

        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();

        // TODO: Naiive implementation.
        // More sophisticated version would check whether there are _chunks_ of
        // NonMutableAccess accessors and execute these chunks in parallel. We do not have
        // performance concerns yet, so this is okay.
        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::StoreIdAccess(ref accessor)    => accessor.access(fle.get_location()),
                &HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
                &HDA::MutableAccess(ref accessor)    => {
                    if !self.cfg.as_ref().map(|c| c.allow_mutable_hooks()).unwrap_or(false) {
                        debug!("Apparently mutable hooks are not allowed... failing now.");
                        return Err(HE::new(HEK::MutableHooksNotAllowed, None));
                    }

                    accessor.access_mut(fle)
                },
            };
            trace_hook_errors(res)
        })
    }
}

impl NonMutableHookDataAccessor for Aspect {
    fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
        let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
        if !accessors.iter().all(|a| {
            let x = is_match!(*a, HDA::NonMutableAccess(_));
            if !x {
                warn!("Denied execution of Non-Mutable-Accessing Hook");
                debug!("Accessor: {:?}", a);
                debug!("in StoreIdAccess-Aspect execution: {:?}", self);
            }
            x
        }) {
            return Err(HE::new(HEK::AccessTypeViolation, None));
        }

        accessors.iter().fold_defresult(|accessor| {
            let res = match accessor {
                &HDA::NonMutableAccess(accessor) => accessor.access(fle),
                _ => unreachable!(),
            };
            trace_hook_errors(res)
        })
    }
}

fn trace_hook_errors(res: HookResult<()>) -> HookResult<()> {
    res.or_else(|e| {
        if !e.is_aborting() {
            trace_error(&e);
            // ignore error if it is not aborting, as we printed it already
            Ok(())
        } else {
            Err(e)
        }
    })
}

<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "foo"]

pub struct Bar;

// @!has foo/struct.Bar.html '//*[@id="implementations"]'
<commit_msg>Fix unneeded-trait-implementations-title test<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "foo"]

pub struct Bar;

// @count foo/struct.Bar.html '//*[@id="implementations"]' 0
<|endoftext|>


<commit_before>use crate::model::BragiError;
use mimir::objects::Coord;

pub fn make_coord(lon: f64, lat: f64) -> Result<Coord, BragiError> {
    if lon < -90f64 || lon > 90f64 {
        Err(BragiError::InvalidParam("lon is not a valid longitude"))
    } else if lat < -180f64 || lat > 180f64 {
        Err(BragiError::InvalidParam("lat is not a valid latitude"))
    } else {
        Ok(Coord::new(lon, lat))
    }
}
<commit_msg>fix latitude/longitude check<commit_after>use crate::model::BragiError;
use mimir::objects::Coord;

pub fn make_coord(lon: f64, lat: f64) -> Result<Coord, BragiError> {
    if lat < -90f64 || lat > 90f64 {
        Err(BragiError::InvalidParam("lat is not a valid latitude"))
    } else if lon < -180f64 || lon > 180f64 {
        Err(BragiError::InvalidParam("lon is not a valid longitude"))
    } else {
        Ok(Coord::new(lon, lat))
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::cluster::{Cluster, Simulator};
use super::node::new_node_cluster;
use super::server::new_server_cluster;
use super::util::*;

fn test_huge_snapshot<T: Simulator>(cluster: &mut Cluster<T>) {
    // init_log();
    let pd_client = cluster.pd_client.clone();
    // Disable default max peer count check.
    pd_client.disable_default_rule();

    let r1 = cluster.bootstrap_conf_change();
    cluster.start();

    // at least 4m data
    for i in 0..2 * 1024 {
        let key = format!("{:01024}", i);
        let value = format!("{:01024}", i);
        cluster.must_put(key.as_bytes(), value.as_bytes());
    }

    let engine_2 = cluster.get_engine(2);
    must_get_none(&engine_2, &format!("{:01024}", 0).into_bytes());
    // add peer (2,2) to region 1.
    pd_client.must_add_peer(r1, new_peer(2, 2));

    let (key, value) = (b"k2", b"v2");
    cluster.must_put(key, value);
    assert_eq!(cluster.get(key), Some(value.to_vec()));
    must_get_equal(&engine_2, key, value);

    // now snapshot must be applied on peer 2;
    let key = format!("{:01024}", 0);
    let value = format!("{:01024}", 0);
    must_get_equal(&engine_2, key.as_bytes(), value.as_bytes());

    // TODO: add more tests.
}

#[test]
fn test_node_huge_snapshot() {
    let count = 5;
    let mut cluster = new_node_cluster(0, count);
    test_huge_snapshot(&mut cluster);
}

#[test]
fn test_server_huge_snapshot() {
    let count = 5;
    let mut cluster = new_server_cluster(0, count);
    test_huge_snapshot(&mut cluster);
}
<commit_msg>raftstore: pass compile. (#702)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::cluster::{Cluster, Simulator};
use super::node::new_node_cluster;
use super::server::new_server_cluster;
use super::util::*;

fn test_huge_snapshot<T: Simulator>(cluster: &mut Cluster<T>) {
    // init_log();
    let pd_client = cluster.pd_client.clone();
    // Disable default max peer count check.
    pd_client.disable_default_rule();

    let r1 = cluster.run_conf_change();

    // at least 4m data
    for i in 0..2 * 1024 {
        let key = format!("{:01024}", i);
        let value = format!("{:01024}", i);
        cluster.must_put(key.as_bytes(), value.as_bytes());
    }

    let engine_2 = cluster.get_engine(2);
    must_get_none(&engine_2, &format!("{:01024}", 0).into_bytes());
    // add peer (2,2) to region 1.
    pd_client.must_add_peer(r1, new_peer(2, 2));

    let (key, value) = (b"k2", b"v2");
    cluster.must_put(key, value);
    assert_eq!(cluster.get(key), Some(value.to_vec()));
    must_get_equal(&engine_2, key, value);

    // now snapshot must be applied on peer 2;
    let key = format!("{:01024}", 0);
    let value = format!("{:01024}", 0);
    must_get_equal(&engine_2, key.as_bytes(), value.as_bytes());

    // TODO: add more tests.
}

#[test]
fn test_node_huge_snapshot() {
    let count = 5;
    let mut cluster = new_node_cluster(0, count);
    test_huge_snapshot(&mut cluster);
}

#[test]
fn test_server_huge_snapshot() {
    let count = 5;
    let mut cluster = new_server_cluster(0, count);
    test_huge_snapshot(&mut cluster);
}
<|endoftext|>


<commit_before>//! LR(1) state construction algorithm.

use collections::{map, Multimap};
use kernel_set;
use grammar::repr::*;
use lr1::core::*;
use lr1::first;
use lr1::lane_table::*;
use lr1::lookahead::*;
use std::rc::Rc;
use std::env;
use tls::Tls;

#[cfg(test)]
mod test;

fn build_lr1_states_legacy<'grammar>(grammar: &'grammar Grammar, start: NonterminalString) -> LR1Result<'grammar>
{
    let eof = TokenSet::eof();
    let mut lr1: LR<'grammar, TokenSet> = LR::new(grammar, start, eof);
    lr1.set_permit_early_stop(true);
    lr1.build_states()
}

type ConstructionFunction<'grammar> = fn(&'grammar Grammar, NonterminalString) -> LR1Result<'grammar> ;

fn use_lane_table() -> bool {
    match env::var("LALRPOP_LANE_TABLE") {
        Ok(ref s) => s == "enabled",
        _ => false
    }
}

pub fn build_lr1_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> LR1Result<'grammar>
{
    let (method_name, method_fn) = if use_lane_table() {
        ("lane", build_lane_table_states as ConstructionFunction)
    } else {
        ("legacy", build_lr1_states_legacy as ConstructionFunction)
    };

    profile! {
        &Tls::session(),
        format!("LR(1) state construction ({})", method_name),
        {
            method_fn(grammar, start)
        }
    }
}

pub fn build_lr0_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> Result<Vec<LR0State<'grammar>>,
                                            LR0TableConstructionError<'grammar>>
{
    let lr1 = LR::new(grammar, start, Nil);
    lr1.build_states()
}

pub struct LR<'grammar, L: LookaheadBuild> {
    grammar: &'grammar Grammar,
    first_sets: first::FirstSets,
    start_nt: NonterminalString,
    start_lookahead: L,
    permit_early_stop: bool,
}

impl<'grammar, L: LookaheadBuild> LR<'grammar, L> {
    fn new(grammar: &'grammar Grammar,
           start_nt: NonterminalString,
           start_lookahead: L)
           -> Self {
        LR {
            grammar: grammar,
            first_sets: first::FirstSets::new(grammar),
            start_nt: start_nt,
            start_lookahead: start_lookahead,
            permit_early_stop: false,
        }
    }

    fn set_permit_early_stop(&mut self, v: bool) {
        self.permit_early_stop = v;
    }

    fn build_states(&self)
                    -> Result<Vec<State<'grammar, L>>,
                              TableConstructionError<'grammar, L>>
    {
        let session = Tls::session();
        let mut kernel_set = kernel_set::KernelSet::new();
        let mut states = vec![];
        let mut conflicts = vec![];

        // create the starting state
        kernel_set.add_state(Kernel::start(self.items(self.start_nt,
                                                      0,
                                                      &self.start_lookahead)));

        while let Some(Kernel { items: seed_items }) = kernel_set.next() {
            let items = self.transitive_closure(seed_items);
            let index = StateIndex(states.len());

            if index.0 % 5000 == 0 && index.0 > 0 {
                log!(session, Verbose, "{} states created so far.", index.0);
            }

            let mut this_state = State { index: index,
                                         items: items.clone(),
                                         shifts: map(),
                                         reductions: vec!(),
                                         gotos: map() };

            // group the items that we can transition into by shifting
            // over a term or nonterm
            let transitions: Multimap<Symbol, Multimap<LR0Item<'grammar>, L>> =
                items.vec
                     .iter()
                     .filter_map(|item| item.shifted_item())
                     .map(|(symbol, Item { production, index, lookahead })| {
                         (symbol, (Item::lr0(production, index), lookahead))
                     })
                     .collect();

            for (symbol, shifted_items) in transitions.into_iter() {
                let shifted_items: Vec<Item<'grammar, L>> =
                    shifted_items.into_iter()
                                 .map(|(lr0_item, lookahead)| {
                                     lr0_item.with_lookahead(lookahead)
                                 })
                                 .collect();

                // Not entirely obvious: if the original set of items
                // is sorted to begin with (and it is), then this new
                // set of shifted items is *also* sorted. This is
                // because it is produced from the old items by simply
                // incrementing the index by 1.
                let next_state = kernel_set.add_state(Kernel::shifted(shifted_items));

                match symbol {
                    Symbol::Terminal(s) => {
                        let prev = this_state.shifts.insert(s, next_state);
                        assert!(prev.is_none()); // cannot have a shift/shift conflict
                    }

                    Symbol::Nonterminal(s) => {
                        let prev = this_state.gotos.insert(s, next_state);
                        assert!(prev.is_none());
                    }
                }
            }

            // finally, consider the reductions
            for item in items.vec.iter().filter(|i| i.can_reduce()) {
                this_state.reductions.push((item.lookahead.clone(), item.production));
            }

            // check for shift-reduce conflicts (reduce-reduce detected above)
            conflicts.extend(L::conflicts(&this_state));

            // extract a new state
            states.push(this_state);

            if self.permit_early_stop && session.stop_after(conflicts.len()) {
                log!(session, Verbose,
                     "{} conflicts encountered, stopping.", conflicts.len());
                break;
            }
        }

        if !conflicts.is_empty() {
            Err(TableConstructionError { states: states, conflicts: conflicts })
        } else {
            Ok(states)
        }
    }

    fn items(&self,
             id: NonterminalString,
             index: usize,
             lookahead: &L)
             -> Vec<Item<'grammar, L>>
    {
        self.grammar.productions_for(id)
                    .iter()
                    .map(|production| {
                        debug_assert!(index <= production.symbols.len());
                        Item { production: production,
                               index: index,
                               lookahead: lookahead.clone() }
                    })
                    .collect()
    }

    // expands `state` with epsilon moves
    fn transitive_closure(&self, items: Vec<Item<'grammar, L>>)
                          -> Items<'grammar, L>
    {
        let mut stack: Vec<LR0Item<'grammar>> =
            items.iter().map(|item| item.to_lr0()).collect();
        let mut map: Multimap<LR0Item<'grammar>, L> =
            items.into_iter()
                 .map(|item| (item.to_lr0(), item.lookahead))
                 .collect();

        while let Some(item) = stack.pop() {
            let lookahead = map.get(&item).unwrap().clone();

            let shift_symbol = item.shift_symbol();

            // Check whether this is an item where the cursor
            // is resting on a non-terminal:
            //
            // I = ... (*) X z... [lookahead]
            //
            // The `nt` will be X and the `remainder` will be `z...`.
            let (nt, remainder) = match shift_symbol {
                None => continue, // requires a reduce
                Some((Symbol::Terminal(_), _)) => {
                    continue; // requires a shift
                }
                Some((Symbol::Nonterminal(nt), remainder)) => {
                    (nt, remainder)
                }
            };

            // In that case, for each production of `X`, we are also
            // in a state where the cursor rests at the start of that production:
            //
            // X = (*) a... [lookahead']
            // X = (*) b... [lookahead']
            //
            // Here `lookahead'` is computed based on the `remainder` and our
            // `lookahead`. In LR1 at least, it is the union of:
            //
            //   (a) FIRST(remainder)
            //   (b) if remainder may match epsilon, also our lookahead.
            for new_item in L::epsilon_moves(self, nt, remainder, &lookahead) {
                let new_item0 = new_item.to_lr0();
                if map.push(new_item0, new_item.lookahead) {
                    stack.push(new_item0);
                }
            }
        }

        let final_items = map.into_iter()
                             .map(|(lr0_item, lookahead)| lr0_item.with_lookahead(lookahead))
                             .collect();

        Items { vec: Rc::new(final_items) }
    }
}

/// Except for the initial state, the kernel sets always contain
/// a set of "seed" items where something has been pushed (that is,
/// index > 0). In other words, items like this:
///
///    A = ...p (*) ...
///
/// where ...p is non-empty. We now have to expand to include any
/// epsilon moves:
///
///    A = ... (*) B ...
///    B = (*) ...        // added by transitive_closure algorithm
///
/// But note that the state is completely identified by its
/// kernel set: the same kernel sets always expand to the
/// same transitive closures, and different kernel sets
/// always expand to different transitive closures. The
/// first point is obvious, but the latter point follows
/// because the transitive closure algorithm only adds
/// items where `index == 0`, and hence it can never add an
/// item found in a kernel set.
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Kernel<'grammar, L: LookaheadBuild> {
    items: Vec<Item<'grammar, L>>
}

impl<'grammar, L: LookaheadBuild> Kernel<'grammar, L> {
    pub fn start(items: Vec<Item<'grammar, L>>) -> Kernel<'grammar, L> {
        // In start state, kernel should have only items with `index == 0`.
        debug_assert!(items.iter().all(|item| item.index == 0));
        Kernel { items: items }
    }

    pub fn shifted(items: Vec<Item<'grammar, L>>) -> Kernel<'grammar, L> {
        // Assert that this kernel consists only of shifted items
        // where `index > 0`. This assertion could cost real time to
        // check so only do it in debug mode.
        debug_assert!(items.iter().all(|item| item.index > 0));
        Kernel { items: items }
    }
}

impl<'grammar, L: LookaheadBuild> kernel_set::Kernel for Kernel<'grammar, L> {
    type Index = StateIndex;

    fn index(c: usize) -> StateIndex {
        StateIndex(c)
    }
}

pub trait LookaheadBuild: Lookahead {
    // Given that there exists an item
    //
    //     X = ... (*) Y ...s [L]
    //
    // where `nt` is `Y`, `remainder` is `...s`, and `lookahead` is
    // `L`, computes the new items resulting from epsilon moves (if
    // any). The technique of doing this will depend on the amount of
    // lookahead.
    //
    // For example, if we have an LR0 item, then for each `Y = ...`
    // production, we just add an `Y = (*) ...` item. But for LR1
    // items, we have to add multiple items where we consider the
    // lookahead from `FIRST(...s, L)`.
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               remainder: &[Symbol],
                               lookahead: &Self)
                               -> Vec<Item<'grammar, Self>>;
}

impl LookaheadBuild for Nil {
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               _remainder: &[Symbol],
                               lookahead: &Nil)
                               -> Vec<LR0Item<'grammar>>
    {
        lr.items(nt, 0, &lookahead)
    }
}

impl LookaheadBuild for TokenSet {
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               remainder: &[Symbol],
                               lookahead: &Self)
                               -> Vec<LR1Item<'grammar>>
    {
        let first_set = lr.first_sets.first1(remainder, lookahead);
        lr.items(nt, 0, &first_set)
    }
}
<commit_msg>make LALRPOP_LANE_TABLE the default<commit_after>//! LR(1) state construction algorithm.

use collections::{map, Multimap};
use kernel_set;
use grammar::repr::*;
use lr1::core::*;
use lr1::first;
use lr1::lane_table::*;
use lr1::lookahead::*;
use std::rc::Rc;
use std::env;
use tls::Tls;

#[cfg(test)]
mod test;

fn build_lr1_states_legacy<'grammar>(grammar: &'grammar Grammar, start: NonterminalString) -> LR1Result<'grammar>
{
    let eof = TokenSet::eof();
    let mut lr1: LR<'grammar, TokenSet> = LR::new(grammar, start, eof);
    lr1.set_permit_early_stop(true);
    lr1.build_states()
}

type ConstructionFunction<'grammar> = fn(&'grammar Grammar, NonterminalString) -> LR1Result<'grammar> ;

fn use_lane_table() -> bool {
    match env::var("LALRPOP_LANE_TABLE") {
        Ok(ref s) => s != "disabled",
        _ => true
    }
}

pub fn build_lr1_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> LR1Result<'grammar>
{
    let (method_name, method_fn) = if use_lane_table() {
        ("lane", build_lane_table_states as ConstructionFunction)
    } else {
        ("legacy", build_lr1_states_legacy as ConstructionFunction)
    };

    profile! {
        &Tls::session(),
        format!("LR(1) state construction ({})", method_name),
        {
            method_fn(grammar, start)
        }
    }
}

pub fn build_lr0_states<'grammar>(grammar: &'grammar Grammar,
                                  start: NonterminalString)
                                  -> Result<Vec<LR0State<'grammar>>,
                                            LR0TableConstructionError<'grammar>>
{
    let lr1 = LR::new(grammar, start, Nil);
    lr1.build_states()
}

pub struct LR<'grammar, L: LookaheadBuild> {
    grammar: &'grammar Grammar,
    first_sets: first::FirstSets,
    start_nt: NonterminalString,
    start_lookahead: L,
    permit_early_stop: bool,
}

impl<'grammar, L: LookaheadBuild> LR<'grammar, L> {
    fn new(grammar: &'grammar Grammar,
           start_nt: NonterminalString,
           start_lookahead: L)
           -> Self {
        LR {
            grammar: grammar,
            first_sets: first::FirstSets::new(grammar),
            start_nt: start_nt,
            start_lookahead: start_lookahead,
            permit_early_stop: false,
        }
    }

    fn set_permit_early_stop(&mut self, v: bool) {
        self.permit_early_stop = v;
    }

    fn build_states(&self)
                    -> Result<Vec<State<'grammar, L>>,
                              TableConstructionError<'grammar, L>>
    {
        let session = Tls::session();
        let mut kernel_set = kernel_set::KernelSet::new();
        let mut states = vec![];
        let mut conflicts = vec![];

        // create the starting state
        kernel_set.add_state(Kernel::start(self.items(self.start_nt,
                                                      0,
                                                      &self.start_lookahead)));

        while let Some(Kernel { items: seed_items }) = kernel_set.next() {
            let items = self.transitive_closure(seed_items);
            let index = StateIndex(states.len());

            if index.0 % 5000 == 0 && index.0 > 0 {
                log!(session, Verbose, "{} states created so far.", index.0);
            }

            let mut this_state = State { index: index,
                                         items: items.clone(),
                                         shifts: map(),
                                         reductions: vec!(),
                                         gotos: map() };

            // group the items that we can transition into by shifting
            // over a term or nonterm
            let transitions: Multimap<Symbol, Multimap<LR0Item<'grammar>, L>> =
                items.vec
                     .iter()
                     .filter_map(|item| item.shifted_item())
                     .map(|(symbol, Item { production, index, lookahead })| {
                         (symbol, (Item::lr0(production, index), lookahead))
                     })
                     .collect();

            for (symbol, shifted_items) in transitions.into_iter() {
                let shifted_items: Vec<Item<'grammar, L>> =
                    shifted_items.into_iter()
                                 .map(|(lr0_item, lookahead)| {
                                     lr0_item.with_lookahead(lookahead)
                                 })
                                 .collect();

                // Not entirely obvious: if the original set of items
                // is sorted to begin with (and it is), then this new
                // set of shifted items is *also* sorted. This is
                // because it is produced from the old items by simply
                // incrementing the index by 1.
                let next_state = kernel_set.add_state(Kernel::shifted(shifted_items));

                match symbol {
                    Symbol::Terminal(s) => {
                        let prev = this_state.shifts.insert(s, next_state);
                        assert!(prev.is_none()); // cannot have a shift/shift conflict
                    }

                    Symbol::Nonterminal(s) => {
                        let prev = this_state.gotos.insert(s, next_state);
                        assert!(prev.is_none());
                    }
                }
            }

            // finally, consider the reductions
            for item in items.vec.iter().filter(|i| i.can_reduce()) {
                this_state.reductions.push((item.lookahead.clone(), item.production));
            }

            // check for shift-reduce conflicts (reduce-reduce detected above)
            conflicts.extend(L::conflicts(&this_state));

            // extract a new state
            states.push(this_state);

            if self.permit_early_stop && session.stop_after(conflicts.len()) {
                log!(session, Verbose,
                     "{} conflicts encountered, stopping.", conflicts.len());
                break;
            }
        }

        if !conflicts.is_empty() {
            Err(TableConstructionError { states: states, conflicts: conflicts })
        } else {
            Ok(states)
        }
    }

    fn items(&self,
             id: NonterminalString,
             index: usize,
             lookahead: &L)
             -> Vec<Item<'grammar, L>>
    {
        self.grammar.productions_for(id)
                    .iter()
                    .map(|production| {
                        debug_assert!(index <= production.symbols.len());
                        Item { production: production,
                               index: index,
                               lookahead: lookahead.clone() }
                    })
                    .collect()
    }

    // expands `state` with epsilon moves
    fn transitive_closure(&self, items: Vec<Item<'grammar, L>>)
                          -> Items<'grammar, L>
    {
        let mut stack: Vec<LR0Item<'grammar>> =
            items.iter().map(|item| item.to_lr0()).collect();
        let mut map: Multimap<LR0Item<'grammar>, L> =
            items.into_iter()
                 .map(|item| (item.to_lr0(), item.lookahead))
                 .collect();

        while let Some(item) = stack.pop() {
            let lookahead = map.get(&item).unwrap().clone();

            let shift_symbol = item.shift_symbol();

            // Check whether this is an item where the cursor
            // is resting on a non-terminal:
            //
            // I = ... (*) X z... [lookahead]
            //
            // The `nt` will be X and the `remainder` will be `z...`.
            let (nt, remainder) = match shift_symbol {
                None => continue, // requires a reduce
                Some((Symbol::Terminal(_), _)) => {
                    continue; // requires a shift
                }
                Some((Symbol::Nonterminal(nt), remainder)) => {
                    (nt, remainder)
                }
            };

            // In that case, for each production of `X`, we are also
            // in a state where the cursor rests at the start of that production:
            //
            // X = (*) a... [lookahead']
            // X = (*) b... [lookahead']
            //
            // Here `lookahead'` is computed based on the `remainder` and our
            // `lookahead`. In LR1 at least, it is the union of:
            //
            //   (a) FIRST(remainder)
            //   (b) if remainder may match epsilon, also our lookahead.
            for new_item in L::epsilon_moves(self, nt, remainder, &lookahead) {
                let new_item0 = new_item.to_lr0();
                if map.push(new_item0, new_item.lookahead) {
                    stack.push(new_item0);
                }
            }
        }

        let final_items = map.into_iter()
                             .map(|(lr0_item, lookahead)| lr0_item.with_lookahead(lookahead))
                             .collect();

        Items { vec: Rc::new(final_items) }
    }
}

/// Except for the initial state, the kernel sets always contain
/// a set of "seed" items where something has been pushed (that is,
/// index > 0). In other words, items like this:
///
///    A = ...p (*) ...
///
/// where ...p is non-empty. We now have to expand to include any
/// epsilon moves:
///
///    A = ... (*) B ...
///    B = (*) ...        // added by transitive_closure algorithm
///
/// But note that the state is completely identified by its
/// kernel set: the same kernel sets always expand to the
/// same transitive closures, and different kernel sets
/// always expand to different transitive closures. The
/// first point is obvious, but the latter point follows
/// because the transitive closure algorithm only adds
/// items where `index == 0`, and hence it can never add an
/// item found in a kernel set.
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Kernel<'grammar, L: LookaheadBuild> {
    items: Vec<Item<'grammar, L>>
}

impl<'grammar, L: LookaheadBuild> Kernel<'grammar, L> {
    pub fn start(items: Vec<Item<'grammar, L>>) -> Kernel<'grammar, L> {
        // In start state, kernel should have only items with `index == 0`.
        debug_assert!(items.iter().all(|item| item.index == 0));
        Kernel { items: items }
    }

    pub fn shifted(items: Vec<Item<'grammar, L>>) -> Kernel<'grammar, L> {
        // Assert that this kernel consists only of shifted items
        // where `index > 0`. This assertion could cost real time to
        // check so only do it in debug mode.
        debug_assert!(items.iter().all(|item| item.index > 0));
        Kernel { items: items }
    }
}

impl<'grammar, L: LookaheadBuild> kernel_set::Kernel for Kernel<'grammar, L> {
    type Index = StateIndex;

    fn index(c: usize) -> StateIndex {
        StateIndex(c)
    }
}

pub trait LookaheadBuild: Lookahead {
    // Given that there exists an item
    //
    //     X = ... (*) Y ...s [L]
    //
    // where `nt` is `Y`, `remainder` is `...s`, and `lookahead` is
    // `L`, computes the new items resulting from epsilon moves (if
    // any). The technique of doing this will depend on the amount of
    // lookahead.
    //
    // For example, if we have an LR0 item, then for each `Y = ...`
    // production, we just add an `Y = (*) ...` item. But for LR1
    // items, we have to add multiple items where we consider the
    // lookahead from `FIRST(...s, L)`.
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               remainder: &[Symbol],
                               lookahead: &Self)
                               -> Vec<Item<'grammar, Self>>;
}

impl LookaheadBuild for Nil {
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               _remainder: &[Symbol],
                               lookahead: &Nil)
                               -> Vec<LR0Item<'grammar>>
    {
        lr.items(nt, 0, &lookahead)
    }
}

impl LookaheadBuild for TokenSet {
    fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
                               nt: NonterminalString,
                               remainder: &[Symbol],
                               lookahead: &Self)
                               -> Vec<LR1Item<'grammar>>
    {
        let first_set = lr.first_sets.first1(remainder, lookahead);
        lr.items(nt, 0, &first_set)
    }
}
<|endoftext|>