<commit_before>/*
    Copyright 2015 Andrei "dread.deimos" Arsenin
    See LICENSE file for legal stuff
*/

// Import STDIN and STDOUT handle generators for input and output respectively.
// We need the std::io::Write trait so we can flush the output buffer later.
use std::io::{stdin, stdout};
use std::io::Write;

// Declare our game module and import it's definitions in this module's scope
pub mod game;
use game::*;

fn main() {
    // Create a game object. Note that it's mutable so we can change it's internal variables. It's
    // also worth to mention that mutability is spread on all struct variables and there's no way
    // to make some of them mutable and others not.
    let mut the_game = Game::new();

    // Just print an invitation line using a println! macros
    println!("Guess the number! (Enter 'q' to quit', 'h' for help)");

    loop {
        // We'll need an empty String object to feed it to IO object as buffer
        let mut input = String::new();

        // Print prompt decoration. We want an imput invitation that displays how many tries have
        // been used so far to guess the secret number
        print!("{} > ", the_game.tries);

        // Flush buffer so the decoration will be printed immedeately without line buffering.
        // Note, that this will fail if you don't include std::io::Write trait.
        let _ = stdout().flush();

        // Read from STDIN to our buffer variable. read_line() method returns a Result object so
        // we need to handle it's success and fail status.
        stdin().read_line(&mut input)
            .ok()
            .expect("Failed to read input");

        // Trim string. Note that trim() method will return &str type, not String. But we don't
        // need the String type any further because we don't want this value to be borrowed.
        // We use "let" to redefine this binding with new type.
        let input = input.trim();

        // Now we attempt to parse the input string to a u32 integer. On success, we have a number
        // and will check if matches our secret number. On fail, we assume that user have entered
        // a command and we will try to figure out which one exactly.
        match input.parse::<u32>() {

            // Our first case. Since we must have four digits according to our game rules, we'll
            // check if input string's length is four. If not, we just print the warning and
            // proceed with the game loop.
            Ok(_) if input.len() != 4 => println!("Number of four digits is needed"),

            // Next, according to our game's rules, all digits of the numbers should be different.
            // So we call a game method that will check this for us. check_unique_digits() returns
            // a bool typed value.
            Ok(_) if !the_game.check_unique_digits(input) => println!("Digits must be unique"),

            // If previous checks have filtered us a valid number, we'll ask our game object to
            // check this number against the secret one. If it matches, we will get the true bool
            // value, print the win message with a number of tries needed to guess the right answer
            // and break the loop so game will end.
            Ok(_) if the_game.guess(input) => {
                println!("You won in {} tries!", the_game.tries + 1);
                break;
            },

            // If the input number was correct, but didn't match the secret value, we'll analyze it
            // and print the number of "cows" (digit exists, but doesn't match position) and
            // "bulls" (digit exists in secret number and matches position).
            Ok(_) => {
                // Here we ask the game object for tuple containing cows and bulls. We use
                // automatic type allocation and our code expects simple integers, so we don't
                // really need to think about particular type of these bindings at the moment.
                let (cows, bulls) = the_game.try(input);

                // We ask the game object to analyze acquired result and save hints on digit
                // positions that are being entered
                the_game.analyze(input, cows, bulls);

                // Now we print number of found matches if there was any
                if cows == 0 && bulls == 0 {
                    println!("Nothing found");
                } else {
                    println!("Found {} cows and {} bulls", cows, bulls);
                }
            }

            // So we failed to parse our input string as integer, so it must be a command. We start
            // another match operator.
            Err(_) => match input {

                // If we encounter an empty value, we just restart the game loop waiting for
                // non-empty command.
                "" => continue,

                // Here we define a pattern that matches one of these strings for a command that
                // quits the game. The break operator will end the game loop and since there's
                // nothing after this loop, the application will close returning user to shell.
                "q" | "quit" | "exit" => break,

                // We'll want to show user a list of available commands, so we call the
                // print_help() function which will handle this for us.
                "h" | "help" | "?" => print_help(),

                // This command calls print_hint(). Read about it below.
                "s" | "stats" => print_hint(the_game.hint_table),

                // This simple command recursively calls the main() function effecrively restarting
                // the game. Make sure to break the loop, so we don't restart game loop after we
                // have returned from this call.

                // Note, that this kind of implementation is not really good one, but it'll be fine
                // for this tutorial. It's drawback is that with every game restart the local stack
                // increases and allocates a new game object that's data is being piled up in the
                // heap.
                "r" | "restart" => {
                    main();
                    break;
                },

                // In case of any other input, we just print a message that we didn't get what user
                // wanted and hint him to use help command.
                _  => println!("Unknown command: \"{}\". Enter 'h' for help", input),
            },
        };
    }
}

// This function just prints out the list of available game commands
fn print_help() {
    println!("r, restart    - Restart game");
    println!("q, quit, exit - Quit game");
    println!("h, help, ?    - This text");
    println!("s, stats      - Check out some hints on potential digit positions");
    println!("<NNNN>        - Enter four unique digits to guess the number and win");
}

// This functions take a two-dimmensional array of special typed values (see more in the game
// module description)
fn print_hint(table: [[Hint; 4]; 10]) {

    // Print position numbers
    println!("   1 2 3 4");

    // Loop through 10 digits from 0 to 9 inclusively
    for i in 0..10 {

        // Print the digit
        print!("{}: ", i);

        // Then loop through four available positions
        for j in 0..4 {

            // For each value of enum type Hint (see definition in game module) we print respective
            // character
            print!("{} ", match table[i][j] {
                Hint::Unknown => " ",
                Hint::Maybe   => "?",
                Hint::Here    => "+",
                Hint::NotHere => "-",
            });
        }

        // Print the new line character to finish line for this digit
        print!("\n");
    }
}
<commit_msg>Added remark about using placeholder<commit_after>/*
    Copyright 2015 Andrei "dread.deimos" Arsenin
    See LICENSE file for legal stuff
*/

// Import STDIN and STDOUT handle generators for input and output respectively.
// We need the std::io::Write trait so we can flush the output buffer later.
use std::io::{stdin, stdout};
use std::io::Write;

// Declare our game module and import it's definitions in this module's scope
pub mod game;
use game::*;

fn main() {
    // Create a game object. Note that it's mutable so we can change it's internal variables. It's
    // also worth to mention that mutability is spread on all struct variables and there's no way
    // to make some of them mutable and others not.
    let mut the_game = Game::new();

    // Just print an invitation line using a println! macros
    println!("Guess the number! (Enter 'q' to quit', 'h' for help)");

    loop {
        // We'll need an empty String object to feed it to IO object as buffer
        let mut input = String::new();

        // Print prompt decoration. We want an imput invitation that displays how many tries have
        // been used so far to guess the secret number
        print!("{} > ", the_game.tries);

        // Flush buffer so the decoration will be printed immedeately without line buffering.
        // Note, that this will fail if you don't include std::io::Write trait. Also, we assign
        // the result of this operation to a placeholder to avoid "Unused result" warning which
        // will appear because flush() expects to return a Result value.
        let _ = stdout().flush();

        // Read from STDIN to our buffer variable. read_line() method returns a Result object so
        // we need to handle it's success and fail status.
        stdin().read_line(&mut input)
            .ok()
            .expect("Failed to read input");

        // Trim string. Note that trim() method will return &str type, not String. But we don't
        // need the String type any further because we don't want this value to be borrowed.
        // We use "let" to redefine this binding with new type.
        let input = input.trim();

        // Now we attempt to parse the input string to a u32 integer. On success, we have a number
        // and will check if matches our secret number. On fail, we assume that user have entered
        // a command and we will try to figure out which one exactly.
        match input.parse::<u32>() {

            // Our first case. Since we must have four digits according to our game rules, we'll
            // check if input string's length is four. If not, we just print the warning and
            // proceed with the game loop.
            Ok(_) if input.len() != 4 => println!("Number of four digits is needed"),

            // Next, according to our game's rules, all digits of the numbers should be different.
            // So we call a game method that will check this for us. check_unique_digits() returns
            // a bool typed value.
            Ok(_) if !the_game.check_unique_digits(input) => println!("Digits must be unique"),

            // If previous checks have filtered us a valid number, we'll ask our game object to
            // check this number against the secret one. If it matches, we will get the true bool
            // value, print the win message with a number of tries needed to guess the right answer
            // and break the loop so game will end.
            Ok(_) if the_game.guess(input) => {
                println!("You won in {} tries!", the_game.tries + 1);
                break;
            },

            // If the input number was correct, but didn't match the secret value, we'll analyze it
            // and print the number of "cows" (digit exists, but doesn't match position) and
            // "bulls" (digit exists in secret number and matches position).
            Ok(_) => {
                // Here we ask the game object for tuple containing cows and bulls. We use
                // automatic type allocation and our code expects simple integers, so we don't
                // really need to think about particular type of these bindings at the moment.
                let (cows, bulls) = the_game.try(input);

                // We ask the game object to analyze acquired result and save hints on digit
                // positions that are being entered
                the_game.analyze(input, cows, bulls);

                // Now we print number of found matches if there was any
                if cows == 0 && bulls == 0 {
                    println!("Nothing found");
                } else {
                    println!("Found {} cows and {} bulls", cows, bulls);
                }
            }

            // So we failed to parse our input string as integer, so it must be a command. We start
            // another match operator.
            Err(_) => match input {

                // If we encounter an empty value, we just restart the game loop waiting for
                // non-empty command.
                "" => continue,

                // Here we define a pattern that matches one of these strings for a command that
                // quits the game. The break operator will end the game loop and since there's
                // nothing after this loop, the application will close returning user to shell.
                "q" | "quit" | "exit" => break,

                // We'll want to show user a list of available commands, so we call the
                // print_help() function which will handle this for us.
                "h" | "help" | "?" => print_help(),

                // This command calls print_hint(). Read about it below.
                "s" | "stats" => print_hint(the_game.hint_table),

                // This simple command recursively calls the main() function effecrively restarting
                // the game. Make sure to break the loop, so we don't restart game loop after we
                // have returned from this call.

                // Note, that this kind of implementation is not really good one, but it'll be fine
                // for this tutorial. It's drawback is that with every game restart the local stack
                // increases and allocates a new game object that's data is being piled up in the
                // heap.
                "r" | "restart" => {
                    main();
                    break;
                },

                // In case of any other input, we just print a message that we didn't get what user
                // wanted and hint him to use help command.
                _  => println!("Unknown command: \"{}\". Enter 'h' for help", input),
            },
        };
    }
}

// This function just prints out the list of available game commands
fn print_help() {
    println!("r, restart    - Restart game");
    println!("q, quit, exit - Quit game");
    println!("h, help, ?    - This text");
    println!("s, stats      - Check out some hints on potential digit positions");
    println!("<NNNN>        - Enter four unique digits to guess the number and win");
}

// This functions take a two-dimmensional array of special typed values (see more in the game
// module description)
fn print_hint(table: [[Hint; 4]; 10]) {

    // Print position numbers
    println!("   1 2 3 4");

    // Loop through 10 digits from 0 to 9 inclusively
    for i in 0..10 {

        // Print the digit
        print!("{}: ", i);

        // Then loop through four available positions
        for j in 0..4 {

            // For each value of enum type Hint (see definition in game module) we print respective
            // character
            print!("{} ", match table[i][j] {
                Hint::Unknown => " ",
                Hint::Maybe   => "?",
                Hint::Here    => "+",
                Hint::NotHere => "-",
            });
        }

        // Print the new line character to finish line for this digit
        print!("\n");
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::WlcHandle;
use rustwlc::types::interface::*;

fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: output_created,
            destroyed: output_destroyed,
            focus: output_focus,
            resolution: output_resolution,

            render: RenderInterface {
                pre: output_render_pre,
                post: output_render_post
            }
        },
        view: ViewInterface {
            created: view_created,
            destroyed: view_destroyed,
            focus: view_focus,
            move_to_output: view_move_to_output,
            request: RequestInterface {
                geometry: view_request_geometry,
                state: view_request_state,
                move_: view_request_move,
                resize: view_request_resize,
                render: RenderInterface {
                    pre: view_request_render_pre,
                    post: view_request_render_post
                }
            },
            keyboard: KeyboardInterface {
                key: keyboard_key
            },
            pointer: PointerInterface {
                button: pointer_button,
                scroll: pointer_scroll,
                motion: pointer_motion
            },
            touch: TouchInterface {
                touch: touch_touch
            },
            compositor: CompositorInterface {
                ready: compositor_ready
            },
            input: InputInterface {
                created: input_created,
                destroyed: input_destroyed
            }
        }
    };
    println!("Created interface {:?}", interface);

    if !rustwlc::init(&interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

// Hook up basic callbacks

fn output_created(handle: WlcHandle) -> bool {
    println!("output_created");
    return true;
}

fn output_destroyed(handle: WlcHandle) {
    println!("output_destroyed");
}

fn output_focus(handle: WlcHandle, focused: bool) {
    println!("output_focus: {}", focused);
}

fn output_resolution(handle: WlcHandle, old_size: Size, new_size: Size) {
    println!("output_resolution: {} to {}", old_size, new_size)
}

fn output_render_pre(handle: WlcHandle) {
    println!("output_render_pre");
}

fn output_render_post(handle: WlcHandle) {
    println!("output_render_post");
}

fn view_created(handle: WlcHandle) -> bool {
    println!("view_created");
    true
}

fn view_destroyed(handle: WlcHandle) {
    println!("view_destroyed");
}

fn view_focus(current: WlcHandle, focused: bool) {
    println!("view_focus: {}", focused);
}

fn view_move_to_output(current: WlcHandle, q1: WlcHandle, q2: WlcHandle) {
    println!("view_move_to_output");
}

fn view_request_geometry(handle: WlcHandle, geometry: Geometry) {
    println!("view_request_geometry: call wlc_view_set_geometry({:?})", geometry);
}

fn view_request_state(handle: WlcHandle, state: ViewState) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
}

fn view_request_move(handle: WlcHandle, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

fn view_request_resize(handle: WlcHandle, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

fn view_request_render_pre(handle: WlcHandle) {
    println!("view_request_render_pre");
}

fn view_request_render_post(handle: WlcHandle) {
    println!("view_request_render_post");
}

fn keyboard_key(handle: WlcHandle, button: libc::c_uint, mods: KeyboardModifiers, time: u32,
                state: ButtonState, point: Point) -> bool {
    false
}

fn pointer_button(handle: WlcHandle, button: libc::c_uint, mods: KeyboardModifiers,
                  time: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: time {}, point {}", time, point);
    false
}

fn pointer_scroll(handle: WlcHandle, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

fn pointer_motion(handle: WlcHandle, dist: u32, point: Point) -> bool {
    false
}

fn touch_touch(handle: WlcHandle, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

fn compositor_ready() {
    println!("Preparing compositor!");
}

fn input_created(device: LibinputDevice) {
    println!("input_created");
}

fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<commit_msg>Successful test of skeleton callbacks<commit_after>#![feature(libc)]
extern crate libc;

extern crate rustwlc;

use rustwlc::types;
use rustwlc::types::*;
//use rustwlc::types::LibinputDevice;
use rustwlc::handle::WlcHandle;
use rustwlc::types::interface::*;

fn main() {
    let interface: WlcInterface = WlcInterface {
        output: OutputInterface {
            created: output_created,
            destroyed: output_destroyed,
            focus: output_focus,
            resolution: output_resolution,

            render: RenderInterface {
                pre: output_render_pre,
                post: output_render_post
            }
        },
        view: ViewInterface {
            created: view_created,
            destroyed: view_destroyed,
            focus: view_focus,
            move_to_output: view_move_to_output,
            request: RequestInterface {
                geometry: view_request_geometry,
                state: view_request_state,
                move_: view_request_move,
                resize: view_request_resize,
                render: RenderInterface {
                    pre: view_request_render_pre,
                    post: view_request_render_post
                }
            }
        },
        keyboard: KeyboardInterface {
            key: keyboard_key
        },
        pointer: PointerInterface {
            button: pointer_button,
            scroll: pointer_scroll,
            motion: pointer_motion
        },
        touch: TouchInterface {
            touch: touch_touch
        },
        compositor: CompositorInterface {
            ready: compositor_ready
        },
        input: InputInterface {
            created: input_created,
            destroyed: input_destroyed
        }
    };
    // Interfaces don't derive debug
    //println!("Created interface {:?}", interface);

    if !rustwlc::init(interface) {
        panic!("Unable to initialize wlc!");
    }
    rustwlc::run_wlc();
}

// Hook up basic callbacks

extern fn output_created(handle: WlcHandle) -> bool {
    println!("output_created");
    return true;
}

extern fn output_destroyed(handle: WlcHandle) {
    println!("output_destroyed");
}

extern fn output_focus(handle: WlcHandle, focused: bool) {
    println!("output_focus: {}", focused);
}

extern fn output_resolution(handle: WlcHandle, old_size: Size, new_size: Size) {
    println!("output_resolution: {:?} to {:?}", old_size, new_size)
}

extern fn output_render_pre(handle: WlcHandle) {
    println!("output_render_pre");
}

extern fn output_render_post(handle: WlcHandle) {
    println!("output_render_post");
}

extern fn view_created(handle: WlcHandle) -> bool {
    println!("view_created");
    true
}

extern fn view_destroyed(handle: WlcHandle) {
    println!("view_destroyed");
}

extern fn view_focus(current: WlcHandle, focused: bool) {
    println!("view_focus: {}", focused);
}

extern fn view_move_to_output(current: WlcHandle, q1: WlcHandle, q2: WlcHandle) {
    println!("view_move_to_output");
}

extern fn view_request_geometry(handle: WlcHandle, geometry: Geometry) {
    println!("view_request_geometry: call wlc_view_set_geometry({:?})", geometry);
}

extern fn view_request_state(handle: WlcHandle, state: ViewState, handled: bool) {
    println!("view_request_state: call wlc_view_set_state({:?})", state);
}

extern fn view_request_move(handle: WlcHandle, dest: Point) {
    println!("view_request_move: to {}, start interactive mode.", dest);
}

extern fn view_request_resize(handle: WlcHandle, edge: ResizeEdge, location: Point) {
    println!("view_request_resize: size {:?}, to {}, start interactive mode.",
             edge, location);
}

extern fn view_request_render_pre(handle: WlcHandle) {
    println!("view_request_render_pre");
}

extern fn view_request_render_post(handle: WlcHandle) {
    println!("view_request_render_post");
}

extern fn keyboard_key(handle: WlcHandle, time: u32, mods: KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    false
}

extern fn pointer_button(handle: WlcHandle, button: libc::c_uint, mods: KeyboardModifiers,
                  time: u32, state: ButtonState, point: Point) -> bool {
    println!("pointer_button: time {}, point {}", time, point);
    false
}

extern fn pointer_scroll(handle: WlcHandle, button: u32, mods: KeyboardModifiers,
                  axis: ScrollAxis, heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

extern fn pointer_motion(handle: WlcHandle, dist: u32, point: Point) {
    println!("Pointer moved {} pixels? to {}", dist, point);
}

extern fn touch_touch(handle: WlcHandle, time: libc::c_uint, mods: KeyboardModifiers,
               touch: TouchType, key: i32, point: Point) -> bool {
    false
}

extern fn compositor_ready() {
    println!("Preparing compositor!");
}

extern fn input_created(device: LibinputDevice) -> bool {
    println!("input_created");
    false
}

extern fn input_destroyed(device: LibinputDevice) {
    println!("input_destroyed");
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    #![show_api]

    program
        = (expr / decl / stmt)*

    decl
        = class_decl > to_class_decl
        / method_decl > to_method_decl

    class_decl
        = kw_class spacing ident class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def spacing ident lparen params_list? rparen block

    block
        = lbracket (stmt / expr)* rbracket

    stmt
        = if_stmt > to_if_stmt
        / while_stmt > to_while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    assign_expr
        = ident bind_op expr

    expr = cond_expr

    cond_expr
        = spacing add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr > to_assign_expr
        / call > call_expr
        / string > string_expr
        / number > number_expr
        / ident > variable_expr
        / lparen expr rparen

    call
        = (ident ".")? ident lparen arg_list? rparen

    arg_list
        = (expr ("," spacing expr)*)

    params_list
        = (ident ("," spacing ident)*)

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    ident = !digit !keyword ident_char+ spacing > to_string
    ident_char = ["a-zA-Z0-9_"]
    sym_char = ["!@#$%^&*()-=_+[]\\{}|;:,./<>? \n\r\t"]

    digit = ["0-9"]
    number = digit+ spacing > to_number
    string = (dbl_quot_string / sng_quot_string) spacing
    dbl_quot_string = dbl_quot (ident_char / digit / sym_char)* dbl_quot
    sng_quot_string = sng_quot (ident_char / digit / sym_char)* sng_quot
    spacing = [" \n\r\t"]* -> ()

    kw_def = "def"
    kw_class = "class"
    kw_true = "true"
    kw_false = "false"
    kw_nil = "nil"
    kw_if = "if"
    kw_else = "else"
    kw_while = "while"
    kw_tail = !ident_char spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil
        / kw_tail

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = spacing "{" spacing
    rbracket = spacing "}" spacing
    dbl_quot = "\""
    sng_quot = "'"

    terminator = (";" / "\n") spacing

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Variable(String),
        NumberLiteral(u32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        Call(Option<String>, String, Option<(PExpr, Vec<PExpr>)>),
        AssingExpr(String, PExpr),
        MethodDecl(String, Option<(String, Vec<String>)>, Vec<PExpr>),
        ClassDecl(String, Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>),
        IfStatement(PExpr, Vec<PExpr>, Option<Vec<PExpr>>),
        WhileStatement(PExpr, Vec<PExpr>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn number_expr(value: u32) -> PExpr {
        Box::new(NumberLiteral(value))
    }

    fn string_expr(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn variable_expr(ident: String) -> PExpr {
        Box::new(Variable(ident))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_expr(receiver: Option<String>, method: String, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn to_assign_expr(variable: String, exp: PExpr) -> PExpr {
        Box::new(AssingExpr(variable, exp))
    }

    fn to_class_decl(name: String, methods: Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>) -> PExpr {
        Box::new(ClassDecl(name, methods))
    }

    fn to_method_decl(name: String, params: Option<(String, Vec<String>)>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(name, params, body))
    }

    fn to_if_stmt(condition: PExpr, block: Vec<PExpr>, else_block: Option<Vec<PExpr>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn to_while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }
}

fn analyse_state(state: ParseState<StrStream, awesome::PExpr>) {
    match state.into_result() {
        Ok((success, error)) => {
            if success.partial_read() {
                println!("Partial match: {:?} because: {}", success.data, error);
            } else {
                println!("Full match: {:?}", success.data);
            }
        }
        Err(error) => {
            println!("Error: {}", error);
        }
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:?}", awesome::parse_program(contents.stream()));
}
<commit_msg>s/params_list/param_list/g<commit_after>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    #![show_api]

    program
        = (expr / decl / stmt)*

    decl
        = class_decl > to_class_decl
        / method_decl > to_method_decl

    class_decl
        = kw_class spacing ident class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def spacing ident lparen param_list? rparen block

    block
        = lbracket (stmt / expr)* rbracket

    stmt
        = if_stmt > to_if_stmt
        / while_stmt > to_while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    assign_expr
        = ident bind_op expr

    expr = cond_expr

    cond_expr
        = spacing add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr > to_assign_expr
        / call > call_expr
        / string > string_expr
        / number > number_expr
        / ident > variable_expr
        / lparen expr rparen

    call
        = (ident ".")? ident lparen arg_list? rparen

    arg_list
        = (expr ("," spacing expr)*)

    param_list
        = (ident ("," spacing ident)*)

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    ident = !digit !keyword ident_char+ spacing > to_string
    ident_char = ["a-zA-Z0-9_"]
    sym_char = ["!@#$%^&*()-=_+[]\\{}|;:,./<>? \n\r\t"]

    digit = ["0-9"]
    number = digit+ spacing > to_number
    string = (dbl_quot_string / sng_quot_string) spacing
    dbl_quot_string = dbl_quot (ident_char / digit / sym_char)* dbl_quot
    sng_quot_string = sng_quot (ident_char / digit / sym_char)* sng_quot
    spacing = [" \n\r\t"]* -> ()

    kw_def = "def"
    kw_class = "class"
    kw_true = "true"
    kw_false = "false"
    kw_nil = "nil"
    kw_if = "if"
    kw_else = "else"
    kw_while = "while"
    kw_tail = !ident_char spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil
        / kw_tail

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = spacing "{" spacing
    rbracket = spacing "}" spacing
    dbl_quot = "\""
    sng_quot = "'"

    terminator = (";" / "\n") spacing

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Variable(String),
        NumberLiteral(u32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        Call(Option<String>, String, Option<(PExpr, Vec<PExpr>)>),
        AssingExpr(String, PExpr),
        MethodDecl(String, Option<(String, Vec<String>)>, Vec<PExpr>),
        ClassDecl(String, Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>),
        IfStatement(PExpr, Vec<PExpr>, Option<Vec<PExpr>>),
        WhileStatement(PExpr, Vec<PExpr>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn number_expr(value: u32) -> PExpr {
        Box::new(NumberLiteral(value))
    }

    fn string_expr(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn variable_expr(ident: String) -> PExpr {
        Box::new(Variable(ident))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_expr(receiver: Option<String>, method: String, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn to_assign_expr(variable: String, exp: PExpr) -> PExpr {
        Box::new(AssingExpr(variable, exp))
    }

    fn to_class_decl(name: String, methods: Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>) -> PExpr {
        Box::new(ClassDecl(name, methods))
    }

    fn to_method_decl(name: String, params: Option<(String, Vec<String>)>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(name, params, body))
    }

    fn to_if_stmt(condition: PExpr, block: Vec<PExpr>, else_block: Option<Vec<PExpr>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn to_while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }
}

fn analyse_state(state: ParseState<StrStream, awesome::PExpr>) {
    match state.into_result() {
        Ok((success, error)) => {
            if success.partial_read() {
                println!("Partial match: {:?} because: {}", success.data, error);
            } else {
                println!("Full match: {:?}", success.data);
            }
        }
        Err(error) => {
            println!("Error: {}", error);
        }
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:?}", awesome::parse_program(contents.stream()));
}
<|endoftext|>


<commit_before>#![feature(globs)]

extern crate rdb;
use std::os;
use std::io::{BufferedReader, File};

fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("Usage: {} [list of files]", args[0]);
        panic!();
    }

    let file = File::open(&Path::new(args[1].to_string()));
    let mut reader = BufferedReader::new(file);

    rdb::parse(&mut reader)
}
<commit_msg>Make it public to avoid warnings<commit_after>#![feature(globs)]

extern crate rdb;
use std::os;
use std::io::{BufferedReader, File};

pub fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("Usage: {} [list of files]", args[0]);
        panic!();
    }

    let file = File::open(&Path::new(args[1].to_string()));
    let mut reader = BufferedReader::new(file);

    rdb::parse(&mut reader)
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use zip::write::FileOptions;
use std::fs::File;

extern crate zip;

fn main() {
    if let Err(err) = create_archive() {
        //If there was a problem creating the zip
        //archive, print the error and exit(1).
        println!("Error: {}", err);
        std::process::exit(1);
    }
}

/*
 * This function creates a zip archive, and returns a Result
 * that indicates if all operations were successful.
 *
 * The first command-line argument is the name and path of the zip file to be created,
 * and all the other arguments are the names and paths of the files to be archived
 *
 */
fn create_archive() -> Result<(), String> {
    //If there are less than 3 command-line arguments, return an error
    if std::env::args().count() < 3 {
        return Err("Usage: zipper <zip file> <file to archive> <file to archive> ...".to_string());
    }

    //The 1st command line argument is the name of the zip file.
    //It's not necessary to error check because we already checked
    //the number of command-line arguments earlier
    let zipfile_name = std::env::args().nth(1).unwrap();

    let path_to_zipfile = std::path::Path::new(&zipfile_name);
    let zipfile = match std::fs::File::create(&path_to_zipfile) {
        Err(e) => return Err(format!("Error creating {}: {}", zipfile_name, e)),
        Ok(f)  => f,
    };
    let mut zip = zip::ZipWriter::new(zipfile);

    //Iterate over the command-line arguments for the names of the
    //files we wish to archive. Skip the first two arguments.
    for arg in std::env::args().skip(2) {
        let filename = &arg;

        //Extract the raw filename out of the full path entered by the user
        //This returns the file name as a type &OsStr slice instead of a &str slice
        let name_of_file = match std::path::Path::new(filename).file_name() {
            Some(c) => c,
            None    => return Err(format!("{}: Invalid file name", filename)),
        };

        //Redefine and convert the &OsStr slice to a standard &str slice.
        //Checks if the filename is valid unicode.
        let name_of_file = match name_of_file.to_str() {
            Some(c) => c,
            None    => return Err(format!("{}: Invalid file name", filename)),
        };

        //Open the file and check for errors
        let mut f = match File::open(filename) {
            Err(e) => return Err(format!("{}: {}", filename, e)),
            Ok(f)  => f,
        };

        //Get the file metadata so we can get the file size. Also check for errors
        let file_metadata = match f.metadata() {
            Err(e) => return Err(format!("{}: {}", filename, e)),
            Ok(f)  => f,
        };

        //Get the exact size of the file from the file metadata
        let file_size = file_metadata.len() as usize;

        //Create a buffer to store the file contents that is exactly the size of the file + 1
        let mut contents: Vec<u8> = Vec::with_capacity(file_size + 1);

        //Read the file and check for errors
        f.read_to_end(&mut contents).map_err(|e| e.to_string())?;

        //Now compress the file and write it into the zip archive
        zip.start_file(name_of_file, FileOptions::default())
            .map_err(|e| e.to_string())?;
        zip.write_all(contents.as_slice())
            .map_err(|e| e.to_string())?;

    } //end for loop

    //Finish the zip file
    //try!(zip.finish().map_err(|e| e.to_string()));
    zip.finish().map_err(|e| e.to_string())?;

    //Return an empty Ok tuple because we had no errors.
    Ok(())
}
<commit_msg>Small cleanup<commit_after>use std::io::prelude::*;
use zip::write::FileOptions;
use std::fs::File;

extern crate zip;

fn main() {
    let mut exit_code = 0;
    if let Err(err) = create_archive() {
        //If there was a problem creating the zip
        //archive, print the error and exit(1).
        println!("Error: {}", err);
        exit_code = 1;
    }

    //Exit with an exit code so that shell scripts can error-check
    std::process::exit(exit_code);
}

/*
 * This function creates a zip archive, and returns a Result
 * that indicates if all operations were successful.
 *
 * The first command-line argument is the name and path of the zip file to be created,
 * and all the other arguments are the names and paths of the files to be archived
 *
 */
fn create_archive() -> Result<(), String> {
    //If there are less than 3 command-line arguments, return an error
    if std::env::args().count() < 3 {
        return Err("Usage: zipper <zip file> <file to archive> <file to archive> ...".to_string());
    }

    //The 1st command line argument is the name of the zip file.
    //It's not necessary to error check because we already checked
    //the number of command-line arguments earlier
    let zipfile_name = std::env::args().nth(1).unwrap();

    let path_to_zipfile = std::path::Path::new(&zipfile_name);
    let zipfile = match std::fs::File::create(&path_to_zipfile) {
        Err(e) => return Err(format!("Error creating {}: {}", zipfile_name, e)),
        Ok(f)  => f,
    };
    let mut zip = zip::ZipWriter::new(zipfile);

    //Iterate over the command-line arguments for the names of the
    //files we wish to archive. Skip the first two arguments.
    for arg in std::env::args().skip(2) {
        let filename = &arg;

        //Extract the raw filename out of the full path entered by the user
        //This returns the file name as a type &OsStr slice instead of a &str slice
        let name_of_file = match std::path::Path::new(filename).file_name() {
            Some(c) => c,
            None    => return Err(format!("{}: Invalid file name", filename)),
        };

        //Redefine and convert the &OsStr slice to a standard &str slice.
        //Checks if the filename is valid unicode.
        let name_of_file = match name_of_file.to_str() {
            Some(c) => c,
            None    => return Err(format!("{}: Invalid file name", filename)),
        };

        //Open the file and check for errors
        let mut f = match File::open(filename) {
            Err(e) => return Err(format!("{}: {}", filename, e)),
            Ok(f)  => f,
        };

        //Get the file metadata so we can get the file size. Also check for errors
        let file_metadata = match f.metadata() {
            Err(e) => return Err(format!("{}: {}", filename, e)),
            Ok(f)  => f,
        };

        //Get the exact size of the file from the file metadata
        let file_size = file_metadata.len() as usize;

        //Create a buffer to store the file contents that is exactly the size of the file + 1
        let mut contents: Vec<u8> = Vec::with_capacity(file_size + 1);

        //Read the file and check for errors
        f.read_to_end(&mut contents).map_err(|e| e.to_string())?;

        //Now compress the file and write it into the zip archive
        zip.start_file(name_of_file, FileOptions::default())
            .map_err(|e| e.to_string())?;
        zip.write_all(contents.as_slice())
            .map_err(|e| e.to_string())?;

    } //end for loop

    //Finish the zip file
    //try!(zip.finish().map_err(|e| e.to_string()));
    zip.finish().map_err(|e| e.to_string())?;

    //Return an empty Ok tuple because we had no errors.
    Ok(())
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug)]
enum PBType {
    Integer64,
    String,
}

#[derive(Clone, Debug)]
struct PBField {
    name: String,
    tag: u8,
    field_type: PBType,
}

#[derive(Clone, Debug)]
struct PBMessage {
    name: String,
    fields: Vec<PBField>,
}

#[derive(Clone, Copy, Debug)]
enum PBWireType {
    VarInt,
    Fixed64,
    LengthDelim,
    Fixed32,
    Reserved,
}

struct TagValue<'a> {
    tag: u8,
    wire_type: PBWireType,
    value: &'a [u8],
}

#[derive(Clone)]
struct ParserPosition<'a> {
    slice: &'a [u8],
    tag: u8,
    wire_type: PBWireType,
}

trait InitParserPosition<'a> {
    fn init(msg_slice: &'a [u8]) -> ParserPosition<'a>;
}

impl<'a> InitParserPosition<'a> for ParserPosition<'a> {
    fn init(msg_slice: &'a [u8]) -> ParserPosition<'a> {
        ParserPosition {
            slice: msg_slice,
            tag: 0,
            wire_type: PBWireType::Reserved,
        }
    }
}

static IDX2WIRE_TYPE: &'static [PBWireType; 6] = &[PBWireType::VarInt,
                                                   PBWireType::Fixed64,
                                                   PBWireType::LengthDelim,
                                                   PBWireType::Reserved,
                                                   PBWireType::Reserved,
                                                   PBWireType::Fixed32];
#[derive(Clone, Copy, Debug)]
enum PBParseError {
    UnknownWireType(usize),
}

fn PBParseNext<'a>(pos: ParserPosition<'a>)
                   -> Result<(TagValue<'a>, ParserPosition<'a>), PBParseError> {
    let mut p = pos.clone();

    p.tag = p.slice[0] >> 3;
    let wire_type_idx = (p.slice[0] & 7) as usize;
    if wire_type_idx >= IDX2WIRE_TYPE.len() {
        return Err(PBParseError::UnknownWireType(wire_type_idx));
    }
    p.wire_type = IDX2WIRE_TYPE[wire_type_idx];

    let mut value = match p.wire_type {
        PBWireType::LengthDelim => {
            let offset = p.slice[1] as usize;
            let start = 2;
            let end = 2 + offset;
            let x = &p.slice[start..end];
            p.slice = &p.slice[end..];
            x
        }
        _ => &[],
    };
    Ok((TagValue {
            value: value,
            tag: p.tag,
            wire_type: p.wire_type,
        },
        p.clone()))
}

use std::str;

#[derive(Debug)]
enum ReprError {
    InvalidWireAndSchemaType,
    Utf8Error(std::str::Utf8Error),
}

fn StringRepr<'a>(wire_type: PBWireType,
                  schema_type: PBType,
                  bytes: &'a [u8])
                  -> Result<String, ReprError> {
    match (wire_type, schema_type) {
        (PBWireType::LengthDelim, PBType::String) => {
            let x = str::from_utf8(bytes);
            match x {
                Ok(y) => Ok(String::from(y)),
                Err(y) => Err(ReprError::Utf8Error(y)),
            }
        }
        _ => Err(ReprError::InvalidWireAndSchemaType),
    }
}

fn IntegerRepr<'a>(wire_type: PBWireType,
                   schema_type: PBType,
                   bytes: &'a [u8])
                   -> Result<i64, ReprError> {

    extern crate num;
    match (wire_type, schema_type) {
        (PBWireType::VarInt, PBType::Integer64) => {
            let mut pos: u8 = 0;
            let mut res: i64 = 0;
            for b in bytes {
                // I'm assuming I have an endieness problem here?
                for i in 0..7 {
                  let bit_shift = 6-i;
                  let pow_add = pos + 6 - i;
                  print!("{} {} {} {}", i, bit_shift, pow_add, ((b >> bit_shift) & 1u8));
                  if ((b >> (6-i)) & 1u8) == 1u8 {
                    res += num::pow(2, (pow_add) as usize);
                    print!(" {} {}",  num::pow(2, (pow_add) as usize), res);
                  }
                  print!("\n");
                }
                pos += 7;
            }
            Ok(res)
        }
        _ => Err(ReprError::InvalidWireAndSchemaType),
    }
}

fn main() {
    /*
     * Sample ProtocolBuffer message for schema:
     *
     *     message Test2 {
     *       required string a = 1;
     *       required string b = 2;
     *     }
     *
     * with a = test, b = testing
     *
     * @see https://developers.google.com/protocol-buffers/docs/encoding
     */
    let msg = vec![0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x04, 0x74, 0x65,
                   0x73, 0x74];
    let msg_slice = msg.as_slice();

    let (mut x, mut pp) = PBParseNext(ParserPosition::init(msg_slice)).unwrap();

    print!("Tag   = {}\n", x.tag);
    print!("Value = {}\n",
           StringRepr(x.wire_type, PBType::String, x.value).unwrap());

    let (x, pp) = PBParseNext(pp).unwrap();

    print!("Tag   = {}\n", x.tag);
    print!("Value = {}\n",
           StringRepr(x.wire_type, PBType::String, x.value).unwrap());

    print!("300 = {}\n",
           IntegerRepr(PBWireType::VarInt, PBType::Integer64, &[0xacu8, 0x02u8]).unwrap());
}
<commit_msg>integer rep of string<commit_after>#[derive(Clone, Copy, Debug)]
enum PBType {
    Integer64,
    String,
}

#[derive(Clone, Debug)]
struct PBField {
    name: String,
    tag: u8,
    field_type: PBType,
}

#[derive(Clone, Debug)]
struct PBMessage {
    name: String,
    fields: Vec<PBField>,
}

#[derive(Clone, Copy, Debug)]
enum PBWireType {
    VarInt,
    Fixed64,
    LengthDelim,
    Fixed32,
    Reserved,
}

struct TagValue<'a> {
    tag: u8,
    wire_type: PBWireType,
    value: &'a [u8],
}

#[derive(Clone)]
struct ParserPosition<'a> {
    slice: &'a [u8],
    tag: u8,
    wire_type: PBWireType,
}

trait InitParserPosition<'a> {
    fn init(msg_slice: &'a [u8]) -> ParserPosition<'a>;
}

impl<'a> InitParserPosition<'a> for ParserPosition<'a> {
    fn init(msg_slice: &'a [u8]) -> ParserPosition<'a> {
        ParserPosition {
            slice: msg_slice,
            tag: 0,
            wire_type: PBWireType::Reserved,
        }
    }
}

static IDX2WIRE_TYPE: &'static [PBWireType; 6] = &[PBWireType::VarInt,
                                                   PBWireType::Fixed64,
                                                   PBWireType::LengthDelim,
                                                   PBWireType::Reserved,
                                                   PBWireType::Reserved,
                                                   PBWireType::Fixed32];
#[derive(Clone, Copy, Debug)]
enum PBParseError {
    UnknownWireType(usize),
}

fn PBParseNext<'a>(pos: ParserPosition<'a>)
                   -> Result<(TagValue<'a>, ParserPosition<'a>), PBParseError> {
    let mut p = pos.clone();

    p.tag = p.slice[0] >> 3;
    let wire_type_idx = (p.slice[0] & 7) as usize;
    if wire_type_idx >= IDX2WIRE_TYPE.len() {
        return Err(PBParseError::UnknownWireType(wire_type_idx));
    }
    p.wire_type = IDX2WIRE_TYPE[wire_type_idx];

    let mut value = match p.wire_type {
        PBWireType::LengthDelim => {
            let offset = p.slice[1] as usize;
            let start = 2;
            let end = 2 + offset;
            let x = &p.slice[start..end];
            p.slice = &p.slice[end..];
            x
        }
        _ => &[],
    };
    Ok((TagValue {
            value: value,
            tag: p.tag,
            wire_type: p.wire_type,
        },
        p.clone()))
}

use std::str;

#[derive(Debug)]
enum ReprError {
    InvalidWireAndSchemaType,
    Utf8Error(std::str::Utf8Error),
}

fn StringRepr<'a>(wire_type: PBWireType,
                  schema_type: PBType,
                  bytes: &'a [u8])
                  -> Result<String, ReprError> {
    match (wire_type, schema_type) {
        (PBWireType::LengthDelim, PBType::String) => {
            let x = str::from_utf8(bytes);
            match x {
                Ok(y) => Ok(String::from(y)),
                Err(y) => Err(ReprError::Utf8Error(y)),
            }
        }
        (PBWireType::VarInt, PBType::Integer64) => {
          match IntegerRepr(wire_type, schema_type, bytes) {
            Ok(i) => Ok(String::from(format!("{}", i))),
            Err(e) => Err(e)
          }
        }
        _ => Err(ReprError::InvalidWireAndSchemaType),
    }
}

fn IntegerRepr<'a>(wire_type: PBWireType,
                   schema_type: PBType,
                   bytes: &'a [u8])
                   -> Result<i64, ReprError> {

    extern crate num;
    match (wire_type, schema_type) {
        (PBWireType::VarInt, PBType::Integer64) => {
            let mut pos: u8 = 0;
            let mut res: i64 = 0;
            for b in bytes {
                // I'm assuming I have an endieness problem here?
                for i in 0..7 {
                  let bit_shift = 6-i;
                  let pow_add = pos + 6 - i;
                  if ((b >> (6-i)) & 1u8) == 1u8 {
                    res += num::pow(2, (pow_add) as usize);
                  }
                }
                pos += 7;
            }
            Ok(res)
        }
        _ => Err(ReprError::InvalidWireAndSchemaType),
    }
}

fn main() {
    /*
     * Sample ProtocolBuffer message for schema:
     *
     *     message Test2 {
     *       required string a = 1;
     *       required string b = 2;
     *     }
     *
     * with a = test, b = testing
     *
     * @see https://developers.google.com/protocol-buffers/docs/encoding
     */
    let msg = vec![0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x04, 0x74, 0x65,
                   0x73, 0x74];
    let msg_slice = msg.as_slice();

    let (mut x, mut pp) = PBParseNext(ParserPosition::init(msg_slice)).unwrap();

    print!("Tag   = {}\n", x.tag);
    print!("Value = {}\n",
           StringRepr(x.wire_type, PBType::String, x.value).unwrap());

    let (x, pp) = PBParseNext(pp).unwrap();

    print!("Tag   = {}\n", x.tag);
    print!("Value = {}\n",
           StringRepr(x.wire_type, PBType::String, x.value).unwrap());

    print!("300 = {}\n",
           IntegerRepr(PBWireType::VarInt, PBType::Integer64, &[0xacu8, 0x02u8]).unwrap());
    print!("300 = string {}\n",
           StringRepr(PBWireType::VarInt, PBType::Integer64, &[0xacu8, 0x02u8]).unwrap());
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;

fn print_arg_error() {
    println!("incorrect arguments passed");
}

struct CSV_descriptor<'a> {
    file_path: &'a  Path,
    delimiter:      char,
    quote:          Option<char>,
}

impl<'a> std::fmt::Display for CSV_descriptor<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} {} {:?}", self.file_path.display(), self.delimiter, self.quote)
    }
}

fn parse_args<'a>(path_arg:         &'a String,
                  delimiter_arg:    &'a String,
                  quote_arg:        &'a String) -> Result<CSV_descriptor<'a>, &'static str>
{

    let csv_file_path = Path::new(path_arg);

    let csv_delimiter = match delimiter_arg.chars().next() {
                            Some(result) => result,
                            None         => return Err("incorrect delimiter"),
                        };

    let csv_quote     = quote_arg.chars().next();

    Ok(CSV_descriptor {file_path: &csv_file_path, delimiter: csv_delimiter, quote: csv_quote})
}

fn get_csv_cols(csv_desc: CSV_descriptor) -> Result<Vec<String>, String> {

    let csv_file = match File::open(csv_desc.file_path) {
        Err(why) => panic!("couldn't open csv @ {}: {}", csv_desc.file_path.display(), why),
        Ok(file) => file,
    };

    let csv_reader = BufReader::new(csv_file);

    let mut csv_line_iter = csv_reader.lines();

    let csv_header: String = match csv_line_iter.next() {
        Some(result) => match result {
                            Err(why) => return Err(format!("error getting csv header: {}", why)),
                            Ok(header) => header,
                        },
        None         => return Err("csv header reading failed".to_string()),
    };

    let csv_cols: Vec<String> = {
        let cols_iter = csv_header.split(csv_desc.delimiter);
        match csv_desc.quote {
            Some(q) => cols_iter.map(|s| {s.trim_matches(q).to_string()}).collect(),
            None    => cols_iter.map(|s| {s.to_string()}).collect(),
        }
    };

    Ok(csv_cols)
}

fn main() {

/*

1. Parse arguments
2. Open CSV files
3. Get columns (cols_N)
4. Get intersection of those two sets of columns(cols_to_compare)
5. Create {column name : column index in cols_N} dicts
6. Create {CSV_col_value : CSV row index in file} dicts, where CSV_col_value is a unique key made of the value of several CSV columns.
   For example, {Alex38 : 76}. In this example a name and age form a unique key for the 76th CSV row.
7. Get intersection of key sets of dicts from step 6 (row_keys_to_compare)
8. Loop through row_keys_to_compare, use dicts from step 6 to get line numbers for CSV files
    8.1 Loop through cols_to_compare, use dicts from step 5 to extract column values from CSV rows(step 8)
    8.2 Compare values

Input parameters: CSV paths, delimiters, quotes

For example, ./main file_1.csv "," "'" file_2.csv " " ""

*/

    /*** 1 ***/
    let args: Vec<String> = env::args().collect();
    if args.len() != 7 {
        print_arg_error();
        return;
    };

    let csv_desc: CSV_descriptor = match parse_args(&args[1], &args[2], &args[3]) {
        Err(why)    => panic!("error parsing arguments: {}", why),
        Ok(result)  => result,
    };
    println!("{}", csv_desc);

    let csv_file = match File::open(csv_desc.file_path) {
        Err(why) => panic!("couldn't open csv @ {}: {}", csv_desc.file_path.display(), why),
        Ok(file) => file,
    };

    /*** 2 ***/
    //let csv_cols: Vec<String> = get_csv_cols(csv_desc);

}
<commit_msg>Moving on: column index, columns to compare<commit_after>use std::collections::{HashSet, HashMap};
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;

fn print_arg_error() {
    println!("incorrect arguments passed");
}

struct CSV_descriptor<'a> {
    file_path: &'a  Path,
    delimiter:      char,
    quote:          Option<char>,
}

impl<'a> std::fmt::Display for CSV_descriptor<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{} {} {:?}", self.file_path.display(), self.delimiter, self.quote)
    }
}

fn parse_args<'a>(path_arg:         &'a String,
                  delimiter_arg:    &'a String,
                  quote_arg:        &'a String) -> Result<CSV_descriptor<'a>, &'static str>
{

    let csv_file_path = Path::new(path_arg);

    let csv_delimiter = match delimiter_arg.chars().next() {
                            Some(result) => result,
                            None         => return Err("incorrect delimiter"),
                        };

    let csv_quote     = quote_arg.chars().next();

    Ok(CSV_descriptor {file_path: &csv_file_path, delimiter: csv_delimiter, quote: csv_quote})
}

fn get_csv_cols(csv_desc: CSV_descriptor) -> Result<Vec<String>, String> {

    let csv_file = match File::open(csv_desc.file_path) {
        Err(why) => panic!("couldn't open csv @ {}: {}", csv_desc.file_path.display(), why),
        Ok(file) => file,
    };

    let csv_reader = BufReader::new(csv_file);

    let mut csv_line_iter = csv_reader.lines();

    let csv_header: String = match csv_line_iter.next() {
        Some(result) => match result {
                            Err(why) => return Err(format!("error getting csv header: {}", why)),
                            Ok(header) => header,
                        },
        None         => return Err("csv header reading failed".to_string()),
    };

    let csv_cols: Vec<String> = {
        let cols_iter = csv_header.split(csv_desc.delimiter);
        match csv_desc.quote {
            Some(q) => cols_iter.map(|s| {s.trim_matches(q).to_string()}).collect(),
            None    => cols_iter.map(|s| {s.to_string()}).collect(),
        }
    };

    Ok(csv_cols)
}

fn main() {

/*

1. Parse arguments
2. Open CSV files
3. Get columns (cols_N)
4. Get intersection of those two sets of columns(cols_to_compare)
5. Create {column name : column index in cols_N} dicts
6. Create {CSV_col_value : CSV row index in file} dicts, where CSV_col_value is a unique key made of the value of several CSV columns.
   For example, {Alex38 : 76}. In this example a name and age form a unique key for the 76th CSV row.
7. Get intersection of key sets of dicts from step 6 (row_keys_to_compare)
8. Loop through row_keys_to_compare, use dicts from step 6 to get line numbers for CSV files
    8.1 Loop through cols_to_compare, use dicts from step 5 to extract column values from CSV rows(step 8)
    8.2 Compare values

Input parameters: CSV paths, delimiters, quotes

For example, ./main file_1.csv "," "'" file_2.csv " " ""

*/

    /*** 1 ***/
    let args: Vec<String> = env::args().collect();
    if args.len() != 7 {
        print_arg_error();
        return;
    };

    let csv_desc_1: CSV_descriptor = match parse_args(&args[1], &args[2], &args[3]) {
        Err(why)    => panic!("error parsing arguments for CSV #1: {}", why),
        Ok(result)  => result,
    };

    let csv_desc_2: CSV_descriptor = match parse_args(&args[4], &args[5], &args[6]) {
        Err(why)    => panic!("error parsing arguments for CSV #2: {}", why),
        Ok(result)  => result,
    };

    /*** 2&3 ***/
    let csv_cols_1: Vec<String> = match get_csv_cols(csv_desc_1) {
        Err(why) => panic!("couldn't get columns: {}", why),
        Ok(cols) => cols,
    };

    let csv_cols_2: Vec<String> = match get_csv_cols(csv_desc_2) {
        Err(why) => panic!("couldn't get columns: {}", why),
        Ok(cols) => cols,
    };

    /*** 5 ***/
    let mut csv_col_index_1 = HashMap::new();
    for i in 0..csv_cols_1.len() {
        let key = csv_cols_1[i].clone();
        if csv_col_index_1.contains_key(&key) {
            panic!("duplicate column found in CSV #1: {}", key);
        };
        csv_col_index_1.insert(key, i);
    }

    let mut csv_col_index_2 = HashMap::new();
    for i in 0..csv_cols_2.len() {
        let key = csv_cols_2[i].clone();
        if csv_col_index_2.contains_key(&key) {
            panic!("duplicate column found in CSV #1: {}", key);
        };
        csv_col_index_2.insert(key, i);
    }

    /*** 4 ***/
    let mut cols_to_compare = HashSet::new();
    for col_1 in csv_col_index_1.keys() {
        if csv_col_index_2.contains_key(col_1) {
            cols_to_compare.insert(col_1);
        };
    }
    println!("{:?}", cols_to_compare);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl > class_decl
        / method_decl > method_decl

    class_decl
        = kw_class constant class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block

    block
        = lbracket ((stmt / expr) terminator?)* rbracket

    stmt
        = if_stmt > if_stmt
        / while_stmt > while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    call
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = call > call
          / receiver_expr

    receiver_expr
        = assign_expr
        / literal
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*)

    param_list
        = (identifier ("," spacing identifier)*)

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call(receiver: Option<PExpr>, method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<(PExpr, Vec<PExpr>)>, body: Vec<(PExpr, Option<()>)>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn if_stmt(condition: PExpr, block: Vec<(PExpr, Option<()>)>, else_block: Option<Vec<(PExpr, Option<()>)>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<(PExpr, Option<()>)>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>),
        IfStatement(PExpr, Vec<(PExpr, Option<()>)>, Option<Vec<(PExpr, Option<()>)>>),
        MethodDecl(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>),
        WhileStatement(PExpr, Vec<(PExpr, Option<()>)>),
        Call(Option<PExpr>, PExpr, Option<(PExpr, Vec<PExpr>)>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", awesome::parse_program(contents.stream()));
}
<commit_msg>Changed precedence of assigment.<commit_after>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl > class_decl
        / method_decl > method_decl

    class_decl
        = kw_class constant class_body

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block

    block
        = lbracket ((stmt / expr) terminator?)* rbracket

    stmt
        = if_stmt > if_stmt
        / while_stmt > while_stmt

    if_stmt
        = kw_if expr block (kw_else block)?

    while_stmt
        = kw_while expr block

    call
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr
          / call > call
          / receiver_expr

    receiver_expr
        = literal
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*)

    param_list
        = (identifier ("," spacing identifier)*)

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call(receiver: Option<PExpr>, method: PExpr, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<(PExpr, Vec<PExpr>)>, body: Vec<(PExpr, Option<()>)>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn if_stmt(condition: PExpr, block: Vec<(PExpr, Option<()>)>, else_block: Option<Vec<(PExpr, Option<()>)>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<(PExpr, Option<()>)>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>)>),
        IfStatement(PExpr, Vec<(PExpr, Option<()>)>, Option<Vec<(PExpr, Option<()>)>>),
        MethodDecl(PExpr, Option<(PExpr, Vec<PExpr>)>, Vec<(PExpr, Option<()>)>),
        WhileStatement(PExpr, Vec<(PExpr, Option<()>)>),
        Call(Option<PExpr>, PExpr, Option<(PExpr, Vec<PExpr>)>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", awesome::parse_program(contents.stream()));
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod opts;

use std::fs::File;
use std::io::Result;

use opts::{Opts};

fn main() -> Result<()> {
    let opts = opts::from_args();
    init(&opts);

    fleetspeak::startup(env!("CARGO_PKG_VERSION"))?;

    loop {
        let packet = fleetspeak::collect(opts.heartbeat_rate)?;
        handle(packet.data);
    }
}

fn init(opts: &Opts) {
    let level = opts.log_verbosity.level();

    let mut loggers = Vec::<Box<dyn simplelog::SharedLogger>>::new();

    if let Some(std) = &opts.log_std {
        let config = Default::default();
        let logger = simplelog::TermLogger::new(level, config, std.mode())
            .expect("failed to create a terminal logger");

        loggers.push(logger);
    }

    if let Some(path) = &opts.log_file {
        let file = File::create(path)
            .expect("failed to create the log file");

        let config = Default::default();
        let logger = simplelog::WriteLogger::new(level, config, file);

        loggers.push(logger);
    }

    simplelog::CombinedLogger::init(loggers)
        .expect("failed to init logging");
}

fn handle(message: rrg_proto::GrrMessage) {
    match message.name {
        Some(name) => println!("requested to execute the '{}' action", name),
        None => eprintln!("missing action name to execute"),
    }
}
<commit_msg>Move logging initialization to another function.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod opts;

use std::fs::File;
use std::io::Result;

use opts::{Opts};

fn main() -> Result<()> {
    let opts = opts::from_args();
    init(&opts);

    fleetspeak::startup(env!("CARGO_PKG_VERSION"))?;

    loop {
        let packet = fleetspeak::collect(opts.heartbeat_rate)?;
        handle(packet.data);
    }
}

fn init(opts: &Opts) {
    init_log(opts);
}

fn init_log(opts: &Opts) {
    let level = opts.log_verbosity.level();

    let mut loggers = Vec::<Box<dyn simplelog::SharedLogger>>::new();

    if let Some(std) = &opts.log_std {
        let config = Default::default();
        let logger = simplelog::TermLogger::new(level, config, std.mode())
            .expect("failed to create a terminal logger");

        loggers.push(logger);
    }

    if let Some(path) = &opts.log_file {
        let file = File::create(path)
            .expect("failed to create the log file");

        let config = Default::default();
        let logger = simplelog::WriteLogger::new(level, config, file);

        loggers.push(logger);
    }

    simplelog::CombinedLogger::init(loggers)
        .expect("failed to init logging");
}

fn handle(message: rrg_proto::GrrMessage) {
    match message.name {
        Some(name) => println!("requested to execute the '{}' action", name),
        None => eprintln!("missing action name to execute"),
    }
}
<|endoftext|>


<commit_before>extern crate time;

fn main() {
    let dow = ["Duinday", "Sitaday", "Wikiday", "Tuxday", "Gnuday", "Commonday"];
    let moy = ["Jabim", "Zodrak", "Trogool", "Yanar", "Shkumbe", "Habniah", "Skarl", "Mikon", "Pertunda", "Kib", "Broket"];
    let dpm = 33;
    let dpw = dow.len();
    let mpy = moy.len();
    let (year, month, day, yoff) = current_day(time::now());
    let wd = (yoff + month * 3 + day) % dpw;
    let mut moff = yoff;

    for mm in 0..mpy {
        let spaces = (17 - moy[mm].len()) / 2;
        for _ in 0..spaces {
            print!(" ");
        }
        println!("{}", moy[mm]);

        for dd in 0..dpw {
            let mut abbrd = String::from(dow[dd]);
            abbrd.truncate(2);
            print!("{} ", abbrd);
        }

        let dd = if mm == month { day } else { 1000 };
        moff = print_days(moff, dpm, dpw, dd);
        if mm == 2 {
            println!("-- Peer Day --");
        }
        else if mm == 6 {
            println!("-- Torrent Feast --");
        }
        else if is_leap_year(year) && mm == 10 {
            println!("-- Immersion Feast --");
        }
    }

    let mut datestr = format!("{}, {:02} of {}", dow[wd], day, moy[month]);
    let mut daystr = format!("{:02}.{:02}", month + 1, day);
    if day == 34 {
        if month == 2 {
            datestr = format!("Peer Day");
            daystr = format!("P");
        }
        else if month == 6 {
            datestr = format!("Torrent Feast");
            daystr = format!("T");
        }
        else if month == 10 {
            datestr = format!("Immersion Feast");
            daystr = format!("T");
        }
    }
    let hol = format!("{}", what_holiday(month, day));
    println!("Today is {} {}{}.  [{}.{}]", datestr, year, hol, year, daystr);
}

fn print_days(moff: usize, dpm: usize, dpw: usize, highlight: usize) -> usize {
    if moff != 0 {
        println!("");
    }

    for _ in 0 .. moff {
        print!("   ");
    }

    for day in 1 .. dpm + 1 {
        if (day + moff) % dpw == 1 {
            println!("");
        }

        let ch = if day == highlight { ">" } else if day + 1 == highlight { "<" } else { " " };
        print!("{:2}{}", day, ch);
    }

    println!("");
    return if moff == 0 { 3 } else { 0 };
}

fn current_day(current_time: time::Tm) -> (usize, usize, usize, usize) {
    let epoch_days_offset = 1483889;
    let seconds_per_day = 86400;
    let now = current_time.to_timespec();
    let days_since_epoch = (epoch_days_offset + now.sec / seconds_per_day) as i32;
    let days_per_year = 365;
    let leap_year = 4;
    let not_leap_year = 33;
    let days_per_month = 33;

    let mut count = 1;
    let mut days_remaining = days_since_epoch;
    let mut year = 0;
    while days_remaining > days_per_year + 1 {
        days_remaining -= days_per_year;
        year += 1;
        if count > not_leap_year {
            count = 1;
        }
        if count % leap_year == 0 {
            days_remaining -= 1;
        }
        count += 1;
    }
    if days_remaining == days_per_year + 1 && count % leap_year == 0 {
        days_remaining = 0;
        year += 1;
    }

    let month = days_remaining / days_per_month;
    let day = days_remaining - month * days_per_month;
    return (year, month as usize, day as usize + 1, (year % 2 * 3) as usize);
}

fn is_leap_year(year: usize) -> bool {
    let rem = year % 33;
    return rem != 0 && rem % 4 == 0;
}

fn what_holiday(month: usize, day: usize) -> String {
    let mut result = format!("");
    if month == 0 && day == 1 {
        result = format!(", New Year's Day");
    }
    else if month == 2 && day == 12 {
        result = format!(", Purification Day");
    }
    else if month == 5 && day == 4 {
        result = format!(", Harvest Gift");
    }
    else if month == 7 && day == 29 {
        result = format!(", Familytide");
    }
    else if month == 10 && day == 21 {
        result = format!(", Freedom Day");
    }
    else if month == 0 && day == 27 {
        result = format!(", International Workers' Day");
    }
    return result;
}

<commit_msg>Account for epagomenal days in annual offsets<commit_after>extern crate time;

fn main() {
    let dow = ["Duinday", "Sitaday", "Wikiday", "Tuxday", "Gnuday", "Commonday"];
    let moy = ["Jabim", "Zodrak", "Trogool", "Yanar", "Shkumbe", "Habniah", "Skarl", "Mikon", "Pertunda", "Kib", "Broket"];
    let dpm = 33;
    let dpw = dow.len();
    let mpy = moy.len();
    let (year, month, day, yoff) = current_day(time::now());
    let wd = (yoff + month * 3 + day) % dpw;
    let mut moff = yoff;

    for mm in 0..mpy {
        let spaces = (17 - moy[mm].len()) / 2;
        for _ in 0..spaces {
            print!(" ");
        }
        println!("{}", moy[mm]);

        for dd in 0..dpw {
            let mut abbrd = String::from(dow[dd]);
            abbrd.truncate(2);
            print!("{} ", abbrd);
        }

        let dd = if mm == month { day } else { 1000 };
        moff = print_days(moff, dpm, dpw, dd);
        if mm == 2 {
            println!("-- Peer Day --");
        }
        else if mm == 6 {
            println!("-- Torrent Feast --");
        }
        else if is_leap_year(year) && mm == 10 {
            println!("-- Immersion Feast --");
        }
    }

    let mut datestr = format!("{}, {:02} of {}", dow[wd], day, moy[month]);
    let mut daystr = format!("{:02}.{:02}", month + 1, day);
    if day == 34 {
        if month == 2 {
            datestr = format!("Peer Day");
            daystr = format!("P");
        }
        else if month == 6 {
            datestr = format!("Torrent Feast");
            daystr = format!("T");
        }
        else if month == 10 {
            datestr = format!("Immersion Feast");
            daystr = format!("T");
        }
    }
    let hol = format!("{}", what_holiday(month, day));
    println!("Today is {} {}{}.  [{}.{}]", datestr, year, hol, year, daystr);
}

fn print_days(moff: usize, dpm: usize, dpw: usize, highlight: usize) -> usize {
    if moff != 0 {
        println!("");
    }

    for _ in 0 .. moff {
        print!("   ");
    }

    for day in 1 .. dpm + 1 {
        if (day + moff) % dpw == 1 {
            println!("");
        }

        let ch = if day == highlight { ">" } else if day + 1 == highlight { "<" } else { " " };
        print!("{:2}{}", day, ch);
    }

    println!("");
    return if moff == 0 { 3 } else { 0 };
}

fn current_day(current_time: time::Tm) -> (usize, usize, usize, usize) {
    let epoch_days_offset = 1483889;
    let seconds_per_day = 86400;
    let now = current_time.to_timespec();
    let days_since_epoch = (epoch_days_offset + now.sec / seconds_per_day) as i32;
    let days_per_year = 365;
    let leap_year = 4;
    let not_leap_year = 33;
    let days_per_month = 33;

    let mut count = 1;
    let mut days_remaining = days_since_epoch;
    let mut year = 0;
    while days_remaining > days_per_year + 1 {
        days_remaining -= days_per_year;
        year += 1;
        if count > not_leap_year {
            count = 1;
        }
        if count % leap_year == 0 {
            days_remaining -= 1;
        }
        count += 1;
    }
    if days_remaining == days_per_year + 1 && count % leap_year == 0 {
        days_remaining = 0;
        year += 1;
    }

    let mut month = 0;
    while days_remaining > days_per_month {
        month += 1;
        days_remaining -= days_per_month;
        if month == 3 || month == 7 || month == 11 {
            days_remaining -= 1;
        }
    }

    let day = days_remaining;
    return (year, month as usize, day as usize + 1, (year % 2 * 3) as usize);
}

fn is_leap_year(year: usize) -> bool {
    let rem = year % 33;
    return rem != 0 && rem % 4 == 0;
}

fn what_holiday(month: usize, day: usize) -> String {
    let mut result = format!("");
    if month == 0 && day == 1 {
        result = format!(", New Year's Day");
    }
    else if month == 2 && day == 12 {
        result = format!(", Purification Day");
    }
    else if month == 5 && day == 4 {
        result = format!(", Harvest Gift");
    }
    else if month == 7 && day == 29 {
        result = format!(", Familytide");
    }
    else if month == 10 && day == 21 {
        result = format!(", Freedom Day");
    }
    else if month == 0 && day == 27 {
        result = format!(", International Workers' Day");
    }
    return result;
}

<|endoftext|>