1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Here it's the peg grammar to parse the peg input  ;-P
//!
//! There is also a function to print the rust source code
//!
//! It's used in order to develop myself
//!
//! A parser for the parser (you know)
//!
//! To generate the code to parse the peg, you just have to run...
//!
//! ```
//! extern crate dynparser;
//! use dynparser::peg::peg2code;
//!
//! fn main() {
//!     peg2code::print_rules2parse_peg();
//! }
//! ```
//!
//! And the result, has to be pasted in peg::rules.rs
//!

use {peg, rules_from_peg};

fn text_peg2code() -> &'static str {
    r#"
    /*      A peg grammar to parse peg grammars
     *
     */

    main            =   grammar

    grammar         =   (rule  /  module)+
    
    module          =   _  mod_name _ '{'  _ grammar  _ '}'
    mod_name        =   symbol
    symbol          =   [_a-zA-Z0-9] [_'"a-zA-Z0-9]*

    rule            =   _  rule_name  _  '='  _  expr  _eol _
    rule_name       =   '.'?  symbol  ('.' symbol)*

    expr            =   or

    or              =   and         ( _  '/'  _  or )?
    error           =   'error' _  '('  _  literal  _  ')'

    and             =   error 
                    /   rep_or_neg  ( _1 _ !(rule_name _ ('=' / '{')) and )*
    _1              =   (' ' / eol)     //  this is the and separator

    rep_or_neg      =   atom_or_par ('*' / '+' / '?')?
                    /   '!' atom_or_par

    atom_or_par     =   (atom / parenth)

    parenth         =   '('  _  expr  _  ')'
                    /   '('  _  expr  _  error("unbalanced parethesis: missing ')'")

    atom            =   literal
                    /   match
                    /   dot
                    /   rule_name

    literal         =  lit_noesc  /  lit_esc

    lit_noesc       =   _'   (  !_' .  )*   _'
    _'              =   "'"

    lit_esc         =   _"
                            (   esc_char
                            /   hex_char
                            /   !_" .
                            )*
                        _"
    _"              =   '"'

    esc_char        =   '\r'
                    /   '\n'
                    /   '\t'
                    /   '\\'
                    /   '\"'

    hex_char        =   '\0x' [0-9A-F] [0-9A-F]

    eol             =   ("\r\n"  /  "\n"  /  "\r")
    _eol            =   (' ' / comment)*  eol

    match           =   '['
                            (
                                (mchars  mbetween*)
                                / mbetween+
                            )
                        ']'

    mchars          =   (!']' !(. '-') .)+
    mbetween        =   (.  '-'  .)

    dot             =   '.'

    _               =   (  ' '
                        /   eol
                        /   comment
                        )*

    comment         =   line_comment
                    /   mline_comment

    line_comment    =   '//' (!eol .)*  eol
    mline_comment   =   '/*' (!'*/' .)* '*/'
    "#
}

/// A parser for the parser.
///
/// It will take the peg grammar to parse peg grammars
///
pub fn print_rules2parse_peg() {
    let rules = rules_from_peg(text_peg2code())
        .map_err(|e| {
            println!("{}", e);
            panic!("FAIL");
        }).unwrap();

    println!("{}", peg::gcode::rust_from_rules(&rules))
}