refine EOF handling

This commit is contained in:
Mark
2023-07-08 22:25:30 -06:00
parent fb8e3071f2
commit b8a6882a27
6 changed files with 108 additions and 99 deletions

View File

@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <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"> <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"/> <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"/> <Property Id="APPHELPLINK" Value="https://github.com/mthom/scryer-prolog"/>
<Media Id="1" Cabinet="scryer.cab" EmbedCab="yes" /> <Media Id="1" Cabinet="scryer.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles"> <Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="Scryer Prolog"> <Directory Id="INSTALLDIR" Name="Scryer Prolog">
<Component Id="MainExecutable" Guid="1b41ceda-ba18-47f9-911b-ee41b4f20921"> <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"/> <File Id="ScryerPrologEXE" Name="scryer-prolog.exe" DiskId="1" Source="target/release/scryer-prolog.exe" KeyPath="yes" Checksum="yes"/>
</Component> </Component>
</Directory> </Directory>
</Directory> </Directory>
<Directory Id="ProgramMenuFolder"> <Directory Id="ProgramMenuFolder">
<Component Id="ApplicationShortcut" Guid="8c9b14a3-e7b1-4d30-a892-61d7371dcae2"> <Component Id="ApplicationShortcut" Guid="8c9b14a3-e7b1-4d30-a892-61d7371dcae2">
<Shortcut Id="ApplicationStarMenuShortcut" Name="Scryer Prolog" Description="Launch Scryer Prolog" Target="[#ScryerPrologEXE]" WorkingDirectory="INSTALLDIR"/> <Shortcut Id="ApplicationStarMenuShortcut" Name="Scryer Prolog" Description="Launch Scryer Prolog" Target="[#ScryerPrologEXE]" WorkingDirectory="INSTALLDIR"/>
<RemoveFolder Id="ApplicationShortcut" On="uninstall"/> <RemoveFolder Id="ApplicationShortcut" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\ScryerProlog" Name="installed" Type="integer" Value="1" KeyPath="yes"/> <RegistryValue Root="HKCU" Key="Software\Microsoft\ScryerProlog" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component> </Component>
</Directory> </Directory>
</Directory> </Directory>
<Feature Id="Complete" Level="1" Display="expand" ConfigurableDirectory="INSTALLDIR"> <Feature Id="Complete" Level="1" Display="expand" ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="MainExecutable"/> <ComponentRef Id="MainExecutable"/>
<ComponentRef Id="ApplicationShortcut"/> <ComponentRef Id="ApplicationShortcut"/>
</Feature> </Feature>
</Product> </Product>
</Wix> </Wix>

View File

@@ -7469,17 +7469,21 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn devour_whitespace(&mut self) -> CallResult { 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.machine_st.registers[1],
&self.indices.stream_aliases, &self.indices.stream_aliases,
atom!("$devour_whitespace"), atom!("$devour_whitespace"),
1, 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. Ok(false) => { // not at EOF.
stream.add_lines_read(parser.lines_read());
} }
Ok(true) => { Ok(true) => {
stream.add_lines_read(parser.lines_read());
self.machine_st.fail = true; self.machine_st.fail = true;
} }
Err(err) => { Err(err) => {

View File

@@ -5,6 +5,7 @@ use crate::machine::loader::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::parser::*; use crate::parser::parser::*;
use crate::read::devour_whitespace;
use crate::predicate_queue; use crate::predicate_queue;
@@ -58,8 +59,8 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline] #[inline]
fn eof(&mut self) -> Result<bool, CompilationError> { fn eof(&mut self) -> Result<bool, CompilationError> {
self.parser.devour_whitespace()?; // eliminate dangling comments before checking for EOF. devour_whitespace(&mut self.parser) // eliminate dangling comments before checking for EOF.
Ok(self.parser.eof()?) .map_err(CompilationError::from)
} }
#[inline] #[inline]
@@ -111,7 +112,7 @@ impl TermStream for LiveTermStream {
#[inline] #[inline]
fn eof(&mut self) -> Result<bool, CompilationError> { fn eof(&mut self) -> Result<bool, CompilationError> {
return Ok(self.term_queue.is_empty()); Ok(self.term_queue.is_empty())
} }
#[inline] #[inline]

View File

@@ -10,20 +10,6 @@ use crate::parser::rug::Integer;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; 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 { macro_rules! consume_chars_with {
($token:expr, $e:expr) => { ($token:expr, $e:expr) => {
loop { 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)] #[derive(Debug, PartialEq)]
pub enum Token { pub enum Token {
Literal(Literal), 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> { fn single_line_comment(&mut self) -> Result<(), ParserError> {
loop { loop {
if self.reader.peek_char().is_none() { 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> { pub fn consume_layout(
let mut layout_inserted = false; &mut self,
let mut more_layout = true; 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 { loop {
let cr = self.lookahead_char(); let cr = self.lookahead_char();
self.consume_layout(cr.ok(), &mut layout_info)?;
match cr { if !layout_info.more {
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 {
break; break;
} }
} }
Ok(layout_inserted) Ok(layout_info.inserted)
} }
pub fn next_token(&mut self) -> Result<Token, ParserError> { pub fn next_token(&mut self) -> Result<Token, ParserError> {

View File

@@ -621,7 +621,26 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
pub fn devour_whitespace(&mut self) -> Result<(), ParserError> { 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(()) Ok(())
} }
@@ -1051,11 +1070,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
Ok(()) Ok(())
} }
#[inline]
pub fn eof(&mut self) -> Result<bool, ParserError> {
self.lexer.eof()
}
#[inline] #[inline]
pub fn add_lines_read(&mut self, lines_read: usize) { pub fn add_lines_read(&mut self, lines_read: usize) {
self.lexer.line_num += lines_read; self.lexer.line_num += lines_read;

View File

@@ -24,19 +24,19 @@ use std::io::{Cursor, Error, ErrorKind, Read};
type SubtermDeque = VecDeque<(usize, usize)>; type SubtermDeque = VecDeque<(usize, usize)>;
impl MachineState { pub(crate) fn devour_whitespace<'a, R: CharRead>(parser: &mut Parser<'a, R>) -> Result<bool, ParserError> {
pub(crate) fn devour_whitespace( match parser.devour_whitespace() {
&mut self, Err(e) if e.is_unexpected_eof() => {
mut inner: Stream, Ok(true)
) -> Result<bool, ParserError> { }
let mut parser = Parser::new(inner, self); Err(e) => Err(e),
Ok(()) => {
parser.devour_whitespace()?; Ok(false)
inner.add_lines_read(parser.lines_read()); }
parser.eof()
} }
}
impl MachineState {
pub(crate) fn read( pub(crate) fn read(
&mut self, &mut self,
mut inner: Stream, mut inner: Stream,