]> Repositorios git - scryer-prolog.git/commitdiff
refine EOF handling
authorMark <[email protected]>
Sun, 9 Jul 2023 04:25:30 +0000 (22:25 -0600)
committerMark <[email protected]>
Sun, 9 Jul 2023 04:25:30 +0000 (22:25 -0600)
scryer-prolog.wxs
src/machine/system_calls.rs
src/machine/term_stream.rs
src/parser/lexer.rs
src/parser/parser.rs
src/read.rs

index b69b1dff457ff1d103b837beef59d84bdc583769..fef55e496b4820f8a2b54a2f0f8ba4ebee2fa64a 100644 (file)
@@ -1,28 +1,28 @@
-<?xml version="1.0" encoding="utf-8"?>\r
-<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">\r
-  <Product Name="Scryer Prolog" Manufacturer="Scryer Prolog contributors" Id="*" UpgradeCode="cfb2dee4-5dd5-4d7d-b426-cd7340810559" Language="1033" Codepage="1252" Version="0.9.0">\r
-    <Package Description="An open source industrial strength production environment for ISO Prolog that is also a testbed for bleeding edge research in logic and constraint programming, which is itself written in a high-level language." Platform="x64" Keywords="prolog" Id="*" Compressed="yes" InstallScope="perMachine" InstallerVersion="300" Languages="1033" SummaryCodepage="1252" Manufacturer="Scryer Prolog contributors"/>\r
-    <Property Id="APPHELPLINK" Value="https://github.com/mthom/scryer-prolog"/>\r
-    <Media Id="1" Cabinet="scryer.cab" EmbedCab="yes" />\r
-    <Directory Id="TARGETDIR" Name="SourceDir">\r
-      <Directory Id="ProgramFilesFolder" Name="PFiles">\r
-        <Directory Id="INSTALLDIR" Name="Scryer Prolog">\r
-          <Component Id="MainExecutable" Guid="1b41ceda-ba18-47f9-911b-ee41b4f20921">\r
-            <File Id="ScryerPrologEXE" Name="scryer-prolog.exe" DiskId="1" Source="target/release/scryer-prolog.exe" KeyPath="yes" Checksum="yes"/>\r
-          </Component>\r
-        </Directory>\r
-      </Directory>\r
-      <Directory Id="ProgramMenuFolder">\r
-        <Component Id="ApplicationShortcut" Guid="8c9b14a3-e7b1-4d30-a892-61d7371dcae2">\r
-          <Shortcut Id="ApplicationStarMenuShortcut" Name="Scryer Prolog" Description="Launch Scryer Prolog" Target="[#ScryerPrologEXE]" WorkingDirectory="INSTALLDIR"/>\r
-          <RemoveFolder Id="ApplicationShortcut" On="uninstall"/>\r
-          <RegistryValue Root="HKCU" Key="Software\Microsoft\ScryerProlog" Name="installed" Type="integer" Value="1" KeyPath="yes"/>\r
-        </Component>\r
-      </Directory>\r
-    </Directory>\r
-    <Feature Id="Complete" Level="1" Display="expand" ConfigurableDirectory="INSTALLDIR">\r
-      <ComponentRef Id="MainExecutable"/>\r
-      <ComponentRef Id="ApplicationShortcut"/>\r
-    </Feature>\r
-  </Product>\r
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+  <Product Name="Scryer Prolog" Manufacturer="Scryer Prolog contributors" Id="*" UpgradeCode="cfb2dee4-5dd5-4d7d-b426-cd7340810559" Language="1033" Codepage="1252" Version="0.9.0">
+    <Package Description="An open source industrial strength production environment for ISO Prolog that is also a testbed for bleeding edge research in logic and constraint programming, which is itself written in a high-level language." Platform="x64" Keywords="prolog" Id="*" Compressed="yes" InstallScope="perMachine" InstallerVersion="300" Languages="1033" SummaryCodepage="1252" Manufacturer="Scryer Prolog contributors"/>
+    <Property Id="APPHELPLINK" Value="https://github.com/mthom/scryer-prolog"/>
+    <Media Id="1" Cabinet="scryer.cab" EmbedCab="yes" />
+    <Directory Id="TARGETDIR" Name="SourceDir">
+      <Directory Id="ProgramFilesFolder" Name="PFiles">
+        <Directory Id="INSTALLDIR" Name="Scryer Prolog">
+          <Component Id="MainExecutable" Guid="1b41ceda-ba18-47f9-911b-ee41b4f20921">
+            <File Id="ScryerPrologEXE" Name="scryer-prolog.exe" DiskId="1" Source="target/release/scryer-prolog.exe" KeyPath="yes" Checksum="yes"/>
+          </Component>
+        </Directory>
+      </Directory>
+      <Directory Id="ProgramMenuFolder">
+        <Component Id="ApplicationShortcut" Guid="8c9b14a3-e7b1-4d30-a892-61d7371dcae2">
+          <Shortcut Id="ApplicationStarMenuShortcut" Name="Scryer Prolog" Description="Launch Scryer Prolog" Target="[#ScryerPrologEXE]" WorkingDirectory="INSTALLDIR"/>
+          <RemoveFolder Id="ApplicationShortcut" On="uninstall"/>
+          <RegistryValue Root="HKCU" Key="Software\Microsoft\ScryerProlog" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
+        </Component>
+      </Directory>
+    </Directory>
+    <Feature Id="Complete" Level="1" Display="expand" ConfigurableDirectory="INSTALLDIR">
+      <ComponentRef Id="MainExecutable"/>
+      <ComponentRef Id="ApplicationShortcut"/>
+    </Feature>
+  </Product>
 </Wix>
\ No newline at end of file
index 11a724cc3eb00a3425fd101b128170035f9b28ce..c6cf925439978ebc12115780b082899804f3ca3e 100644 (file)
@@ -7469,17 +7469,21 @@ impl Machine {
 
     #[inline(always)]
     pub(crate) fn devour_whitespace(&mut self) -> CallResult {
-        let stream = self.machine_st.get_stream_or_alias(
+        let mut stream = self.machine_st.get_stream_or_alias(
             self.machine_st.registers[1],
             &self.indices.stream_aliases,
             atom!("$devour_whitespace"),
             1,
         )?;
 
-        match self.machine_st.devour_whitespace(stream) {
+        let mut parser = Parser::new(stream, &mut self.machine_st);
+
+        match devour_whitespace(&mut parser) {
             Ok(false) => { // not at EOF.
+                stream.add_lines_read(parser.lines_read());
             }
             Ok(true) => {
+                stream.add_lines_read(parser.lines_read());
                 self.machine_st.fail = true;
             }
             Err(err) => {
index 079f5c49b72e775030b5ffc52c515eab13809375..8c6b055da006d9b5a608c15ef85fe7233c9aafef 100644 (file)
@@ -5,6 +5,7 @@ use crate::machine::loader::*;
 use crate::machine::machine_errors::*;
 use crate::parser::ast::*;
 use crate::parser::parser::*;
+use crate::read::devour_whitespace;
 
 use crate::predicate_queue;
 
@@ -58,8 +59,8 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
 
     #[inline]
     fn eof(&mut self) -> Result<bool, CompilationError> {
-        self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF.
-        Ok(self.parser.eof()?)
+        devour_whitespace(&mut self.parser) // eliminate dangling comments before checking for EOF.
+            .map_err(CompilationError::from)
     }
 
     #[inline]
@@ -111,7 +112,7 @@ impl TermStream for LiveTermStream {
 
     #[inline]
     fn eof(&mut self) -> Result<bool, CompilationError> {
-        return Ok(self.term_queue.is_empty());
+        Ok(self.term_queue.is_empty())
     }
 
     #[inline]
index e3a81e6f03b9adddf4b74fa61efd48abe43da9fc..1eacc80b3673328fe6279a7d3e4fc1e4aa4cb7ac 100644 (file)
@@ -10,20 +10,6 @@ use crate::parser::rug::Integer;
 use std::convert::TryFrom;
 use std::fmt;
 
-macro_rules! is_not_eof {
-    ($parser:expr, $c:expr) => {
-        match $c {
-            Ok('\u{0}') => {
-                $parser.consume('\u{0}'.len_utf8());
-                return Ok(true);
-            }
-            Ok(c) => c,
-            Err(e) if e.is_unexpected_eof() => return Ok(true),
-            Err(e) => return Err(e),
-        }
-    };
-}
-
 macro_rules! consume_chars_with {
     ($token:expr, $e:expr) => {
         loop {
@@ -37,6 +23,12 @@ macro_rules! consume_chars_with {
     };
 }
 
+#[derive(Debug, Default)]
+pub struct LayoutInfo {
+    pub inserted: bool,
+    pub more: bool,
+}
+
 #[derive(Debug, PartialEq)]
 pub enum Token {
     Literal(Literal),
@@ -121,18 +113,6 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         }
     }
 
-    pub fn eof(&mut self) -> Result<bool, ParserError> {
-        let mut c = is_not_eof!(self.reader, self.lookahead_char());
-
-        while layout_char!(c) {
-            self.skip_char(c);
-
-            c = is_not_eof!(self.reader, self.lookahead_char());
-        }
-
-        Ok(false)
-    }
-
     fn single_line_comment(&mut self) -> Result<(), ParserError> {
         loop {
             if self.reader.peek_char().is_none() {
@@ -929,38 +909,48 @@ impl<'a, R: CharRead> Lexer<'a, R> {
         }
     }
 
-    pub fn scan_for_layout(&mut self) -> Result<bool, ParserError> {
-        let mut layout_inserted = false;
-        let mut more_layout = true;
+    pub fn consume_layout(
+        &mut self,
+        c: Option<char>,
+        layout_info: &mut LayoutInfo,
+    ) -> Result<(), ParserError> {
+        match c {
+            Some(c) if layout_char!(c) => {
+                self.skip_char(c);
+                layout_info.inserted = true;
+            }
+            Some(c) if end_line_comment_char!(c) => {
+                self.single_line_comment()?;
+                layout_info.inserted = true;
+            }
+            Some(c) if comment_1_char!(c) => {
+                if self.bracketed_comment()? {
+                    layout_info.inserted = true;
+                } else {
+                    layout_info.more = false;
+                }
+            }
+            _ => {
+                layout_info.more = false;
+            }
+        }
+
+        Ok(())
+    }
+
+    fn scan_for_layout(&mut self) -> Result<bool, ParserError> {
+        let mut layout_info = LayoutInfo { inserted: false, more: true };
 
         loop {
             let cr = self.lookahead_char();
+            self.consume_layout(cr.ok(), &mut layout_info)?;
 
-            match cr {
-                Ok(c) if layout_char!(c) => {
-                    self.skip_char(c);
-                    layout_inserted = true;
-                }
-                Ok(c) if end_line_comment_char!(c) => {
-                    self.single_line_comment()?;
-                    layout_inserted = true;
-                }
-                Ok(c) if comment_1_char!(c) => {
-                    if self.bracketed_comment()? {
-                        layout_inserted = true;
-                    } else {
-                        more_layout = false;
-                    }
-                }
-                _ => more_layout = false,
-            };
-
-            if !more_layout {
+            if !layout_info.more {
                 break;
             }
         }
 
-        Ok(layout_inserted)
+        Ok(layout_info.inserted)
     }
 
     pub fn next_token(&mut self) -> Result<Token, ParserError> {
index c170cfe0c794db59117ec640e2770c145c8b07c7..41cc108ca0e57603832bc22666e42751aab4e6b7 100644 (file)
@@ -621,7 +621,26 @@ impl<'a, R: CharRead> Parser<'a, R> {
     }
 
     pub fn devour_whitespace(&mut self) -> Result<(), ParserError> {
-        self.lexer.scan_for_layout()?;
+        match self.lexer.lookahead_char() {
+            Err(e) => { // if e.is_unexpected_eof() => {
+                return Err(e);
+            }
+            Ok(c) => {
+                let mut layout_info = LayoutInfo { inserted: false, more: true };
+                let mut cr = Some(c);
+
+                loop {
+                    self.lexer.consume_layout(cr, &mut layout_info)?;
+
+                    if !layout_info.more {
+                        break;
+                    }
+
+                    cr = self.lexer.lookahead_char().ok();
+                }
+            }
+        }
+
         Ok(())
     }
 
@@ -1051,11 +1070,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
         Ok(())
     }
 
-    #[inline]
-    pub fn eof(&mut self) -> Result<bool, ParserError> {
-        self.lexer.eof()
-    }
-
     #[inline]
     pub fn add_lines_read(&mut self, lines_read: usize) {
         self.lexer.line_num += lines_read;
index 86fdcdbdbf84624c9c2e3aced0982d7a1914355c..6094b38e9671ce5585afdd4dbb53459c31d47577 100644 (file)
@@ -24,19 +24,19 @@ use std::io::{Cursor, Error, ErrorKind, Read};
 
 type SubtermDeque = VecDeque<(usize, usize)>;
 
-impl MachineState {
-    pub(crate) fn devour_whitespace(
-        &mut self,
-        mut inner: Stream,
-    ) -> Result<bool, ParserError> {
-        let mut parser = Parser::new(inner, self);
-
-        parser.devour_whitespace()?;
-        inner.add_lines_read(parser.lines_read());
-
-        parser.eof()
+pub(crate) fn devour_whitespace<'a, R: CharRead>(parser: &mut Parser<'a, R>) -> Result<bool, ParserError> {
+    match parser.devour_whitespace() {
+        Err(e) if e.is_unexpected_eof() => {
+            Ok(true)
+        }
+        Err(e) => Err(e),
+        Ok(()) => {
+            Ok(false)
+        }
     }
+}
 
+impl MachineState {
     pub(crate) fn read(
         &mut self,
         mut inner: Stream,