Newer
Older
use parser::{Parser};
use combinators::non_primitive_combinators::ThenR;
use combinators::primitive_combinators::Alternative;
use crate::combinators::common::characters::Char;
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
/* Operators
infixr 3 <|>
infixl 4 <*>
infixl 4 <*
infixl 4 *>
infixl 4 <~>
*/
#[macro_use]
macro_rules! infix {
// done converting
(@cvt () $postfix:tt) => { infix!(@pfx () $postfix) };
// | | ^ postfix expression
// | ^ operand stack
// ^ postfix interpreter
// infix to postfix conversion using the rules at the bottom of this page: http://csis.pace.edu/~wolf/CS122/infix-postfix.htm
// at end of input, flush the operators to postfix
(@cvt ($ophead:tt $($optail:tt)*) ($($postfix:tt)*)) => { infix!(@cvt ($($optail)*) ($($postfix)* $ophead)) };
// 2. push an operator onto the stack if it's empty or has a left-paren on top
(@cvt ( ) $postfix:tt <|> $($tail:tt)*) => { infix!(@cvt (<|> ) $postfix $($tail)*) };
(@cvt ( ) $postfix:tt *> $($tail:tt)*) => { infix!(@cvt (*> ) $postfix $($tail)*) };
//(@cvt ( ) $postfix:tt / $($tail:tt)*) => { infix!(@cvt (/ ) $postfix $($tail)*) };
(@cvt (LP $($optail:tt)*) $postfix:tt <|> $($tail:tt)*) => { infix!(@cvt (<|> LP $($optail)*) $postfix $($tail)*) };
(@cvt (LP $($optail:tt)*) $postfix:tt *> $($tail:tt)*) => { infix!(@cvt (*> LP $($optail)*) $postfix $($tail)*) };
//(@cvt (LP $($optail:tt)*) $postfix:tt / $($tail:tt)*) => { infix!(@cvt (/ LP $($optail)*) $postfix $($tail)*) };
// 3. push a left-paren onto the stack
(@cvt ($($operator:tt)*) $postfix:tt ($($inner:tt)*) $($tail:tt)*) => { infix!(@cvt (LP $($operator)*) $postfix $($inner)* RP $($tail)*) };
// 4. see right-paren, pop operators to postfix until left-paren
(@cvt (LP $($optail:tt)*) $postfix:tt RP $($tail:tt)*) => { infix!(@cvt ($($optail)*) $postfix $($tail)*) };
(@cvt ($ophead:tt $($optail:tt)*) ($($postfix:tt)*) RP $($tail:tt)*) => { infix!(@cvt ($($optail)*) ($($postfix)* $ophead) RP $($tail)*) };
// 5. if an operator w/ lower precedence is on top, just push
(@cvt (<|> $($optail:tt)*) $postfix:tt *> $($tail:tt)*) => { infix!(@cvt (*> <|> $($optail)*) $postfix $($tail)*) };
//(@cvt (- $($optail:tt)*) $postfix:tt * $($tail:tt)*) => { infix!(@cvt (* - $($optail)*) $postfix $($tail)*) };
//(@cvt (+ $($optail:tt)*) $postfix:tt / $($tail:tt)*) => { infix!(@cvt (/ + $($optail)*) $postfix $($tail)*) };
//(@cvt (- $($optail:tt)*) $postfix:tt / $($tail:tt)*) => { infix!(@cvt (/ - $($optail)*) $postfix $($tail)*) };
// 6. if an operator w/ equal precedence is on top, pop and push
(@cvt (<|> $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { infix!(@cvt (<|> $($optail)*) ($($postfix)* <|>) $($tail)*) };
(@cvt (*> $($optail:tt)*) ($($postfix:tt)*) *> $($tail:tt)*) => { infix!(@cvt (*> $($optail)*) ($($postfix)* *>) $($tail)*) };
//(@cvt (/ $($optail:tt)*) ($($postfix:tt)*) / $($tail:tt)*) => { infix!(@cvt (/ $($optail)*) ($($postfix)* /) $($tail)*) };
//(@cvt (* $($optail:tt)*) ($($postfix:tt)*) / $($tail:tt)*) => { infix!(@cvt (/ $($optail)*) ($($postfix)* *) $($tail)*) };
//(@cvt (/ $($optail:tt)*) ($($postfix:tt)*) * $($tail:tt)*) => { infix!(@cvt (* $($optail)*) ($($postfix)* /) $($tail)*) };
// 7. if an operator w/ higher precedence is on top, pop it to postfix
(@cvt (*> $($optail:tt)*) ($($postfix:tt)*) <|> $($tail:tt)*) => { infix!(@cvt ($($optail)*) ($($postfix)* *>) <|> $($tail)*) };
//(@cvt (/ $($optail:tt)*) ($($postfix:tt)*) + $($tail:tt)*) => { infix!(@cvt ($($optail)*) ($($postfix)* /) + $($tail)*) };
// 1. operands go to the postfix output
(@cvt $operators:tt ($($postfix:tt)*) $head:tt $($tail:tt)*) => { infix!(@cvt $operators ($($postfix)* ($head)) $($tail)*) };
// postfix interpreter
(@pfx ($result:expr ) ( )) => { $result };
(@pfx (($a:expr) ($b:expr) $($stack:tt)*) (<|> $($tail:tt)*)) => { infix!(@pfx (((
combinators::primitive_combinators::Alternative {
parser_first:$b,
parser_second: $a,
_t: std::marker::PhantomData
}
)) $($stack)*) ($($tail)*)) };
(@pfx (($a:expr) ($b:expr) $($stack:tt)*) (*> $($tail:tt)*)) => { infix!(@pfx (((
combinators::non_primitive_combinators::ThenR{
parser_first:$b,
parser_second: $a,
_a: std::marker::PhantomData,
_b: std::marker::PhantomData
}
)) $($stack)*) ($($tail)*)) };
//(@pfx (($a:expr) ($b:expr) $($stack:tt)*) (/ $($tail:tt)*)) => { infix!(@pfx ((($b / $a)) $($stack)*) ($($tail)*)) };
(@pfx ($($stack:tt)* ) ($head:tt $($tail:tt)*)) => { infix!(@pfx ($head $($stack)*) ($($tail)*)) };
($($t:tt)*) => { infix!(@cvt () () $($t)*) }
// | | | ^ infix expression
// | | ^ postfix expression
// | ^ operator stack
// ^ convert infix to postfix
}
let p1 = Char {c: 'a'};
let p2 = Char {c: 'b'};
let p3 = Char {c: 'c'};
let p4 = Char {c: 'd'};
let p5 = Char {c: 'e'};
let p = infix!(p1 *> p2 <|> p3 *> p4 <|> p5);
println!("{:#?}", p.parse("e"));