tt: TokenType,
priority: usize,
spec: u32,
+ unfold_bounds: usize,
}
pub(crate) fn as_partial_string(
tt: TokenType::Term,
priority: td.priority,
spec,
+ unfold_bounds: 0,
});
}
}
tt: TokenType::Term,
priority: td.priority,
spec,
+ unfold_bounds: 0,
});
}
}
tt: TokenType::Term,
priority,
spec: assoc,
+ unfold_bounds: 0,
});
}
Token::End => TokenType::End,
};
- self.stack.push(TokenDesc { tt, priority, spec });
+ self.stack.push(TokenDesc { tt, priority, spec, unfold_bounds: 0, });
}
fn reduce_op(&mut self, priority: usize) {
}
if let Some(&mut TokenDesc {
+ ref mut tt,
ref mut priority,
ref mut spec,
- ref mut tt,
+ ref mut unfold_bounds,
}) = self.stack.last_mut()
{
*tt = TokenType::Term;
*priority = 0;
*spec = TERM;
+ *unfold_bounds = 0;
}
return true;
}
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
- if let Some(term) = self.terms.pop() {
- let op_desc = self.stack[index - 1];
+ if let Some(mut term) = self.terms.pop() {
+ let mut op_desc = self.stack[index - 1];
if 0 < op_desc.priority && op_desc.priority < self.stack[index].priority {
/* '|' is a head-tail separator here, not
* terms it compacted out again. */
match (term.name(), term.arity()) {
(Some(name), 2) if name == atom!(",") => {
- let terms = unfold_by_str(term, name); // notice: name == "," here.
+ let terms = if op_desc.unfold_bounds == 0 {
+ unfold_by_str(term, atom!(","))
+ } else {
+ let mut terms = vec![];
+
+ while let Some((fst, snd)) = unfold_by_str_once(&mut term, atom!(",")) {
+ terms.push(fst);
+ term = snd;
+
+ op_desc.unfold_bounds -= 2;
+
+ if op_desc.unfold_bounds == 0 {
+ break;
+ }
+ }
+
+ terms.push(term);
+ terms
+ };
+
let arity = terms.len() - 1;
self.terms.extend(terms.into_iter());
tt: TokenType::Term,
priority: 0,
spec: TERM,
+ unfold_bounds: 0,
});
self.terms.push(match list {
),
Token::Literal(c) => {
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
+
if let Some(name) = atomized {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
/* '|' as an operator must have priority > 1000 and can only be infix.
* See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78
*/
- let bar_atom = atom!("|");
-
- let (priority, spec) = get_op_desc(bar_atom, op_dir)
+ let (priority, spec) = get_op_desc(atom!("|"), op_dir)
.map(|CompositeOpDesc { inf, spec, .. }| (inf, spec))
.unwrap_or((1000, DELIMITER));
+ let old_stack_len = self.stack.len();
+
self.reduce_op(priority);
+
+ let new_stack_len = self.stack.len();
+
+ if let Some(term_desc) = self.stack.last_mut() {
+ term_desc.unfold_bounds = old_stack_len - new_stack_len;
+ }
+
self.shift(Token::HeadTailSeparator, priority, spec);
}
Token::Comma => {