name = "prolog_parser_rebis"
version = "0.8.68"
+edition = "2018"
repository = "https://github.com/mthom/prolog_parser"
description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation."
license = "BSD-3-Clause"
-use rug::{Integer, Rational};
+use crate::tabled_rc::*;
use ordered_float::*;
-use tabled_rc::*;
+use rug::{Integer, Rational};
-use put_back_n::*;
+use crate::put_back_n::*;
use std::cell::Cell;
use std::cmp::Ordering;
pub const XFX: u32 = 0x0001;
pub const XFY: u32 = 0x0002;
pub const YFX: u32 = 0x0004;
-pub const XF: u32 = 0x0010;
-pub const YF: u32 = 0x0020;
-pub const FX: u32 = 0x0040;
-pub const FY: u32 = 0x0080;
+pub const XF: u32 = 0x0010;
+pub const YF: u32 = 0x0020;
+pub const FX: u32 = 0x0040;
+pub const FY: u32 = 0x0080;
pub const DELIMITER: u32 = 0x0100;
-pub const TERM: u32 = 0x1000;
+pub const TERM: u32 = 0x1000;
pub const LTERM: u32 = 0x3000;
pub const NEGATIVE_SIGN: u32 = 0x0200;
#[macro_export]
macro_rules! clause_name {
- ($name: expr, $tbl: expr) => (
+ ($name: expr, $tbl: expr) => {
ClauseName::User(TabledRc::new($name, $tbl.clone()))
- ) ;
- ($name: expr) => (
+ };
+ ($name: expr) => {
ClauseName::BuiltIn($name)
- )
+ };
}
#[macro_export]
macro_rules! atom {
- ($e:expr, $tbl:expr) => (
+ ($e:expr, $tbl:expr) => {
Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None)
- );
- ($e:expr) => (
+ };
+ ($e:expr) => {
Constant::Atom(clause_name!($e), None)
- )
+ };
}
#[macro_export]
macro_rules! rc_atom {
- ($e:expr) => (
+ ($e:expr) => {
Rc::new(String::from($e))
- )
+ };
}
macro_rules! is_term {
- ($x:expr) => ( ($x & TERM) != 0 )
+ ($x:expr) => {
+ ($x & TERM) != 0
+ };
}
macro_rules! is_lterm {
- ($x:expr) => ( ($x & LTERM) != 0 )
+ ($x:expr) => {
+ ($x & LTERM) != 0
+ };
}
macro_rules! is_op {
- ($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 )
+ ($x:expr) => {
+ $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0
+ };
}
macro_rules! is_negate {
- ($x:expr) => ( ($x & NEGATIVE_SIGN) != 0 )
+ ($x:expr) => {
+ ($x & NEGATIVE_SIGN) != 0
+ };
}
#[macro_export]
macro_rules! is_prefix {
- ($x:expr) => ( $x & (FX | FY) != 0 )
+ ($x:expr) => {
+ $x & (FX | FY) != 0
+ };
}
#[macro_export]
macro_rules! is_postfix {
- ($x:expr) => ( $x & (XF | YF) != 0 )
+ ($x:expr) => {
+ $x & (XF | YF) != 0
+ };
}
#[macro_export]
macro_rules! is_infix {
- ($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
+ ($x:expr) => {
+ ($x & (XFX | XFY | YFX)) != 0
+ };
}
#[macro_export]
macro_rules! is_xfx {
- ($x:expr) => ( ($x & XFX) != 0 )
+ ($x:expr) => {
+ ($x & XFX) != 0
+ };
}
#[macro_export]
macro_rules! is_xfy {
- ($x:expr) => ( ($x & XFY) != 0 )
+ ($x:expr) => {
+ ($x & XFY) != 0
+ };
}
#[macro_export]
macro_rules! is_yfx {
- ($x:expr) => ( ($x & YFX) != 0 )
+ ($x:expr) => {
+ ($x & YFX) != 0
+ };
}
#[macro_export]
macro_rules! is_yf {
- ($x:expr) => ( ($x & YF) != 0 )
+ ($x:expr) => {
+ ($x & YF) != 0
+ };
}
#[macro_export]
macro_rules! is_xf {
- ($x:expr) => ( ($x & XF) != 0 )
+ ($x:expr) => {
+ ($x & XF) != 0
+ };
}
#[macro_export]
macro_rules! is_fx {
- ($x:expr) => ( ($x & FX) != 0 )
+ ($x:expr) => {
+ ($x & FX) != 0
+ };
}
#[macro_export]
macro_rules! is_fy {
- ($x:expr) => ( ($x & FY) != 0 )
+ ($x:expr) => {
+ ($x & FY) != 0
+ };
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RegType {
Perm(usize),
- Temp(usize)
+ Temp(usize),
}
impl Default for RegType {
impl RegType {
pub fn reg_num(self) -> usize {
match self {
- RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num
+ RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num,
}
}
pub fn is_perm(self) -> bool {
match self {
RegType::Perm(_) => true,
- _ => false
+ _ => false,
}
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&RegType::Perm(val) => write!(f, "Y{}", val),
- &RegType::Temp(val) => write!(f, "X{}", val)
+ &RegType::Temp(val) => write!(f, "X{}", val),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum VarReg {
ArgAndNorm(RegType, usize),
- Norm(RegType)
+ Norm(RegType),
}
impl VarReg {
pub fn norm(self) -> RegType {
match self {
- VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
+ VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg,
}
}
}
match self {
&VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
&VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
- &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
- write!(f, "Y{} A{}", reg, arg),
- &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
- write!(f, "X{} A{}", reg, arg)
+ &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg),
+ &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg),
}
}
}
#[macro_export]
macro_rules! temp_v {
- ($x:expr) => (
+ ($x:expr) => {
RegType::Temp($x)
- )
+ };
}
#[macro_export]
macro_rules! perm_v {
- ($x:expr) => (
+ ($x:expr) => {
RegType::Perm($x)
- )
+ };
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum GenContext {
- Head, Mid(usize), Last(usize) // Mid & Last: chunk_num
+ Head,
+ Mid(usize),
+ Last(usize), // Mid & Last: chunk_num
}
impl GenContext {
pub fn chunk_num(self) -> usize {
match self {
GenContext::Head => 0,
- GenContext::Mid(cn) | GenContext::Last(cn) => cn
+ GenContext::Mid(cn) | GenContext::Last(cn) => cn,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct MachineFlags {
- pub double_quotes: DoubleQuotes
+ pub double_quotes: DoubleQuotes,
}
impl Default for MachineFlags {
fn default() -> Self {
- MachineFlags { double_quotes: DoubleQuotes::default() }
+ MachineFlags {
+ double_quotes: DoubleQuotes::default(),
+ }
}
}
#[derive(Debug, Clone, Copy)]
pub enum DoubleQuotes {
- Atom, Chars, Codes
+ Atom,
+ Chars,
+ Codes,
}
impl DoubleQuotes {
pub fn default_op_dir() -> OpDir {
let mut op_dir = OpDir::new();
- op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200));
- op_dir.insert((clause_name!(":-"), Fixity::Pre), OpDirValue::new(FX, 1200));
- op_dir.insert((clause_name!("?-"), Fixity::Pre), OpDirValue::new(FX, 1200));
- op_dir.insert((clause_name!(","), Fixity::In), OpDirValue::new(XFY, 1000));
+ op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200));
+ op_dir.insert((clause_name!(":-"), Fixity::Pre), OpDirValue::new(FX, 1200));
+ op_dir.insert((clause_name!("?-"), Fixity::Pre), OpDirValue::new(FX, 1200));
+ op_dir.insert((clause_name!(","), Fixity::In), OpDirValue::new(XFY, 1000));
op_dir
}
#[derive(Debug, Clone)]
pub enum ArithmeticError {
NonEvaluableFunctor(Constant, usize),
- UninstantiatedVar
+ UninstantiatedVar,
}
#[derive(Debug)]
MissingQuote(usize, usize),
NonPrologChar(usize, usize),
ParseBigInt(usize, usize),
- Utf8Error(usize, usize)
+ Utf8Error(usize, usize),
}
impl ParserError {
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
match self {
&ParserError::BackQuotedString(line_num, col_num)
- | &ParserError::UnexpectedChar(_, line_num, col_num)
- | &ParserError::IncompleteReduction(line_num, col_num)
- | &ParserError::MissingQuote(line_num, col_num)
- | &ParserError::NonPrologChar(line_num, col_num)
- | &ParserError::ParseBigInt(line_num, col_num)
- | &ParserError::Utf8Error(line_num, col_num) =>
- Some((line_num, col_num)),
- _ =>
- None
+ | &ParserError::UnexpectedChar(_, line_num, col_num)
+ | &ParserError::IncompleteReduction(line_num, col_num)
+ | &ParserError::MissingQuote(line_num, col_num)
+ | &ParserError::NonPrologChar(line_num, col_num)
+ | &ParserError::ParseBigInt(line_num, col_num)
+ | &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
+ _ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
- &ParserError::BackQuotedString(..) =>
- "back_quoted_string",
- &ParserError::UnexpectedChar(..) =>
- "unexpected_char",
- &ParserError::UnexpectedEOF =>
- "unexpected_end_of_file",
- &ParserError::IncompleteReduction(..) =>
- "incomplete_reduction",
- &ParserError::InvalidSingleQuotedCharacter(..) =>
- "invalid_single_quoted_character",
- &ParserError::IO(_) =>
- "input_output_error",
- &ParserError::MissingQuote(..) =>
- "missing_quote",
- &ParserError::NonPrologChar(..) =>
- "non_prolog_character",
- &ParserError::ParseBigInt(..) =>
- "cannot_parse_big_int",
- &ParserError::Utf8Error(..) =>
- "utf8_conversion_error",
+ &ParserError::BackQuotedString(..) => "back_quoted_string",
+ &ParserError::UnexpectedChar(..) => "unexpected_char",
+ &ParserError::UnexpectedEOF => "unexpected_end_of_file",
+ &ParserError::IncompleteReduction(..) => "incomplete_reduction",
+ &ParserError::InvalidSingleQuotedCharacter(..) => "invalid_single_quoted_character",
+ &ParserError::IO(_) => "input_output_error",
+ &ParserError::MissingQuote(..) => "missing_quote",
+ &ParserError::NonPrologChar(..) => "non_prolog_character",
+ &ParserError::ParseBigInt(..) => "cannot_parse_big_int",
+ &ParserError::Utf8Error(..) => "utf8_conversion_error",
}
}
}
}
}
-
#[derive(Debug, Clone, Copy)]
pub struct CompositeOpDir<'a, 'b> {
pub primary_op_dir: Option<&'b OpDir>,
pub secondary_op_dir: &'a OpDir,
}
-impl<'a, 'b> CompositeOpDir<'a, 'b>
-{
+impl<'a, 'b> CompositeOpDir<'a, 'b> {
#[inline]
pub fn new(secondary_op_dir: &'a OpDir, primary_op_dir: Option<&'b OpDir>) -> Self {
- CompositeOpDir { primary_op_dir, secondary_op_dir }
+ CompositeOpDir {
+ primary_op_dir,
+ secondary_op_dir,
+ }
}
#[inline]
- pub(crate)
- fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue>
- {
- let entry =
- if let Some(ref primary_op_dir) = &self.primary_op_dir {
- primary_op_dir.get(&(name.clone(), fixity))
- } else {
- None
- };
+ pub(crate) fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue> {
+ let entry = if let Some(ref primary_op_dir) = &self.primary_op_dir {
+ primary_op_dir.get(&(name.clone(), fixity))
+ } else {
+ None
+ };
entry.or_else(move || self.secondary_op_dir.get(&(name, fixity)))
}
}
-
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum Fixity {
- In, Post, Pre
+ In,
+ Post,
+ Pre,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &Constant::Atom(ref atom, _) =>
+ &Constant::Atom(ref atom, _) => {
if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
write!(f, "'{}'", atom.as_str())
} else {
write!(f, "{}", atom.as_str())
- },
- &Constant::Char(c) =>
- write!(f, "'{}'", c as u32),
- &Constant::EmptyList =>
- write!(f, "[]"),
- &Constant::Fixnum(n) =>
- write!(f, "{}", n),
- &Constant::Integer(ref n) =>
- write!(f, "{}", n),
- &Constant::Rational(ref n) =>
- write!(f, "{}", n),
- &Constant::Float(ref n) =>
- write!(f, "{}", n),
- &Constant::String(ref s) =>
- write!(f, "\"{}\"", &s),
- &Constant::Usize(integer) =>
- write!(f, "u{}", integer),
+ }
+ }
+ &Constant::Char(c) => write!(f, "'{}'", c as u32),
+ &Constant::EmptyList => write!(f, "[]"),
+ &Constant::Fixnum(n) => write!(f, "{}", n),
+ &Constant::Integer(ref n) => write!(f, "{}", n),
+ &Constant::Rational(ref n) => write!(f, "{}", n),
+ &Constant::Float(ref n) => write!(f, "{}", n),
+ &Constant::String(ref s) => write!(f, "\"{}\"", &s),
+ &Constant::Usize(integer) => write!(f, "u{}", integer),
}
}
}
fn eq(&self, other: &Constant) -> bool {
match (self, other) {
(&Constant::Atom(ref atom, _), &Constant::Char(c))
- | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => {
- atom.is_char() && Some(c) == atom.as_str().chars().next()
- },
- (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) =>
- a1.as_str() == a2.as_str(),
- (&Constant::Char(c1), &Constant::Char(c2)) =>
- c1 == c2,
- (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) =>
- n1 == n2,
- (&Constant::Fixnum(n1), &Constant::Integer(ref n2)) |
- (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => {
+ | (&Constant::Char(c), &Constant::Atom(ref atom, _)) => {
+ atom.is_char() && Some(c) == atom.as_str().chars().next()
+ }
+ (&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(),
+ (&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2,
+ (&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2,
+ (&Constant::Fixnum(n1), &Constant::Integer(ref n2))
+ | (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => {
if let Some(n2) = n2.to_isize() {
n1 == n2
} else {
false
}
}
- (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) =>
- n1 == n2,
- (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) =>
- n1 == n2,
- (&Constant::Float(ref n1), &Constant::Float(ref n2)) =>
- n1 == n2,
- (&Constant::String(ref s1), &Constant::String(ref s2)) => {
- &s1 == &s2
- }
- (&Constant::EmptyList, &Constant::EmptyList) =>
- true,
- (&Constant::Usize(u1), &Constant::Usize(u2)) =>
- u1 == u2,
- _ => false
+ (&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2,
+ (&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2,
+ (&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2,
+ (&Constant::String(ref s1), &Constant::String(ref s2)) => &s1 == &s2,
+ (&Constant::EmptyList, &Constant::EmptyList) => true,
+ (&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2,
+ _ => false,
}
}
}
pub fn to_atom(self) -> Option<ClauseName> {
match self {
Constant::Atom(a, _) => Some(a.defrock_brackets()),
- _ => None
+ _ => None,
}
}
}
#[derive(Debug, Clone)]
pub enum ClauseName {
BuiltIn(&'static str),
- User(TabledRc<Atom>)
+ User(TabledRc<Atom>),
}
impl fmt::Display for ClauseName {
match self {
&ClauseName::User(ref name) => {
let module = name.owning_module();
- ClauseName::User(TabledRc { atom: module.clone(),
- table: TabledData::new(module) })
- },
- _ => clause_name!("user")
+ ClauseName::User(TabledRc {
+ atom: module.clone(),
+ table: TabledData::new(module),
+ })
+ }
+ _ => clause_name!("user"),
}
}
pub fn to_rc(&self) -> Rc<String> {
match self {
&ClauseName::BuiltIn(s) => Rc::new(s.to_string()),
- &ClauseName::User(ref rc) => rc.inner()
+ &ClauseName::User(ref rc) => rc.inner(),
}
}
false
}
}
- ClauseName::User(ref name) => {
- other.has_table(&name.table)
- }
+ ClauseName::User(ref name) => other.has_table(&name.table),
}
}
pub fn as_str(&self) -> &str {
match self {
&ClauseName::BuiltIn(s) => s,
- &ClauseName::User(ref name) => name.as_ref()
+ &ClauseName::User(ref name) => name.as_ref(),
}
}
pub fn defrock_brackets(self) -> Self {
fn defrock_brackets(s: &str) -> &str {
if s.starts_with('(') && s.ends_with(')') {
- &s[1 .. s.len() - 1]
+ &s[1..s.len() - 1]
} else {
s
}
}
match self {
- ClauseName::BuiltIn(s) =>
- ClauseName::BuiltIn(defrock_brackets(s)),
- ClauseName::User(s) =>
+ ClauseName::BuiltIn(s) => ClauseName::BuiltIn(defrock_brackets(s)),
+ ClauseName::User(s) => {
ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table))
+ }
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Term {
AnonVar,
- Clause(Cell<RegType>, ClauseName, Vec<Box<Term>>, Option<SharedOpDesc>),
+ Clause(
+ Cell<RegType>,
+ ClauseName,
+ Vec<Box<Term>>,
+ Option<SharedOpDesc>,
+ ),
Cons(Cell<RegType>, Box<Term>, Box<Term>),
Constant(Cell<RegType>, Constant),
- Var(Cell<VarReg>, Rc<Var>)
+ Var(Cell<VarReg>, Rc<Var>),
}
impl Term {
match self {
&Term::Clause(_, _, _, ref spec) => spec.clone(),
&Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(),
- _ => None
+ _ => None,
}
}
pub fn to_constant(self) -> Option<Constant> {
match self {
Term::Constant(_, c) => Some(c),
- _ => None
+ _ => None,
}
}
pub fn first_arg(&self) -> Option<&Term> {
match self {
- &Term::Clause(_, _, ref terms, _) =>
- terms.first().map(|bt| bt.as_ref()),
- _ => None
+ &Term::Clause(_, _, ref terms, _) => terms.first().map(|bt| bt.as_ref()),
+ _ => None,
}
}
pub fn set_name(&mut self, new_name: ClauseName) {
match self {
Term::Constant(_, Constant::Atom(ref mut atom, _))
- | Term::Clause(_, ref mut atom, ..) => {
- *atom = new_name;
+ | Term::Clause(_, ref mut atom, ..) => {
+ *atom = new_name;
}
_ => {}
}
pub fn name(&self) -> Option<ClauseName> {
match self {
- &Term::Constant(_, Constant::Atom(ref atom, _))
- | &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
- _ => None
+ &Term::Constant(_, Constant::Atom(ref atom, _)) | &Term::Clause(_, ref atom, ..) => {
+ Some(atom.clone())
+ }
+ _ => None,
}
}
pub fn arity(&self) -> usize {
match self {
&Term::Clause(_, _, ref child_terms, ..) => child_terms.len(),
- _ => 0
+ _ => 0,
}
}
}
-use crate::lexical::parse_lossy;
-use crate::ordered_float::*;
use crate::rug::Integer;
+use lexical::parse_lossy;
+use ordered_float::*;
-use ast::*;
-use tabled_rc::*;
+use crate::ast::*;
+use crate::tabled_rc::*;
use std::convert::TryFrom;
use std::fmt;
use std::rc::Rc;
macro_rules! is_not_eof {
- ($c:expr) => (
+ ($c:expr) => {
match $c {
Ok(c) => c,
Err(ParserError::UnexpectedEOF) => return Ok(true),
- Err(e) => return Err(e)
+ Err(e) => return Err(e),
}
- )
+ };
}
macro_rules! consume_chars_with {
Ok(Some(c)) => $token.push(c),
Ok(None) => continue,
Err(ParserError::UnexpectedChar(..)) => break,
- Err(e) => return Err(e)
+ Err(e) => return Err(e),
}
}
- }
+ };
}
#[derive(Debug, Clone, PartialEq)]
pub enum Token {
Constant(Constant),
Var(Rc<Atom>),
- Open, // '('
- OpenCT, // '('
- Close, // ')'
- OpenList, // '['
- CloseList, // ']'
- OpenCurly, // '{'
- CloseCurly, // '}'
+ Open, // '('
+ OpenCT, // '('
+ Close, // ')'
+ OpenList, // '['
+ CloseList, // ']'
+ OpenCurly, // '{'
+ CloseCurly, // '}'
HeadTailSeparator, // '|'
- Comma, // ','
- End
+ Comma, // ','
+ End,
}
pub struct Lexer<'a, R: Read> {
pub(crate) reader: &'a mut ParsingStream<R>,
pub(crate) flags: MachineFlags,
pub(crate) line_num: usize,
- pub(crate) col_num: usize
+ pub(crate) col_num: usize,
}
impl<'a, R: Read + fmt::Debug> fmt::Debug for Lexer<'a, R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lexer")
- .field("atom_tbl", &self.atom_tbl)
- .field("reader", &"&'a mut ParsingStream<R>") // Hacky solution.
- .field("line_num", &self.line_num)
- .field("col_num", &self.col_num)
- .finish()
+ .field("atom_tbl", &self.atom_tbl)
+ .field("reader", &"&'a mut ParsingStream<R>") // Hacky solution.
+ .field("line_num", &self.line_num)
+ .field("col_num", &self.col_num)
+ .finish()
}
}
flags: MachineFlags,
src: &'a mut ParsingStream<R>,
) -> Self {
- Lexer { atom_tbl, flags, reader: src, line_num: 0, col_num: 0 }
+ Lexer {
+ atom_tbl,
+ flags,
+ reader: src,
+ line_num: 0,
+ col_num: 0,
+ }
}
fn return_char(&mut self, c: char) {
}
}
- fn single_line_comment(&mut self) -> Result<(), ParserError>
- {
+ fn single_line_comment(&mut self) -> Result<(), ParserError> {
loop {
if self.reader.peek().is_none() || new_line_char!(self.skip_char()?) {
break;
}
}
- fn get_single_quoted_item(&mut self) -> Result<Option<char>, ParserError>
- {
+ fn get_single_quoted_item(&mut self) -> Result<Option<char>, ParserError> {
if backslash_char!(self.lookahead_char()?) {
let c = self.skip_char()?;
}
}
- fn get_double_quoted_item(&mut self) -> Result<Option<char>, ParserError>
- {
+ fn get_double_quoted_item(&mut self) -> Result<Option<char>, ParserError> {
if backslash_char!(self.lookahead_char()?) {
let c = self.skip_char()?;
if new_line_char!(self.lookahead_char()?) {
self.skip_char()?;
- return Ok(None)
+ return Ok(None);
} else {
self.return_char(c);
}
}
}
- fn get_control_escape_sequence(&mut self) -> Result<char, ParserError>
- {
+ fn get_control_escape_sequence(&mut self) -> Result<char, ParserError> {
let escaped = match self.lookahead_char()? {
'a' => '\u{07}', // UTF-8 alert
'b' => '\u{08}', // UTF-8 backspace
't' => '\t',
'n' => '\n',
'r' => '\r',
- c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num))
+ c => return Err(ParserError::UnexpectedChar(c, self.line_num, self.col_num)),
};
self.skip_char()?;
return Ok(escaped);
}
- fn get_octal_escape_sequence(&mut self) -> Result<char, ParserError>
- {
+ fn get_octal_escape_sequence(&mut self) -> Result<char, ParserError> {
self.escape_sequence_to_char(|c| octal_digit_char!(c), 8)
}
- fn get_hexadecimal_escape_sequence(&mut self) -> Result<char, ParserError>
- {
+ fn get_hexadecimal_escape_sequence(&mut self) -> Result<char, ParserError> {
self.skip_char()?;
let c = self.lookahead_char()?;
if backslash_char!(c) {
self.skip_char()?;
- u32::from_str_radix(&token, radix)
- .map_or_else(
- |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
- |n| char::try_from(n)
+ u32::from_str_radix(&token, radix).map_or_else(
+ |_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
+ |n| {
+ char::try_from(n)
.map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num))
- )
+ },
+ )
} else {
// on failure, restore the token characters and backslash.
self.reader.put_back_all(token.chars().map(Ok));
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
Integer::from_str_radix(&token, 16)
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
self.return_char('x');
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
Integer::from_str_radix(&token, 8)
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
self.return_char('o');
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
Integer::from_str_radix(&token, 2)
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else {
self.return_char('b');
}
}
} else {
- return Err(ParserError::InvalidSingleQuotedCharacter(self.lookahead_char()?))
+ return Err(ParserError::InvalidSingleQuotedCharacter(
+ self.lookahead_char()?,
+ ));
}
} else {
match self.get_back_quoted_string() {
- Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
- Err(e) => return Err(e)
+ Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
+ Err(e) => return Err(e),
}
}
isize::from_str_radix(&token, 10)
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
} else if decimal_digit_char!(self.lookahead_char()?) {
token.push('.');
let c = match self.lookahead_char() {
Err(_) => return Ok(self.vacate_with_float(token)),
- Ok(c) => c
+ Ok(c) => c,
};
if !sign_char!(c) && !decimal_digit_char!(c) {
Err(_) => {
self.return_char(token.pop().unwrap());
return Ok(self.vacate_with_float(token));
- },
- Ok(c) => c
+ }
+ Ok(c) => c,
};
if !decimal_digit_char!(c) {
isize::from_str_radix(&token, 10)
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
}
} else {
if token.starts_with('0') && token.len() == 1 {
if c == 'x' {
- self.hexadecimal_constant()
- .or_else(|e| {
- if let ParserError::ParseBigInt(..) = e {
- isize::from_str_radix(&token, 10)
- .map(|n| Token::Constant(Constant::Fixnum(n)))
- .or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
- })
- } else {
- Err(e)
- }
- })
+ self.hexadecimal_constant().or_else(|e| {
+ if let ParserError::ParseBigInt(..) = e {
+ isize::from_str_radix(&token, 10)
+ .map(|n| Token::Constant(Constant::Fixnum(n)))
+ .or_else(|_| {
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| {
+ ParserError::ParseBigInt(self.line_num, self.col_num)
+ })
+ })
+ } else {
+ Err(e)
+ }
+ })
} else if c == 'o' {
- self.octal_constant()
- .or_else(|e| {
- if let ParserError::ParseBigInt(..) = e {
- isize::from_str_radix(&token, 10)
- .map(|n| Token::Constant(Constant::Fixnum(n)))
- .or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
- })
- } else {
- Err(e)
- }
- })
+ self.octal_constant().or_else(|e| {
+ if let ParserError::ParseBigInt(..) = e {
+ isize::from_str_radix(&token, 10)
+ .map(|n| Token::Constant(Constant::Fixnum(n)))
+ .or_else(|_| {
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| {
+ ParserError::ParseBigInt(self.line_num, self.col_num)
+ })
+ })
+ } else {
+ Err(e)
+ }
+ })
} else if c == 'b' {
- self.binary_constant()
- .or_else(|e| {
- if let ParserError::ParseBigInt(..) = e {
- isize::from_str_radix(&token, 10)
- .map(|n| Token::Constant(Constant::Fixnum(n)))
- .or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
- })
- } else {
- Err(e)
- }
- })
+ self.binary_constant().or_else(|e| {
+ if let ParserError::ParseBigInt(..) = e {
+ isize::from_str_radix(&token, 10)
+ .map(|n| Token::Constant(Constant::Fixnum(n)))
+ .or_else(|_| {
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| {
+ ParserError::ParseBigInt(self.line_num, self.col_num)
+ })
+ })
+ } else {
+ Err(e)
+ }
+ })
} else if single_quote_char!(c) {
self.skip_char()?;
}
self.get_single_quoted_char()
- .and_then(|c| {
- Ok(Token::Constant(Constant::Fixnum(c as isize)))
- })
+ .and_then(|c| Ok(Token::Constant(Constant::Fixnum(c as isize))))
.or_else(|_| {
self.return_char(c);
isize::from_str_radix(&token, 10)
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| {
+ ParserError::ParseBigInt(self.line_num, self.col_num)
+ })
})
})
} else {
isize::from_str_radix(&token, 10)
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
}
} else {
isize::from_str_radix(&token, 10)
.map(|n| Token::Constant(Constant::Fixnum(n)))
.or_else(|_| {
- token.parse::<Integer>()
- .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
- .map_err(|_| ParserError::ParseBigInt(
- self.line_num,
- self.col_num,
- ))
+ token
+ .parse::<Integer>()
+ .map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
+ .map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
})
}
}
Ok(c) if layout_char!(c) || new_line_char!(c) => {
self.skip_char()?;
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) =>
+ }
+ Ok(c) if comment_1_char!(c) => {
if self.bracketed_comment()? {
layout_inserted = true;
} else {
more_layout = false;
- },
- _ => more_layout = false
+ }
+ }
+ _ => more_layout = false,
};
if !more_layout {
if c == '(' {
self.skip_char()?;
- return Ok(if layout_inserted { Token::Open }
- else { Token::OpenCT });
+ return Ok(if layout_inserted {
+ Token::Open
+ } else {
+ Token::OpenCT
+ });
}
if c == '.' {
}
return Ok(Token::End);
- },
+ }
Err(ParserError::UnexpectedEOF) => {
return Ok(Token::End);
}
}
self.name_token(c)
- },
- Err(e) => Err(e)
+ }
+ Err(e) => Err(e),
}
}
}
-extern crate lexical;
-extern crate ordered_float;
-#[cfg(feature = "rug")]
-extern crate rug;
#[cfg(feature = "num-rug-adapter")]
-extern crate num_rug_adapter as rug;
-extern crate unicode_reader;
+use num_rug_adapter as rug;
+#[cfg(feature = "rug")]
+use rug;
-#[macro_use] pub mod tabled_rc;
-#[macro_use] pub mod ast;
-#[macro_use] pub mod macros;
+#[macro_use]
+pub mod tabled_rc;
+#[macro_use]
+pub mod ast;
+#[macro_use]
+pub mod macros;
pub mod parser;
pub mod put_back_n;
-use ast::*;
-use lexer::*;
-use tabled_rc::*;
+use crate::ast::*;
+use crate::lexer::*;
+use crate::tabled_rc::*;
use ordered_float::OrderedFloat;
-use rug::ops::NegAssign;
+use crate::rug::ops::NegAssign;
use std::cell::Cell;
use std::io::Read;
Term,
Open,
OpenCT,
- OpenList, // '['
- OpenCurly, // '{'
+ OpenList, // '['
+ OpenCurly, // '{'
HeadTailSeparator, // '|'
- Comma, // ','
+ Comma, // ','
Close,
- CloseList, // ']'
- CloseCurly, // '}'
- End
+ CloseList, // ']'
+ CloseCurly, // '}'
+ End,
}
impl TokenType {
fn is_sep(self) -> bool {
match self {
- TokenType::HeadTailSeparator | TokenType::OpenCT | TokenType::Open |
- TokenType::Close | TokenType::OpenList | TokenType::CloseList |
- TokenType::OpenCurly | TokenType::CloseCurly | TokenType::Comma
- => true,
- _ => false
+ TokenType::HeadTailSeparator
+ | TokenType::OpenCT
+ | TokenType::Open
+ | TokenType::Close
+ | TokenType::OpenList
+ | TokenType::CloseList
+ | TokenType::OpenCurly
+ | TokenType::CloseCurly
+ | TokenType::Comma => true,
+ _ => false,
}
}
}
struct TokenDesc {
tt: TokenType,
priority: usize,
- spec: u32
+ spec: u32,
}
-pub
-fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> Option<SharedOpDesc>
-{
+pub fn get_clause_spec(
+ name: ClauseName,
+ arity: usize,
+ op_dir: &CompositeOpDir,
+) -> Option<SharedOpDesc> {
match arity {
1 => {
/* This is a clause with an operator principal functor. Prefix operators
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::Post) {
return Some(cell.clone());
}
- },
- 2 =>
+ }
+ 2 => {
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::In) {
return Some(cell.clone());
- },
+ }
+ }
_ => {}
};
None
}
-pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option<OpDesc>
-{
- let mut op_desc = OpDesc { pre: 0, inf: 0, post: 0, spec: 0 };
+pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option<OpDesc> {
+ let mut op_desc = OpDesc {
+ pre: 0,
+ inf: 0,
+ post: 0,
+ spec: 0,
+ };
if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) {
let (pri, spec) = cell.get();
}
}
-fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool
-{
+fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool {
d2.priority <= priority
&& is_term!(d3.spec)
&& is_term!(d1.spec)
&& d1.priority < d2.priority
}
-fn affirm_yfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool
-{
+fn affirm_yfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool {
d2.priority <= priority
- && ((is_term!(d3.spec) && d3.priority < d2.priority)
- || (is_lterm!(d3.spec) && d3.priority == d2.priority))
+ && ((is_term!(d3.spec) && d3.priority < d2.priority)
+ || (is_lterm!(d3.spec) && d3.priority == d2.priority))
&& is_term!(d1.spec)
&& d1.priority < d2.priority
}
-
-fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool
-{
+fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> bool {
d2.priority < priority
&& is_term!(d3.spec)
&& d3.priority < d2.priority
&& d1.priority <= d2.priority
}
-fn affirm_yf(d1: TokenDesc, d2: TokenDesc) -> bool
-{
+fn affirm_yf(d1: TokenDesc, d2: TokenDesc) -> bool {
let is_valid_lterm = is_lterm!(d2.spec) && d2.priority == d1.priority;
(is_term!(d2.spec) && d2.priority < d1.priority) || is_valid_lterm
}
-fn affirm_xf(d1: TokenDesc, d2: TokenDesc) -> bool
-{
+fn affirm_xf(d1: TokenDesc, d2: TokenDesc) -> bool {
is_term!(d2.spec) && d2.priority < d1.priority
}
-fn affirm_fy(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool
-{
+fn affirm_fy(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool {
d2.priority < priority && is_term!(d1.spec) && d1.priority <= d2.priority
}
-fn affirm_fx(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool
-{
+fn affirm_fx(priority: usize, d1: TokenDesc, d2: TokenDesc) -> bool {
d2.priority <= priority && is_term!(d1.spec) && d1.priority < d2.priority
}
-fn sep_to_atom(tt: TokenType) -> Option<ClauseName>
-{
+fn sep_to_atom(tt: TokenType) -> Option<ClauseName> {
match tt {
- TokenType::Open | TokenType::OpenCT =>
- Some(clause_name!("(")),
- TokenType::Close =>
- Some(clause_name!(")")),
- TokenType::OpenList =>
- Some(clause_name!("[")),
- TokenType::CloseList =>
- Some(clause_name!("]")),
- TokenType::OpenCurly =>
- Some(clause_name!("{")),
- TokenType::CloseCurly =>
- Some(clause_name!("}")),
- TokenType::HeadTailSeparator =>
- Some(clause_name!("|")),
- TokenType::Comma =>
- Some(clause_name!(",")),
- TokenType::End =>
- Some(clause_name!(".")),
- _ => None
+ TokenType::Open | TokenType::OpenCT => Some(clause_name!("(")),
+ TokenType::Close => Some(clause_name!(")")),
+ TokenType::OpenList => Some(clause_name!("[")),
+ TokenType::CloseList => Some(clause_name!("]")),
+ TokenType::OpenCurly => Some(clause_name!("{")),
+ TokenType::CloseCurly => Some(clause_name!("}")),
+ TokenType::HeadTailSeparator => Some(clause_name!("|")),
+ TokenType::Comma => Some(clause_name!(",")),
+ TokenType::End => Some(clause_name!(".")),
+ _ => None,
}
}
pub pre: usize,
pub inf: usize,
pub post: usize,
- pub spec: Specifier
+ pub spec: Specifier,
}
#[derive(Debug)]
terms: Vec<Term>,
}
-fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result<Vec<Token>, ParserError>
-{
+fn read_tokens<'a, R: Read>(lexer: &mut Lexer<'a, R>) -> Result<Vec<Token>, ParserError> {
let mut tokens = vec![];
loop {
atom_tbl: TabledData<Atom>,
flags: MachineFlags,
) -> Self {
- Parser { lexer: Lexer::new(atom_tbl, flags, stream),
- tokens: vec![],
- stack: Vec::new(),
- terms: Vec::new() }
+ Parser {
+ lexer: Lexer::new(atom_tbl, flags, stream),
+ tokens: vec![],
+ stack: Vec::new(),
+ terms: Vec::new(),
+ }
}
#[inline]
fn get_term_name(&mut self, td: TokenDesc) -> Option<(ClauseName, Option<SharedOpDesc>)> {
match td.tt {
- TokenType::HeadTailSeparator => {
- Some((clause_name!("|"), Some(SharedOpDesc::new(td.priority, td.spec))))
- }
- TokenType::Comma => {
- Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY))))
- }
- TokenType::Term => {
- match self.terms.pop() {
- Some(Term::Constant(_, Constant::Atom(atom, spec))) =>
- Some((atom, spec)),
- Some(term) => {
- self.terms.push(term);
- None
- },
- _ => None
+ TokenType::HeadTailSeparator => Some((
+ clause_name!("|"),
+ Some(SharedOpDesc::new(td.priority, td.spec)),
+ )),
+ TokenType::Comma => Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY)))),
+ TokenType::Term => match self.terms.pop() {
+ Some(Term::Constant(_, Constant::Atom(atom, spec))) => Some((atom, spec)),
+ Some(term) => {
+ self.terms.push(term);
+ None
}
- }
- _ => {
- None
- }
+ _ => None,
+ },
+ _ => None,
}
}
- fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier)
- {
+ fn push_binary_op(&mut self, td: TokenDesc, spec: Specifier) {
if let Some(arg2) = self.terms.pop() {
if let Some((name, shared_op_desc)) = self.get_term_name(td) {
if let Some(arg1) = self.terms.pop() {
- let term = Term::Clause(Cell::default(),
- name,
- vec![Box::new(arg1), Box::new(arg2)],
- shared_op_desc);
+ let term = Term::Clause(
+ Cell::default(),
+ name,
+ vec![Box::new(arg1), Box::new(arg2)],
+ shared_op_desc,
+ );
self.terms.push(term);
- self.stack.push(TokenDesc { tt: TokenType::Term,
- priority: td.priority,
- spec });
+ self.stack.push(TokenDesc {
+ tt: TokenType::Term,
+ priority: td.priority,
+ spec,
+ });
}
}
}
}
- fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32)
- {
+ fn push_unary_op(&mut self, td: TokenDesc, spec: Specifier, assoc: u32) {
if let Some(mut arg1) = self.terms.pop() {
if let Some(mut name) = self.terms.pop() {
if is_postfix!(assoc) {
}
if let Term::Constant(_, Constant::Atom(name, shared_op_desc)) = name {
- let term = Term::Clause(Cell::default(), name, vec![Box::new(arg1)],
- shared_op_desc);
+ let term =
+ Term::Clause(Cell::default(), name, vec![Box::new(arg1)], shared_op_desc);
self.terms.push(term);
- self.stack.push(TokenDesc { tt: TokenType::Term,
- priority: td.priority,
- spec });
+ self.stack.push(TokenDesc {
+ tt: TokenType::Term,
+ priority: td.priority,
+ spec,
+ });
}
}
}
}
- fn promote_atom_op(&mut self, atom: ClauseName, priority: usize, assoc: u32,
- op_dir_val: Option<&OpDirValue>)
- {
+ fn promote_atom_op(
+ &mut self,
+ atom: ClauseName,
+ priority: usize,
+ assoc: u32,
+ op_dir_val: Option<&OpDirValue>,
+ ) {
let spec = op_dir_val.map(|op_dir_val| op_dir_val.shared_op_desc());
- self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, spec)));
- self.stack.push(TokenDesc { tt: TokenType::Term, priority, spec: assoc });
+ self.terms
+ .push(Term::Constant(Cell::default(), Constant::Atom(atom, spec)));
+ self.stack.push(TokenDesc {
+ tt: TokenType::Term,
+ priority,
+ spec: assoc,
+ });
}
- fn shift(&mut self, token: Token, priority: usize, spec: Specifier)
- {
+ fn shift(&mut self, token: Token, priority: usize, spec: Specifier) {
let tt = match token {
- Token::Constant(Constant::String(s))
- if self.lexer.flags.double_quotes.is_codes() => {
- let mut list = Term::Constant(Cell::default(), Constant::EmptyList);
+ Token::Constant(Constant::String(s)) if self.lexer.flags.double_quotes.is_codes() => {
+ let mut list = Term::Constant(Cell::default(), Constant::EmptyList);
- for c in s.chars().rev() {
- list = Term::Cons(
+ for c in s.chars().rev() {
+ list = Term::Cons(
+ Cell::default(),
+ Box::new(Term::Constant(
Cell::default(),
- Box::new(Term::Constant(
- Cell::default(),
- Constant::Fixnum(c as isize),
- )),
- Box::new(list),
- );
- }
-
- self.terms.push(list);
- TokenType::Term
+ Constant::Fixnum(c as isize),
+ )),
+ Box::new(list),
+ );
}
+
+ self.terms.push(list);
+ TokenType::Term
+ }
Token::Constant(c) => {
self.terms.push(Term::Constant(Cell::default(), c));
TokenType::Term
- },
+ }
Token::Var(v) => {
if v.trim() == "_" {
self.terms.push(Term::AnonVar);
}
TokenType::Term
- },
+ }
Token::Comma => TokenType::Comma,
Token::Open => TokenType::Open,
Token::Close => TokenType::Close,
if let Some(desc1) = self.stack.pop() {
if let Some(desc2) = self.stack.pop() {
if let Some(desc3) = self.stack.pop() {
- if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1)
- {
+ if is_xfx!(desc2.spec) && affirm_xfx(priority, desc2, desc3, desc1) {
self.push_binary_op(desc2, LTERM);
continue;
- }
- else if is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1)
- {
+ } else if is_yfx!(desc2.spec) && affirm_yfx(priority, desc2, desc3, desc1) {
self.push_binary_op(desc2, LTERM);
continue;
- }
- else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1)
- {
+ } else if is_xfy!(desc2.spec) && affirm_xfy(priority, desc2, desc3, desc1) {
self.push_binary_op(desc2, TERM);
continue;
} else {
}
}
- fn compute_arity_in_brackets(&self) -> Option<usize>
- {
+ fn compute_arity_in_brackets(&self) -> Option<usize> {
let mut arity = 0;
for (i, desc) in self.stack.iter().rev().enumerate() {
- if i % 2 == 0 { // expect a term or non-comma operator.
+ if i % 2 == 0 {
+ // expect a term or non-comma operator.
if let TokenType::Comma = desc.tt {
return None;
} else if is_term!(desc.spec) || is_op!(desc.spec) || is_negate!(desc.spec) {
None
}
- fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool
- {
+ fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool {
if self.stack.is_empty() {
return false;
}
let arity = match self.compute_arity_in_brackets() {
Some(arity) => arity,
- None => return false
+ None => return false,
};
if self.stack.len() > 2 * arity {
if self.atomize_term(&self.terms[idx - 1]).is_some() {
self.stack.truncate(stack_len + 1);
- let mut subterms: Vec<_> = self.terms.drain(idx ..)
- .map(|t| Box::new(t))
- .collect();
+ let mut subterms: Vec<_> = self.terms.drain(idx..).map(|t| Box::new(t)).collect();
if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) {
// reduce the '.' functor to a cons cell if it applies.
self.terms.push(Term::Cons(Cell::default(), head, tail));
} else {
let spec = get_clause_spec(name.clone(), subterms.len(), op_dir);
- self.terms.push(Term::Clause(Cell::default(), name, subterms, spec));
+ self.terms
+ .push(Term::Clause(Cell::default(), name, subterms, spec));
}
- if let Some(&mut TokenDesc { ref mut priority, ref mut spec,
- ref mut tt }) = self.stack.last_mut()
+ if let Some(&mut TokenDesc {
+ ref mut priority,
+ ref mut spec,
+ ref mut tt,
+ }) = self.stack.last_mut()
{
*tt = TokenType::Term;
*priority = 0;
}
pub fn devour_whitespace(&mut self) -> Result<(), ParserError> {
- self.lexer.scan_for_layout()?;
+ self.lexer.scan_for_layout()?;
Ok(())
}
self.stack.clear()
}
- fn expand_comma_compacted_terms(&mut self, index: usize) -> usize
- {
+ fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
if let Some(term) = self.terms.pop() {
let op_desc = self.stack[index - 1];
self.terms.extend(terms.into_iter());
return arity;
}
- _ => {
- }
+ _ => {}
}
}
0
}
- fn compute_arity_in_list(&self) -> Option<usize>
- {
+ fn compute_arity_in_list(&self) -> Option<usize> {
let mut arity = 0;
for (i, desc) in self.stack.iter().rev().enumerate() {
- if i % 2 == 0 { // expect a term or non-comma operator.
+ if i % 2 == 0 {
+ // expect a term or non-comma operator.
if let TokenType::Comma = desc.tt {
return None;
} else if is_term!(desc.spec) || is_op!(desc.spec) {
None
}
- fn reduce_list(&mut self) -> Result<bool, ParserError>
- {
+ fn reduce_list(&mut self) -> Result<bool, ParserError> {
if self.stack.is_empty() {
return Ok(false);
}
td.tt = TokenType::Term;
td.priority = 0;
- self.terms.push(Term::Constant(Cell::default(), Constant::EmptyList));
+ self.terms
+ .push(Term::Constant(Cell::default(), Constant::EmptyList));
return Ok(true);
}
}
let mut arity = match self.compute_arity_in_list() {
Some(arity) => arity,
- None => return Ok(false)
+ None => return Ok(false),
};
// we know that self.stack.len() >= 2 by this point.
let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator {
Term::Constant(Cell::default(), Constant::EmptyList)
} else {
- let term =
- match self.terms.pop() {
- Some(term) => term,
- _ => return Err(ParserError::IncompleteReduction(self.lexer.line_num,
- self.lexer.col_num))
- };
+ let term = match self.terms.pop() {
+ Some(term) => term,
+ _ => {
+ return Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ ))
+ }
+ };
if self.stack[idx].priority > 1000 {
arity += self.expand_comma_compacted_terms(idx);
let idx = self.terms.len() - arity;
- let list = self.terms.drain(idx ..)
- .rev()
- .fold(end_term, |acc, t| Term::Cons(Cell::default(),
- Box::new(t),
- Box::new(acc)));
+ let list = self.terms.drain(idx..).rev().fold(end_term, |acc, t| {
+ Term::Cons(Cell::default(), Box::new(t), Box::new(acc))
+ });
self.stack.truncate(list_len);
- self.stack.push(TokenDesc { tt: TokenType::Term, priority: 0, spec: TERM });
+ self.stack.push(TokenDesc {
+ tt: TokenType::Term,
+ priority: 0,
+ spec: TERM,
+ });
self.terms.push(list);
Ok(true)
td.priority = 0;
td.spec = TERM;
- let term = Term::Constant(Cell::default(),
- atom!("{}", self.lexer.atom_tbl));
+ let term = Term::Constant(Cell::default(), atom!("{}", self.lexer.atom_tbl));
self.terms.push(term);
return Ok(true);
}
let term = match self.terms.pop() {
Some(term) => term,
- _ => return Err(ParserError::IncompleteReduction(
- self.lexer.line_num,
- self.lexer.col_num,
- ))
+ _ => {
+ return Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ ))
+ }
};
self.terms.push(Term::Clause(
Cell::default(),
clause_name!("{}"),
vec![Box::new(term)],
- None
+ None,
));
return Ok(true);
let idx = self.stack.len() - 2;
match self.stack.remove(idx) {
- td =>
- match td.tt {
- TokenType::Open | TokenType::OpenCT => {
- if self.stack[idx].tt == TokenType::Comma {
- return false;
- }
+ td => match td.tt {
+ TokenType::Open | TokenType::OpenCT => {
+ if self.stack[idx].tt == TokenType::Comma {
+ return false;
+ }
- if let Some(atom) = sep_to_atom(self.stack[idx].tt) {
- self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, None)));
- }
+ if let Some(atom) = sep_to_atom(self.stack[idx].tt) {
+ self.terms
+ .push(Term::Constant(Cell::default(), Constant::Atom(atom, None)));
+ }
- self.stack[idx].spec = TERM;
- self.stack[idx].tt = TokenType::Term;
- self.stack[idx].priority = 0;
- true
- },
- _ => false
+ self.stack[idx].spec = TERM;
+ self.stack[idx].tt = TokenType::Term;
+ self.stack[idx].priority = 0;
+ true
}
+ _ => false,
+ },
}
}
fn shift_op(&mut self, name: ClauseName, op_dir: &CompositeOpDir) -> Result<bool, ParserError> {
- if let Some(OpDesc { pre, inf, post, spec }) = get_op_desc(name.clone(), op_dir) {
+ if let Some(OpDesc {
+ pre,
+ inf,
+ post,
+ spec,
+ }) = get_op_desc(name.clone(), op_dir)
+ {
if (pre > 0 && inf + post > 0) || is_negate!(spec) {
match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? {
// do this when layout hasn't been inserted,
spec & (XFX | XFY | YFX | YF | XF),
op_dir_val,
);
- },
+ }
_ => {
self.reduce_op(inf + post);
);
} else {
let op_dir_val = op_dir.get(name.clone(), Fixity::Pre);
- self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val);
+ self.promote_atom_op(
+ name,
+ pre,
+ spec & (FX | FY | NEGATIVE_SIGN),
+ op_dir_val,
+ );
}
} else {
let op_dir_val = op_dir.get(name.clone(), Fixity::Pre);
- self.promote_atom_op(name, pre, spec & (FX | FY | NEGATIVE_SIGN), op_dir_val);
+ self.promote_atom_op(
+ name,
+ pre,
+ spec & (FX | FY | NEGATIVE_SIGN),
+ op_dir_val,
+ );
}
}
}
}
Ok(true)
- } else { // not an operator.
+ } else {
+ // not an operator.
Ok(false)
}
}
fn atomize_term(&self, term: &Term) -> Option<ClauseName> {
match term {
&Term::Constant(_, ref c) => self.atomize_constant(c),
- _ => None
+ _ => None,
}
}
fn atomize_constant(&self, c: &Constant) -> Option<ClauseName> {
match c {
&Constant::Atom(ref name, _) => Some(name.clone()),
- &Constant::Char(c) =>
- Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
- &Constant::EmptyList =>
- Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
- _ => None
+ &Constant::Char(c) => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
+ &Constant::EmptyList => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
+ _ => None,
}
}
- fn negate_number<N, Negator, ToConstant>(
- &mut self,
- n: N,
- negator: Negator,
- constr: ToConstant
- )
- where Negator: Fn(N) -> N,
- ToConstant: Fn(N) -> Constant
+ fn negate_number<N, Negator, ToConstant>(&mut self, n: N, negator: Negator, constr: ToConstant)
+ where
+ Negator: Fn(N) -> N,
+ ToConstant: Fn(N) -> Constant,
{
if let Some(desc) = self.stack.last().cloned() {
if let Some(term) = self.terms.last().cloned() {
match term {
Term::Constant(_, Constant::Atom(ref name, _))
- if name.as_str() == "-" && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => {
- self.stack.pop();
- self.terms.pop();
+ if name.as_str() == "-"
+ && (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
+ {
+ self.stack.pop();
+ self.terms.pop();
- self.shift(Token::Constant(constr(negator(n))), 0, TERM);
- return;
- },
+ self.shift(Token::Constant(constr(negator(n))), 0, TERM);
+ return;
+ }
_ => {}
}
}
Some(t) => {
t.neg_assign();
}
- None => {
- }
+ None => {}
};
t
}
match token {
- Token::Constant(Constant::Fixnum(n)) =>
- self.negate_number(n, |n| -n, Constant::Fixnum),
- Token::Constant(Constant::Integer(n)) =>
- self.negate_number(n, negate_rc, Constant::Integer),
- Token::Constant(Constant::Rational(n)) =>
- self.negate_number(n, negate_rc, Constant::Rational),
- Token::Constant(Constant::Float(n)) =>
- self.negate_number(
- n,
- |n| OrderedFloat(-n.into_inner()),
- |n| Constant::Float(n)
- ),
- Token::Constant(c) =>
+ Token::Constant(Constant::Fixnum(n)) => self.negate_number(n, |n| -n, Constant::Fixnum),
+ Token::Constant(Constant::Integer(n)) => {
+ self.negate_number(n, negate_rc, Constant::Integer)
+ }
+ Token::Constant(Constant::Rational(n)) => {
+ self.negate_number(n, negate_rc, Constant::Rational)
+ }
+ Token::Constant(Constant::Float(n)) => {
+ self.negate_number(n, |n| OrderedFloat(-n.into_inner()), |n| Constant::Float(n))
+ }
+ Token::Constant(c) => {
if let Some(name) = self.atomize_constant(&c) {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Constant(c), 0, TERM);
}
} else {
self.shift(Token::Constant(c), 0, TERM);
- },
+ }
+ }
Token::Var(v) => self.shift(Token::Var(v), 0, TERM),
- Token::Open => self.shift(Token::Open, 1300, DELIMITER),
+ Token::Open => self.shift(Token::Open, 1300, DELIMITER),
Token::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER),
- Token::Close =>
+ Token::Close => {
if !self.reduce_term(op_dir) {
if !self.reduce_brackets() {
return Err(ParserError::IncompleteReduction(
self.lexer.col_num,
));
}
- },
- Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER),
- Token::CloseList =>
+ }
+ }
+ Token::OpenList => self.shift(Token::OpenList, 1300, DELIMITER),
+ Token::CloseList => {
if !self.reduce_list()? {
return Err(ParserError::IncompleteReduction(
self.lexer.line_num,
self.lexer.col_num,
));
- },
+ }
+ }
Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER),
- Token::CloseCurly =>
+ Token::CloseCurly => {
if !self.reduce_curly()? {
return Err(ParserError::IncompleteReduction(
self.lexer.line_num,
self.lexer.col_num,
));
- },
+ }
+ }
Token::HeadTailSeparator => {
/* '|' 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
self.reduce_op(priority);
self.shift(Token::HeadTailSeparator, priority, spec);
- },
+ }
Token::Comma => {
self.reduce_op(1000);
self.shift(Token::Comma, 1000, XFY);
- },
- Token::End =>
- match self.stack.last().map(|t| t.tt) {
- Some(TokenType::Open)
- | Some(TokenType::OpenCT)
- | Some(TokenType::OpenList)
- | Some(TokenType::OpenCurly)
- | Some(TokenType::HeadTailSeparator)
- | Some(TokenType::Comma)
- => return Err(ParserError::IncompleteReduction(self.lexer.line_num,
- self.lexer.col_num)),
- _ => {}
+ }
+ Token::End => match self.stack.last().map(|t| t.tt) {
+ Some(TokenType::Open)
+ | Some(TokenType::OpenCT)
+ | Some(TokenType::OpenList)
+ | Some(TokenType::OpenCurly)
+ | Some(TokenType::HeadTailSeparator)
+ | Some(TokenType::Comma) => {
+ return Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ ))
}
+ _ => {}
+ },
}
Ok(())
self.lexer.eof()
}
- pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result<Term, ParserError>
- {
+ pub fn read_term(&mut self, op_dir: &CompositeOpDir) -> Result<Term, ParserError> {
self.tokens = read_tokens(&mut self.lexer)?;
while let Some(token) = self.tokens.pop() {
self.reduce_op(1400);
if self.terms.len() > 1 || self.stack.len() > 1 {
- return Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num));
+ return Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ ));
}
match self.terms.pop() {
- Some(term) => if self.terms.is_empty() {
- Ok(term)
- } else {
- Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num))
- },
- _ => Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num))
+ Some(term) => {
+ if self.terms.is_empty() {
+ Ok(term)
+ } else {
+ Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ ))
+ }
+ }
+ _ => Err(ParserError::IncompleteReduction(
+ self.lexer.line_num,
+ self.lexer.col_num,
+ )),
}
}
- pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result<Vec<Term>, ParserError>
- {
+ pub fn read(&mut self, op_dir: &CompositeOpDir) -> Result<Vec<Term>, ParserError> {
let mut terms = Vec::new();
loop {