use std::cell::Cell;
use std::collections::{HashMap, HashSet};
+use std::iter::once;
use std::rc::Rc;
#[derive(Clone)]
pub enum TokenOrRedirect {
Atom(ClauseName),
- NumberedVar(String),
+ Op(ClauseName),
+ NumberedVar(String),
Redirect,
Open,
Close,
fn print_op(ct: ClauseType, fixity: Fixity, state_stack: &mut Vec<TokenOrRedirect>) {
match fixity {
Fixity::Post => {
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ state_stack.push(TokenOrRedirect::Op(ct.name()));
state_stack.push(TokenOrRedirect::Redirect);
},
Fixity::Pre => {
state_stack.push(TokenOrRedirect::Redirect);
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ state_stack.push(TokenOrRedirect::Op(ct.name()));
},
Fixity::In => {
state_stack.push(TokenOrRedirect::Redirect);
- state_stack.push(TokenOrRedirect::Atom(ct.name()));
+ state_stack.push(TokenOrRedirect::Op(ct.name()));
state_stack.push(TokenOrRedirect::Redirect);
}
}
}).collect()
}
-fn non_quoted_token(c: char) -> bool {
- graphic_token_char!(c) || alpha_numeric_char!(c)
+fn non_quoted_graphic_token<Iter: Iterator<Item=char>>(mut iter: Iter, c: char) -> bool {
+ if c == '/' {
+ return match iter.next() {
+ None => true,
+ Some('*') => false, // if we start with comment token, we must quote.
+ Some(c) => if graphic_token_char!(c) {
+ iter.all(|c| graphic_token_char!(c))
+ } else {
+ false
+ }
+ }
+ } else if c == '.' {
+ return match iter.next() {
+ None => false,
+ Some(c) => if graphic_token_char!(c) {
+ iter.all(|c| graphic_token_char!(c))
+ } else {
+ false
+ }
+ }
+ } else {
+ iter.all(|c| graphic_token_char!(c))
+ }
+}
+
+fn non_quoted_token<Iter: Iterator<Item=char>>(mut iter: Iter) -> bool {
+ if let Some(c) = iter.next() {
+ if small_letter_char!(c) {
+ iter.all(|c| alpha_numeric_char!(c))
+ } else if graphic_token_char!(c) {
+ non_quoted_graphic_token(iter, c)
+ } else if semicolon_char!(c) {
+ iter.next().is_none()
+ } else if cut_char!(c) {
+ iter.next().is_none()
+ } else if solo_char!(c) {
+ !iter.next().is_none()
+ } else if c == '[' {
+ (iter.next() == Some(']') && iter.next().is_none())
+ } else if c == '{' {
+ (iter.next() == Some('}') && iter.next().is_none())
+ } else {
+ false
+ }
+ } else {
+ false
+ }
}
impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
})
}
- fn print_atom(&mut self, atom: &ClauseName) {
+ fn print_atom(&mut self, atom: &ClauseName, is_op: bool) {
match atom.as_str() {
"" => self.outputter.append("''"),
";" | "!" => self.outputter.append(atom.as_str()),
- s => if s.chars().all(non_quoted_token) {
+ s => if is_op || non_quoted_token(s.chars()) {
self.outputter.append(atom.as_str());
} else {
self.outputter.push_char('\'');
fn print_constant(&mut self, c: Constant) {
match c {
Constant::Atom(ref atom) =>
- self.print_atom(atom),
- Constant::Char(c) if non_quoted_token(c) =>
+ self.print_atom(atom, false),
+ Constant::Char(c) if non_quoted_token(once(c)) =>
self.print_char(c),
Constant::Char(c) => {
self.outputter.push_char('\'');
if let Some(loc_data) = self.state_stack.pop() {
match loc_data {
TokenOrRedirect::Atom(atom) =>
- self.print_atom(&atom),
+ self.print_atom(&atom, false),
+ TokenOrRedirect::Op(atom) =>
+ self.print_atom(&atom, true),
TokenOrRedirect::NumberedVar(num_var) =>
self.outputter.append(num_var.as_str()),
TokenOrRedirect::Redirect =>
submit(&mut wam, ":- op(900, xfx, ~).");
submit(&mut wam, "X ~ Y :- abs(X - Y) =< 1 rdiv 10000.");
- assert_prolog_success!(&mut wam, "?- X is 3 ^ 3.",
+ assert_prolog_success!(&mut wam, "?- X is 3 ** 3.",
[["X = 27"]]);
- assert_prolog_success!(&mut wam, "?- X is 3 ^ 0.",
+ assert_prolog_success!(&mut wam, "?- X is 3 ** 0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- X is 3 ^ -0.",
+ assert_prolog_success!(&mut wam, "?- X is 3 ** -0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- X is 3 ^ 1.",
+ assert_prolog_success!(&mut wam, "?- X is 3 ** 1.",
[["X = 3"]]);
- assert_prolog_success!(&mut wam, "?- X is 3 ^ -3.",
+ assert_prolog_success!(&mut wam, "?- X is 3 ** -3.",
[["X = 1/27"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ 3.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** 3.",
[["X = -27"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ 3.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** 3.",
[["X = -27"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ 0.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** 0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ -0.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** -0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ 1.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** 1.",
[["X = -3"]]);
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ -3.",
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** -3.",
[["X = -1/27"]]);
- assert_prolog_success!(&mut wam, "?- X is (1 rdiv 27) ^ -3, X ~ 19683.");
- assert_prolog_success!(&mut wam, "?- X is (-1 rdiv 27) ^ -3, X ~ -19683.");
+ assert_prolog_success!(&mut wam, "?- X is (1 rdiv 27) ** -3, X ~ 19683.");
+ assert_prolog_success!(&mut wam, "?- X is (-1 rdiv 27) ** -3, X ~ -19683.");
- assert_prolog_success!(&mut wam, "?- X is 0.0 ^ 0.",
+ assert_prolog_success!(&mut wam, "?- X is 0.0 ** 0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is 0.0 ^ -2342, error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is 0.0 ** -2342, error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- X is 0.0 ^ 2342.",
+ assert_prolog_success!(&mut wam, "?- X is 0.0 ** 2342.",
[["X = 0"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is (-3) ^ (1 rdiv 2), error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is (-3) ** (1 rdiv 2), error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is (-3/2) ^ (1 rdiv 2), error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is (-3/2) ** (1 rdiv 2), error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ^ (1 rdiv 4), error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ** (1 rdiv 4), error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ^ (-1 rdiv 4), error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ** (-1 rdiv 4), error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is 0 ^ (-5 rdiv 4), error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is 0 ** (-5 rdiv 4), error(E, _), true).",
[["E = evaluation_error(no_roots)"]]);
- assert_prolog_success!(&mut wam, "?- X is 3 ^ (1 rdiv 3), Y is X ^ 3, Y ~ 3.");
- assert_prolog_success!(&mut wam, "?- X is (-3) ^ (1 rdiv 3), Y is X ^ 3, Y ~ -3.");
- assert_prolog_failure!(&mut wam, "?- X is (-5) ^ (1 rdiv 3), Y is X ^ 3, Y ~ -3.");
- assert_prolog_failure!(&mut wam, "?- X is 5 ^ (1 rdiv 3), Y is X ^ 3, Y ~ 3.");
- assert_prolog_failure!(&mut wam, "?- X is (1 rdiv 3) ^ 0.5, Y is X ^ 2, X ~ Y.");
- assert_prolog_success!(&mut wam, "?- X is (1 rdiv 3) ^ 0.5, Y is X ^ 2, 1 rdiv 3 ~ Y.");
+ assert_prolog_success!(&mut wam, "?- X is 3 ** (1 rdiv 3), Y is X ** 3, Y ~ 3.");
+ assert_prolog_success!(&mut wam, "?- X is (-3) ** (1 rdiv 3), Y is X ** 3, Y ~ -3.");
+ assert_prolog_failure!(&mut wam, "?- X is (-5) ** (1 rdiv 3), Y is X ** 3, Y ~ -3.");
+ assert_prolog_failure!(&mut wam, "?- X is 5 ** (1 rdiv 3), Y is X ** 3, Y ~ 3.");
+ assert_prolog_failure!(&mut wam, "?- X is (1 rdiv 3) ** 0.5, Y is X ** 2, X ~ Y.");
+ assert_prolog_success!(&mut wam, "?- X is (1 rdiv 3) ** 0.5, Y is X ** 2, 1 rdiv 3 ~ Y.");
- assert_prolog_success!(&mut wam, "?- X is (-5) ^ (-1 rdiv 3), Y is X ^ 3, Y ~ -1 rdiv 5.");
- assert_prolog_failure!(&mut wam, "?- X is (-5) ^ (-1 rdiv 3), Y is X ^ 3, Y ~ 1 rdiv 5.");
+ assert_prolog_success!(&mut wam, "?- X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ -1 rdiv 5.");
+ assert_prolog_failure!(&mut wam, "?- X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ 1 rdiv 5.");
- assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ^ 5.",
+ assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ** 5.",
[["X = 0"]]);
- assert_prolog_success!(&mut wam, "?- X is (-0 rdiv 5) ^ 5.",
+ assert_prolog_success!(&mut wam, "?- X is (-0 rdiv 5) ** 5.",
[["X = 0"]]);
- assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ^ 0.",
+ assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ** 0.",
[["X = 1"]]);
- assert_prolog_success!(&mut wam, "?- catch(_ is (0 rdiv 0) ^ 5, error(E, _), true).",
+ assert_prolog_success!(&mut wam, "?- catch(_ is (0 rdiv 0) ** 5, error(E, _), true).",
[["E = evaluation_error(zero_divisor)"]]);
}