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
126
use pest::Parser;
use crate::lexicon::Lexicon;
use crate::matching::MPMatching;
use crate::segment::MPSegment;
#[derive(Parser)]
#[grammar = "transform_str.pest"]
pub struct SParser;
pub struct TSParser<'a> {
lexicon: &'a Lexicon,
}
impl<'a> TSParser<'a> {
pub fn new(lexicon: &'a Lexicon) -> TSParser<'a> {
TSParser {
lexicon
}
}
pub fn compile(&self, source: &str, matching: &MPMatching<'a>) -> &MPSegment {
let parse_result = SParser::parse(Rule::expr, source);
if parse_result.is_err() {
panic!("These do not seem like transforms: \"{}\"\n\nerr: {}\n\nmatching: {:?}", source, parse_result.err().unwrap(), matching);
}
let pair = parse_result.ok().unwrap().next().unwrap();
self.compile_expr(pair, matching)
}
fn compile_expr(&self, pair: pest::iterators::Pair<Rule>, matching: &MPMatching<'a>) -> &MPSegment {
match pair.as_rule() {
Rule::monadicExpr => {
let mut pair = pair.into_inner();
let op = pair.next().expect("cin");
let termpair = pair.next().expect("sei");
let term = self.compile_expr(termpair, matching);
self.parse_monadic_op(op, term)
},
Rule::dyadicExpr => {
let mut pair = pair.into_inner();
let op = pair.next().expect("och");
let fstpair = pair.next().expect("sie");
let fst = self.compile_expr(fstpair, matching);
let sndpair = pair.next().expect("nue");
let snd = self.compile_expr(sndpair, matching);
self.parse_dyadic_op(op, fst, snd)
},
Rule::triadicExpr => {
let mut pair = pair.into_inner();
let op = pair.next().expect("och");
let fstpair = pair.next().expect("sie");
let fst = self.compile_expr(fstpair, matching);
let sndpair = pair.next().expect("nue");
let snd = self.compile_expr(sndpair, matching);
let trdpair = pair.next().expect("nue");
let trd = self.compile_expr(trdpair, matching);
self.parse_triadic_op(op, fst, snd, trd)
},
Rule::v_decimal => {
self.lexicon.intern("v_decimal", pair.as_str(), true)
},
Rule::v_string => {
self.lexicon.intern("v_string", pair.as_str(), true)
},
Rule::var => {
let var = self.lexicon.intern("var", pair.as_str(), true);
matching.get(var).expect("segment")
},
unknown_expr => panic!("Unexpected expression: {:?}", unknown_expr),
}
}
fn parse_triadic_op(&self, op: pest::iterators::Pair<Rule>, fst: &MPSegment, snd: &MPSegment, trd: &MPSegment) -> &MPSegment {
match op.as_str() {
"substring" => {
let fst_str = &fst.text;
let snd_num = snd.text.as_str().parse::<usize>().ok().expect("die");
let trd_num = trd.text.as_str().parse::<usize>().ok().expect("die");
let substr = fst_str.chars().skip(snd_num).take(trd_num).collect();
self.lexicon.intern_with_text(&fst.name, substr, true)
},
"replace" => {
let fst_str = &fst.text;
let snd_str = &snd.text;
let trd_str = &trd.text;
let result = fst_str.replace(snd_str, trd_str);
self.lexicon.intern_with_text(&fst.name, result, true)
},
_ => panic!("Unexpected triadic operator: {}", op.as_str()),
}
}
fn parse_dyadic_op(&self, op: pest::iterators::Pair<Rule>, fst: &MPSegment, snd: &MPSegment) -> &MPSegment {
match op.as_str() {
"index_of" => {
let fst_str = &fst.text;
let snd_str = &snd.text;
let result = fst_str.find(snd_str);
match result {
None => self.lexicon.intern("v_decimal", "-1", true),
Some(i) => self.lexicon.intern_with_text("v_decimal", format!("{}", i), true),
}
},
"concat" => {
let mut fst_str = fst.text.clone();
fst_str.push_str(&snd.text);
self.lexicon.intern_with_text(&fst.name, fst_str, true)
},
_ => panic!("Unexpected dyadic operator: {}", op.as_str()),
}
}
fn parse_monadic_op(&self, op: pest::iterators::Pair<Rule>, term: &MPSegment) -> &MPSegment {
match op.as_str() {
"len" => {
let result = format!("{}", term.text.len());
self.lexicon.intern_with_text("v_decimal", result, true)
},
_ => panic!("Unexpected monadic operator: {}", op.as_str()),
}
}
}