]> Repositorios git - scryer-prolog.git/commitdiff
reconcile '[]' and [] (#644), solve remaining conformity issues (#648), move (--... v0.8.127
authorMark Thom <[email protected]>
Mon, 3 Aug 2020 05:33:37 +0000 (23:33 -0600)
committerMark Thom <[email protected]>
Mon, 3 Aug 2020 05:33:37 +0000 (23:33 -0600)
12 files changed:
Cargo.lock
Cargo.toml
src/heap_print.rs
src/lib/builtins.pl
src/lib/dcgs.pl
src/machine/machine_errors.rs
src/machine/machine_state.rs
src/machine/streams.rs
src/machine/system_calls.rs
src/machine/term_expansion.rs
src/read.rs
src/toplevel.pl

index 041ddfa9eb975fd8d23a3de46c5d7b2efc6e3a66..ef258334f1252888a07a95198be752aa4c341da2 100644 (file)
@@ -502,6 +502,17 @@ version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
 
+[[package]]
+name = "libsodium-sys"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a685b64f837b339074115f2e7f7b431ac73681d08d75b389db7498b8892b8a58"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
 [[package]]
 name = "lock_api"
 version = "0.3.4"
@@ -894,9 +905,9 @@ dependencies = [
 
 [[package]]
 name = "prolog_parser"
-version = "0.8.63"
+version = "0.8.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fa8dbe0881bcc9a247db279802701d87bbe9d4c6604bb0e5cad3dd3314f241d"
+checksum = "fdcfe8260335a150812e36b171ff985ce88f02de16c05f4a13fe4f10e8c247f8"
 dependencies = [
  "lexical",
  "num-rug-adapter",
@@ -1250,6 +1261,7 @@ dependencies = [
  "rustyline",
  "select",
  "sha3",
+ "sodiumoxide",
  "unicode_reader",
 ]
 
@@ -1390,6 +1402,17 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
 
+[[package]]
+name = "sodiumoxide"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7038b67c941e23501573cb7242ffb08709abe9b11eb74bceff875bbda024a6a8"
+dependencies = [
+ "libc",
+ "libsodium-sys",
+ "serde",
+]
+
 [[package]]
 name = "spin"
 version = "0.5.2"
index 6eaf21285e65f73b440002ef9421318885a0ef61..c359e1bac374bcc89f5ee67fb0a33628dc3a0a88 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.126"
+version = "0.8.127"
 authors = ["Mark Thom <[email protected]>"]
 edition = "2018"
 description = "A modern Prolog implementation written mostly in Rust."
@@ -32,7 +32,7 @@ libc = "0.2.62"
 nix = "0.15.0"
 num-rug-adapter = { optional = true, version = "0.1.3" }
 ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.63", default-features = false }
+prolog_parser = { version = "0.8.65", default-features = false }
 ref_thread_local = "0.0.0"
 rug = { version = "1.4.0", optional = true }
 rustyline = "6.0.0"
index 4a7b3e76d5bcc4ddb685577be07f3c32da528fc5..2a51fa91823c2e66f49338b78276bf0cca990358 100644 (file)
@@ -1298,6 +1298,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     !iter.immediate_leaf_has_property(|addr, heap| {
                         match heap.index_addr(&addr).as_ref() {
                             &HeapCellValue::Integer(ref n) => &**n >= &0,
+                            &HeapCellValue::Addr(Addr::Fixnum(n)) => n >= 0,
                             &HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64),
                             &HeapCellValue::Rational(ref r) => &**r >= &0,
                             _ => false
index 3e1c8d28e71d46ea6aa1462dec1991f5f23c56fa..ebfebfffa801294a2de5648d8f26801342b5587b 100644 (file)
@@ -24,6 +24,8 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
 :- op(400, yfx, [div, //, rdiv, <<, >>, mod, rem]).
 :- op(200, fy, [+, -, \]).
 
+:- op(1200, xfx, -->).
+
 % arithmetic comparison operators.
 :- op(700, xfx, [>, <, =\=, =:=, >=, =<]).
 
index 5e8e19d5b23d8f4a4c7e8f9b12a1eafe5c4543c3..942f6b8ebeb32d06adcbc79e1fbd5336a14324c7 100644 (file)
@@ -1,7 +1,7 @@
-:- module(dcgs, [op(1200, xfx, -->),
-                op(1105, xfy, '|'),
-                phrase/2,
-                phrase/3]).
+:- module(dcgs,
+          [op(1105, xfy, '|'),
+                  phrase/2,
+                  phrase/3]).
 
 :- use_module(library(error)).
 :- use_module(library(lists), [append/3]).
index dddc58ac5697c3664fe2dbf8480f0e286bc6de5e..1dcc1db8bf63444fffd2aafeb00b86af14f65477 100644 (file)
@@ -840,5 +840,4 @@ impl From<ParserError> for EvalSession {
     fn from(err: ParserError) -> Self {
         EvalSession::from(SessionError::ParserError(err))
     }
-
 }
index 02f7230a25d1623f5af1358a524e0940c8bd8b65..e8799566a99097ac774a79ae35a82ecda4e61e71 100644 (file)
@@ -636,11 +636,10 @@ impl MachineState {
         }
 
         let mut orig_stream = stream.clone();
-        let mut stream = self.open_parsing_stream(stream, "read_term", 3)?;
 
         loop {
             match self.read(
-                &mut stream,
+                stream.clone(),
                 indices.atom_tbl.clone(),
                 &indices.op_dir,
             ) {
@@ -1337,14 +1336,8 @@ pub(crate) trait CallPolicy: Any + fmt::Debug {
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::Read => {
-                let mut stream = machine_st.open_parsing_stream(
-                    current_input_stream.clone(),
-                    "read",
-                    1,
-                )?;
-
                 match machine_st.read(
-                    &mut stream,
+                    current_input_stream.clone(),
                     indices.atom_tbl.clone(),
                     &indices.op_dir,
                 ) {
index f646ff9b7972ddc0e7e117d5d037d7251ff4fd31..7e07067a5e1e6e5af6f1279cf1a3cf38db0437f7 100644 (file)
@@ -6,13 +6,15 @@ use crate::machine::machine_errors::*;
 use crate::machine::machine_indices::*;
 use crate::machine::machine_state::*;
 
-use std::cmp::Ordering;
+use std::cmp::{min, Ordering};
 use std::cell::RefCell;
 use std::error::Error;
 use std::fmt;
 use std::fs::File;
+use std::io;
 use std::io::{stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
 use std::hash::{Hash, Hasher};
+use std::mem;
 use std::net::{Shutdown, TcpStream};
 use std::ops::DerefMut;
 use std::rc::Rc;
@@ -92,20 +94,83 @@ impl EOFAction {
     }
 }
 
+fn parser_top_to_bytes(mut buf: Vec<io::Result<char>>) -> io::Result<Vec<u8>> {
+    let mut str_buf = String::new();
+
+    while let Some(c) = buf.pop() {
+        str_buf.push(c?);
+    }
+
+    unsafe {
+        let array = str_buf.as_bytes_mut();
+        array.reverse();
+        Ok(Vec::from(array))
+    }
+}
+
 /* all these streams are closed automatically when the instance is
  * dropped. */
 pub enum StreamInstance {
     Bytes(Cursor<Vec<u8>>),
-    DynReadSource(Box<dyn Read>),
     InputFile(ClauseName, File),
     OutputFile(ClauseName, File, bool), // File, append.
     Null,
+    PausedPrologStream(Vec<u8>, Box<StreamInstance>),
     ReadlineStream(ReadlineStream),
+    StaticStr(Cursor<&'static str>),
     Stdout,
     TcpStream(ClauseName, TcpStream),
     TlsStream(ClauseName, TlsStream<TcpStream>)
 }
 
+impl StreamInstance {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        match self {
+            StreamInstance::PausedPrologStream(ref mut put_back, ref mut stream) => {
+                let mut index = 0;
+
+                while index < min(buf.len(), put_back.len()) {
+                    let b = put_back.pop().unwrap();
+                    buf[index] = b;
+                    index += 1;
+                }
+
+                if index == buf.len() {
+                    Ok(buf.len())
+                } else {
+                    stream.read(&mut buf[index ..])
+                }
+            }
+            StreamInstance::InputFile(_, ref mut file) => {
+                file.read(buf)
+            }
+            StreamInstance::TcpStream(_, ref mut tcp_stream) => {
+                tcp_stream.read(buf)
+            }
+            StreamInstance::TlsStream(_, ref mut tls_stream) => {
+                tls_stream.read(buf)
+            }
+            StreamInstance::ReadlineStream(ref mut rl_stream) => {
+                rl_stream.read(buf)
+            }
+            StreamInstance::StaticStr(ref mut src) => {
+                src.read(buf)
+            }
+            StreamInstance::Bytes(ref mut cursor) => {
+                cursor.read(buf)
+            }
+            StreamInstance::OutputFile(..) |
+            StreamInstance::Stdout |
+            StreamInstance::Null => {
+                Err(std::io::Error::new(
+                    ErrorKind::PermissionDenied,
+                    StreamError::ReadFromOutputStream,
+                ))
+            }
+        }
+    }
+}
+
 impl Drop for StreamInstance {
     fn drop(&mut self) {
         match self {
@@ -126,15 +191,20 @@ impl fmt::Debug for StreamInstance {
         match self {
             &StreamInstance::Bytes(ref bytes) =>
                 write!(fmt, "Bytes({:?})", bytes),
-            &StreamInstance::DynReadSource(_) =>
-                write!(fmt, "DynReadSource(_)"),  // Hacky solution.
-            &StreamInstance::InputFile(_, ref file) => write!(fmt, "InputFile({:?})", file),
-            &StreamInstance::OutputFile(_, ref file, _) => write!(fmt, "OutputFile({:?})", file),
-            &StreamInstance::Null => write!(fmt, "Null"),
+            &StreamInstance::StaticStr(_) =>
+                write!(fmt, "StaticStr(_)"),  // Hacky solution.
+            &StreamInstance::InputFile(_, ref file) =>
+                write!(fmt, "InputFile({:?})", file),
+            &StreamInstance::OutputFile(_, ref file, _) =>
+                write!(fmt, "OutputFile({:?})", file),
+            &StreamInstance::Null =>
+                write!(fmt, "Null"),
+            &StreamInstance::PausedPrologStream(ref put_back, ref stream) =>
+                write!(fmt, "PausedPrologStream({:?}, {:?})", put_back, stream),
             &StreamInstance::ReadlineStream(ref readline_stream) =>
                 write!(fmt, "ReadlineStream({:?})", readline_stream),
-            // &StreamInstance::Stdin => write!(fmt, "Stdin"),
-            &StreamInstance::Stdout => write!(fmt, "Stdout"),
+            &StreamInstance::Stdout =>
+                write!(fmt, "Stdout"),
             &StreamInstance::TcpStream(_, ref tcp_stream) =>
                 write!(fmt, "TcpStream({:?})", tcp_stream),
             &StreamInstance::TlsStream(_, ref tls_stream) =>
@@ -282,7 +352,7 @@ impl From<ReadlineStream> for Stream {
 
 impl From<&'static str> for Stream {
     fn from(src: &'static str) -> Stream {
-        Stream::from_inst(StreamInstance::DynReadSource(Box::new(src.as_bytes())))
+        Stream::from_inst(StreamInstance::StaticStr(Cursor::new(src)))
     }
 }
 
@@ -413,8 +483,9 @@ impl Stream {
     fn mode(&self) -> &'static str {
         match self.stream_inst.0.borrow().1 {
             StreamInstance::Bytes(_) |
+            StreamInstance::PausedPrologStream(..) |
             StreamInstance::ReadlineStream(_) |
-            StreamInstance::DynReadSource(_) |
+            StreamInstance::StaticStr(_) |
             StreamInstance::InputFile(..) => {
                 "read"
             }
@@ -493,7 +564,6 @@ impl Stream {
     pub(crate)
     fn is_stdin(&self) -> bool {
         match self.stream_inst.0.borrow().1 {
-            //StreamInstance::Stdin |
             StreamInstance::ReadlineStream(_) => {
                 true
             }
@@ -523,12 +593,12 @@ impl Stream {
     pub(crate)
     fn is_input_stream(&self) -> bool {
         match self.stream_inst.0.borrow().1 {
-            // StreamInstance::Stdin |
             StreamInstance::TcpStream(..) |
             StreamInstance::TlsStream(..) |
             StreamInstance::Bytes(_) |
+            StreamInstance::PausedPrologStream(..) |
             StreamInstance::ReadlineStream(_) |
-            StreamInstance::DynReadSource(_) |
+            StreamInstance::StaticStr(_) |
             StreamInstance::InputFile(..) => {
                 true
             }
@@ -555,27 +625,49 @@ impl Stream {
         }
     }
 
+    fn unpause_stream(&mut self) {
+        let stream_inst =
+            match self.stream_inst.0.borrow_mut().1 {
+                StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst)
+                    if put_back.is_empty() => {
+                        mem::replace(&mut **stream_inst, StreamInstance::Null)
+                    }
+                _ => {
+                    return;
+                }
+            };
+
+        self.stream_inst.0.borrow_mut().1 = stream_inst;
+    }
+
     // returns true on success.
     #[inline]
     pub(super)
     fn reset(&mut self) -> bool {
         self.stream_inst.0.borrow_mut().0 = false;
 
-        match self.stream_inst.0.borrow_mut().1 {
-            StreamInstance::Bytes(ref mut cursor) => {
-                cursor.set_position(0);
-                true
-            }
-            StreamInstance::InputFile(_, ref mut file) => {
-                file.seek(SeekFrom::Start(0)).unwrap();
-                true
-            }
-            StreamInstance::ReadlineStream(_) => {
-                true
-            }
-            _ => {
-                false
+        loop {
+            match self.stream_inst.0.borrow_mut().1 {
+                StreamInstance::Bytes(ref mut cursor) => {
+                    cursor.set_position(0);
+                    return true;
+                }
+                StreamInstance::InputFile(_, ref mut file) => {
+                    file.seek(SeekFrom::Start(0)).unwrap();
+                    return true;
+                }
+                StreamInstance::PausedPrologStream(ref mut put_back, _) => {
+                    put_back.clear();
+                }
+                StreamInstance::ReadlineStream(_) => {
+                    return true;
+                }
+                _ => {
+                    return false;
+                }
             }
+
+            self.unpause_stream();
         }
     }
 
@@ -687,6 +779,34 @@ impl Stream {
             }
         }
     }
+
+    #[inline]
+    pub(crate)
+    fn pause_stream(&mut self, buf: Vec<io::Result<char>>) -> io::Result<()> {
+        match self.stream_inst.0.borrow_mut().1 {
+            StreamInstance::PausedPrologStream(ref mut inner_buf, _) => {
+                inner_buf.extend(parser_top_to_bytes(buf)?.into_iter());
+                return Ok(());
+            }
+            _ => {
+            }
+        }
+
+        if !buf.is_empty() {
+            let stream_inst = mem::replace(
+                &mut self.stream_inst.0.borrow_mut().1,
+                StreamInstance::Null,
+            );
+
+            self.stream_inst.0.borrow_mut().1 =
+                StreamInstance::PausedPrologStream(
+                    parser_top_to_bytes(buf)?,
+                    Box::new(stream_inst),
+                );
+        }
+
+        Ok(())
+    }
 }
 
 impl MachineState {
@@ -883,7 +1003,7 @@ impl MachineState {
         stub_name: &'static str,
         stub_arity: usize,
     ) -> Result<PrologStream, MachineStub> {
-        match parsing_stream(stream.clone()) {
+        match parsing_stream(stream) {
             Ok(parsing_stream) => {
                 Ok(parsing_stream)
             }
@@ -1045,38 +1165,11 @@ impl MachineState {
 }
 
 impl Read for Stream {
+    #[inline]
     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
-        match self.stream_inst.0.borrow_mut().1 {
-            StreamInstance::InputFile(_, ref mut file) => {
-                file.read(buf)
-            }
-            StreamInstance::TcpStream(_, ref mut tcp_stream) => {
-                tcp_stream.read(buf)
-            }
-            StreamInstance::TlsStream(_, ref mut tls_stream) => {
-                tls_stream.read(buf)
-            }
-            StreamInstance::ReadlineStream(ref mut rl_stream) => {
-                rl_stream.read(buf)
-            }
-            StreamInstance::DynReadSource(ref mut src) => {
-                src.read(buf)
-            }
-            StreamInstance::Bytes(ref mut cursor) => {
-                cursor.read(buf)
-            }
-/*
-            StreamInstance::Stdin => {
-                stdin().read(buf)
-            }
-*/
-            StreamInstance::OutputFile(..) | StreamInstance::Stdout | StreamInstance::Null => {
-                Err(std::io::Error::new(
-                    ErrorKind::PermissionDenied,
-                    StreamError::ReadFromOutputStream,
-                ))
-            }
-        }
+        let bytes_read = self.stream_inst.0.borrow_mut().1.read(buf)?;
+        self.unpause_stream();
+        Ok(bytes_read)
     }
 }
 
@@ -1098,8 +1191,11 @@ impl Write for Stream {
             StreamInstance::Stdout => {
                 stdout().write(buf)
             }
-            StreamInstance::DynReadSource(_) | StreamInstance::ReadlineStream(_) |
-            StreamInstance::InputFile(..) | StreamInstance::Null => {
+            StreamInstance::PausedPrologStream(..) |
+            StreamInstance::StaticStr(_) |
+            StreamInstance::ReadlineStream(_) |
+            StreamInstance::InputFile(..) |
+            StreamInstance::Null => {
                 Err(std::io::Error::new(
                     ErrorKind::PermissionDenied,
                     StreamError::WriteToInputStream,
@@ -1125,8 +1221,11 @@ impl Write for Stream {
             StreamInstance::Stdout => {
                 stdout().flush()
             }
-            StreamInstance::DynReadSource(_) | StreamInstance::ReadlineStream(_) |
-            StreamInstance::InputFile(..) | StreamInstance::Null => {
+            StreamInstance::PausedPrologStream(..) |
+            StreamInstance::StaticStr(_) |
+            StreamInstance::ReadlineStream(_) |
+            StreamInstance::InputFile(..) |
+            StreamInstance::Null => {
                 Err(std::io::Error::new(
                     ErrorKind::PermissionDenied,
                     StreamError::FlushToInputStream,
index 10ae3d7f40885a80e0ec3a83c43f2341c205992b..644f8296f0169eb8885963da22c96ad2694d89ad 100644 (file)
@@ -2470,10 +2470,11 @@ impl MachineState {
                         string.push(c as char);
                     }
                 } else {
-                    let mut iter = self.open_parsing_stream(stream.clone(),
-                                                            "get_n_chars",
-                                                            2,
-                                                            )?;
+                    let mut iter = self.open_parsing_stream(
+                        stream.clone(),
+                        "get_n_chars",
+                        2,
+                    )?;
 
                     for _ in 0..num {
                          let result = iter.next();
@@ -4475,16 +4476,10 @@ impl MachineState {
                 let mut heap_pstr_iter = self.heap_pstr_iter(self[temp_v!(1)]);
                 let chars = heap_pstr_iter.to_string();
 
-                let mut stream = self.open_parsing_stream(
-                    Stream::from(chars),
-                    "read_term_from_chars",
-                    2,
-                )?;
-
                 if let Addr::EmptyList = heap_pstr_iter.focus() {
                     let term_write_result =
                         match self.read(
-                            &mut stream,
+                            Stream::from(chars),
                             indices.atom_tbl.clone(),
                             &indices.op_dir,
                         ) {
index f26799b71005bd596477624805b1aedbaea784cc..6ee8f8d3462fe4fcf166d9f8c93d5be25e5138f8 100644 (file)
@@ -165,7 +165,7 @@ impl<'a> TermStream<'a> {
 
     #[inline]
     pub fn eof(&mut self) -> Result<bool, ParserError> {
-       self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
+           self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
         Ok(self.stack.is_empty() && self.parser.eof()?)
     }
 
index 9230f76e0ed280112a9bc7e6b92437e130ccdfdd..e468dfbdc94850a6caf4c6e4954ef3b80940d4b6 100644 (file)
@@ -67,10 +67,10 @@ pub mod readline {
                         }
                     }
 
-                    if self.pending_input.get_ref().chars().last() != Some('\n')
-                    {
+                    if self.pending_input.get_ref().chars().last() != Some('\n') {
                         *self.pending_input.get_mut() += "\n";
                     }
+
                     self.pending_input.read(buf)
                 }
                 Err(ReadlineError::Eof) => {
@@ -160,12 +160,23 @@ pub mod readline {
 impl MachineState {
     pub fn read(
         &mut self,
-        inner: &mut PrologStream,
+        mut inner: Stream,
         atom_tbl: TabledData<Atom>,
         op_dir: &OpDir,
     ) -> Result<TermWriteResult, ParserError> {
-        let mut parser = Parser::new(inner, atom_tbl, self.flags);
-        let term = parser.read_term(composite_op!(op_dir))?;
+        let mut stream = parsing_stream(inner.clone())?;
+
+        let term = {
+            let mut parser = Parser::new(&mut stream, atom_tbl, self.flags);
+            parser.read_term(composite_op!(op_dir))?
+        };
+
+        // 'pausing' the stream saves the pending top buffer
+        // created by the parsing stream, which was created in this
+        // scope and is about to be destroyed in it.
+
+        let buf = stream.take_buf();
+        inner.pause_stream(buf)?;
 
         Ok(write_term_to_heap(&term, self))
     }
index dfe53d26358f3f66c544d1c5b908b33d2e9d4ffa..bbada3a23fa2e665b4c7fa8b4d77329bd2941384 100644 (file)
@@ -108,28 +108,28 @@ read_and_match :-
     '$read_query_term'(_, Term, _, _, VarList),
     instruction_match(Term, VarList).
 
+
 % make compile_batch, a system routine, callable.
 compile_batch :- '$compile_batch'.
 
 instruction_match(Term, VarList) :-
     (  var(Term) ->
        throw(error(instantiation_error, repl/0))
-    ;
-    Term = [Item] -> !,
-                     (  atom(Item) ->
-                           (  Item == user ->
-                              catch(compile_batch, E, print_exception_with_check(E))
-                           ;  consult(Item)
-                           )
-                     ;
-                        catch(throw(error(type_error(atom, Item), repl/0)),
-                                  E,
-                                  print_exception_with_check(E))
-                     )
-    ;
-    Term = end_of_file -> halt
-    ;
-    submit_query_and_print_results(Term, VarList)
+    ;  Term = [Item] ->
+       !,
+       (  atom(Item) ->
+             (  Item == user ->
+                catch(compile_batch, E, print_exception_with_check(E))
+             ;  consult(Item)
+             )
+       ;
+          catch(throw(error(type_error(atom, Item), repl/0)),
+                    E,
+                    print_exception_with_check(E))
+       )
+    ;  Term = end_of_file ->
+       halt
+    ;  submit_query_and_print_results(Term, VarList)
     ).
 
 :- use_module(library(iso_ext)).
@@ -159,10 +159,10 @@ needs_bracketing(Value, Op) :-
              false),
     (  EqPrec < FPrec ->
        true
-    ;  '$quoted_token'(F) ->
-       true
     ;  FPrec > 0, F == Value, graphic_token_char(F) ->
        true
+    ;  F \== '.', '$quoted_token'(F) ->
+       true
     ;  EqPrec == FPrec,
        memberchk(EqSpec, [fx,xfx,yfx])
     ).