change prolog_parse_rebis to use 2018 edition rust
so all crates use the same edition
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
name = "prolog_parser_rebis"
|
name = "prolog_parser_rebis"
|
||||||
version = "0.8.68"
|
version = "0.8.68"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
repository = "https://github.com/mthom/prolog_parser"
|
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."
|
description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation."
|
||||||
license = "BSD-3-Clause"
|
license = "BSD-3-Clause"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use rug::{Integer, Rational};
|
use crate::tabled_rc::*;
|
||||||
use ordered_float::*;
|
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::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -27,112 +27,140 @@ pub const MAX_ARITY: usize = 1023;
|
|||||||
pub const XFX: u32 = 0x0001;
|
pub const XFX: u32 = 0x0001;
|
||||||
pub const XFY: u32 = 0x0002;
|
pub const XFY: u32 = 0x0002;
|
||||||
pub const YFX: u32 = 0x0004;
|
pub const YFX: u32 = 0x0004;
|
||||||
pub const XF: u32 = 0x0010;
|
pub const XF: u32 = 0x0010;
|
||||||
pub const YF: u32 = 0x0020;
|
pub const YF: u32 = 0x0020;
|
||||||
pub const FX: u32 = 0x0040;
|
pub const FX: u32 = 0x0040;
|
||||||
pub const FY: u32 = 0x0080;
|
pub const FY: u32 = 0x0080;
|
||||||
pub const DELIMITER: u32 = 0x0100;
|
pub const DELIMITER: u32 = 0x0100;
|
||||||
pub const TERM: u32 = 0x1000;
|
pub const TERM: u32 = 0x1000;
|
||||||
pub const LTERM: u32 = 0x3000;
|
pub const LTERM: u32 = 0x3000;
|
||||||
|
|
||||||
pub const NEGATIVE_SIGN: u32 = 0x0200;
|
pub const NEGATIVE_SIGN: u32 = 0x0200;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! clause_name {
|
macro_rules! clause_name {
|
||||||
($name: expr, $tbl: expr) => (
|
($name: expr, $tbl: expr) => {
|
||||||
ClauseName::User(TabledRc::new($name, $tbl.clone()))
|
ClauseName::User(TabledRc::new($name, $tbl.clone()))
|
||||||
) ;
|
};
|
||||||
($name: expr) => (
|
($name: expr) => {
|
||||||
ClauseName::BuiltIn($name)
|
ClauseName::BuiltIn($name)
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! atom {
|
macro_rules! atom {
|
||||||
($e:expr, $tbl:expr) => (
|
($e:expr, $tbl:expr) => {
|
||||||
Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None)
|
Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)), None)
|
||||||
);
|
};
|
||||||
($e:expr) => (
|
($e:expr) => {
|
||||||
Constant::Atom(clause_name!($e), None)
|
Constant::Atom(clause_name!($e), None)
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! rc_atom {
|
macro_rules! rc_atom {
|
||||||
($e:expr) => (
|
($e:expr) => {
|
||||||
Rc::new(String::from($e))
|
Rc::new(String::from($e))
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
macro_rules! is_term {
|
macro_rules! is_term {
|
||||||
($x:expr) => ( ($x & TERM) != 0 )
|
($x:expr) => {
|
||||||
|
($x & TERM) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_lterm {
|
macro_rules! is_lterm {
|
||||||
($x:expr) => ( ($x & LTERM) != 0 )
|
($x:expr) => {
|
||||||
|
($x & LTERM) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! is_op {
|
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 {
|
macro_rules! is_negate {
|
||||||
($x:expr) => ( ($x & NEGATIVE_SIGN) != 0 )
|
($x:expr) => {
|
||||||
|
($x & NEGATIVE_SIGN) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_prefix {
|
macro_rules! is_prefix {
|
||||||
($x:expr) => ( $x & (FX | FY) != 0 )
|
($x:expr) => {
|
||||||
|
$x & (FX | FY) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_postfix {
|
macro_rules! is_postfix {
|
||||||
($x:expr) => ( $x & (XF | YF) != 0 )
|
($x:expr) => {
|
||||||
|
$x & (XF | YF) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_infix {
|
macro_rules! is_infix {
|
||||||
($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
|
($x:expr) => {
|
||||||
|
($x & (XFX | XFY | YFX)) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_xfx {
|
macro_rules! is_xfx {
|
||||||
($x:expr) => ( ($x & XFX) != 0 )
|
($x:expr) => {
|
||||||
|
($x & XFX) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_xfy {
|
macro_rules! is_xfy {
|
||||||
($x:expr) => ( ($x & XFY) != 0 )
|
($x:expr) => {
|
||||||
|
($x & XFY) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_yfx {
|
macro_rules! is_yfx {
|
||||||
($x:expr) => ( ($x & YFX) != 0 )
|
($x:expr) => {
|
||||||
|
($x & YFX) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_yf {
|
macro_rules! is_yf {
|
||||||
($x:expr) => ( ($x & YF) != 0 )
|
($x:expr) => {
|
||||||
|
($x & YF) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_xf {
|
macro_rules! is_xf {
|
||||||
($x:expr) => ( ($x & XF) != 0 )
|
($x:expr) => {
|
||||||
|
($x & XF) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_fx {
|
macro_rules! is_fx {
|
||||||
($x:expr) => ( ($x & FX) != 0 )
|
($x:expr) => {
|
||||||
|
($x & FX) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! is_fy {
|
macro_rules! is_fy {
|
||||||
($x:expr) => ( ($x & FY) != 0 )
|
($x:expr) => {
|
||||||
|
($x & FY) != 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum RegType {
|
pub enum RegType {
|
||||||
Perm(usize),
|
Perm(usize),
|
||||||
Temp(usize)
|
Temp(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RegType {
|
impl Default for RegType {
|
||||||
@@ -144,14 +172,14 @@ impl Default for RegType {
|
|||||||
impl RegType {
|
impl RegType {
|
||||||
pub fn reg_num(self) -> usize {
|
pub fn reg_num(self) -> usize {
|
||||||
match self {
|
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 {
|
pub fn is_perm(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
RegType::Perm(_) => true,
|
RegType::Perm(_) => true,
|
||||||
_ => false
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +188,7 @@ impl fmt::Display for RegType {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&RegType::Perm(val) => write!(f, "Y{}", val),
|
&RegType::Perm(val) => write!(f, "Y{}", val),
|
||||||
&RegType::Temp(val) => write!(f, "X{}", val)
|
&RegType::Temp(val) => write!(f, "X{}", val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,13 +196,13 @@ impl fmt::Display for RegType {
|
|||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum VarReg {
|
pub enum VarReg {
|
||||||
ArgAndNorm(RegType, usize),
|
ArgAndNorm(RegType, usize),
|
||||||
Norm(RegType)
|
Norm(RegType),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VarReg {
|
impl VarReg {
|
||||||
pub fn norm(self) -> RegType {
|
pub fn norm(self) -> RegType {
|
||||||
match self {
|
match self {
|
||||||
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
|
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,10 +212,8 @@ impl fmt::Display for VarReg {
|
|||||||
match self {
|
match self {
|
||||||
&VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
|
&VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
|
||||||
&VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
|
&VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
|
||||||
&VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
|
&VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg),
|
||||||
write!(f, "Y{} A{}", reg, arg),
|
&VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg),
|
||||||
&VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
|
|
||||||
write!(f, "X{} A{}", reg, arg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,28 +226,30 @@ impl Default for VarReg {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! temp_v {
|
macro_rules! temp_v {
|
||||||
($x:expr) => (
|
($x:expr) => {
|
||||||
RegType::Temp($x)
|
RegType::Temp($x)
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! perm_v {
|
macro_rules! perm_v {
|
||||||
($x:expr) => (
|
($x:expr) => {
|
||||||
RegType::Perm($x)
|
RegType::Perm($x)
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum GenContext {
|
pub enum GenContext {
|
||||||
Head, Mid(usize), Last(usize) // Mid & Last: chunk_num
|
Head,
|
||||||
|
Mid(usize),
|
||||||
|
Last(usize), // Mid & Last: chunk_num
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenContext {
|
impl GenContext {
|
||||||
pub fn chunk_num(self) -> usize {
|
pub fn chunk_num(self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
GenContext::Head => 0,
|
GenContext::Head => 0,
|
||||||
GenContext::Mid(cn) | GenContext::Last(cn) => cn
|
GenContext::Mid(cn) | GenContext::Last(cn) => cn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,18 +275,22 @@ pub type OpDir = HashMap<OpDirKey, OpDirValue>;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct MachineFlags {
|
pub struct MachineFlags {
|
||||||
pub double_quotes: DoubleQuotes
|
pub double_quotes: DoubleQuotes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MachineFlags {
|
impl Default for MachineFlags {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MachineFlags { double_quotes: DoubleQuotes::default() }
|
MachineFlags {
|
||||||
|
double_quotes: DoubleQuotes::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum DoubleQuotes {
|
pub enum DoubleQuotes {
|
||||||
Atom, Chars, Codes
|
Atom,
|
||||||
|
Chars,
|
||||||
|
Codes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DoubleQuotes {
|
impl DoubleQuotes {
|
||||||
@@ -296,10 +328,10 @@ impl Default for DoubleQuotes {
|
|||||||
pub fn default_op_dir() -> OpDir {
|
pub fn default_op_dir() -> OpDir {
|
||||||
let mut op_dir = OpDir::new();
|
let mut op_dir = OpDir::new();
|
||||||
|
|
||||||
op_dir.insert((clause_name!(":-"), Fixity::In), OpDirValue::new(XFX, 1200));
|
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::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(XFY, 1000));
|
||||||
|
|
||||||
op_dir
|
op_dir
|
||||||
}
|
}
|
||||||
@@ -307,7 +339,7 @@ pub fn default_op_dir() -> OpDir {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ArithmeticError {
|
pub enum ArithmeticError {
|
||||||
NonEvaluableFunctor(Constant, usize),
|
NonEvaluableFunctor(Constant, usize),
|
||||||
UninstantiatedVar
|
UninstantiatedVar,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -321,47 +353,35 @@ pub enum ParserError {
|
|||||||
MissingQuote(usize, usize),
|
MissingQuote(usize, usize),
|
||||||
NonPrologChar(usize, usize),
|
NonPrologChar(usize, usize),
|
||||||
ParseBigInt(usize, usize),
|
ParseBigInt(usize, usize),
|
||||||
Utf8Error(usize, usize)
|
Utf8Error(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserError {
|
impl ParserError {
|
||||||
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
|
pub fn line_and_col_num(&self) -> Option<(usize, usize)> {
|
||||||
match self {
|
match self {
|
||||||
&ParserError::BackQuotedString(line_num, col_num)
|
&ParserError::BackQuotedString(line_num, col_num)
|
||||||
| &ParserError::UnexpectedChar(_, line_num, col_num)
|
| &ParserError::UnexpectedChar(_, line_num, col_num)
|
||||||
| &ParserError::IncompleteReduction(line_num, col_num)
|
| &ParserError::IncompleteReduction(line_num, col_num)
|
||||||
| &ParserError::MissingQuote(line_num, col_num)
|
| &ParserError::MissingQuote(line_num, col_num)
|
||||||
| &ParserError::NonPrologChar(line_num, col_num)
|
| &ParserError::NonPrologChar(line_num, col_num)
|
||||||
| &ParserError::ParseBigInt(line_num, col_num)
|
| &ParserError::ParseBigInt(line_num, col_num)
|
||||||
| &ParserError::Utf8Error(line_num, col_num) =>
|
| &ParserError::Utf8Error(line_num, col_num) => Some((line_num, col_num)),
|
||||||
Some((line_num, col_num)),
|
_ => None,
|
||||||
_ =>
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
&ParserError::BackQuotedString(..) =>
|
&ParserError::BackQuotedString(..) => "back_quoted_string",
|
||||||
"back_quoted_string",
|
&ParserError::UnexpectedChar(..) => "unexpected_char",
|
||||||
&ParserError::UnexpectedChar(..) =>
|
&ParserError::UnexpectedEOF => "unexpected_end_of_file",
|
||||||
"unexpected_char",
|
&ParserError::IncompleteReduction(..) => "incomplete_reduction",
|
||||||
&ParserError::UnexpectedEOF =>
|
&ParserError::InvalidSingleQuotedCharacter(..) => "invalid_single_quoted_character",
|
||||||
"unexpected_end_of_file",
|
&ParserError::IO(_) => "input_output_error",
|
||||||
&ParserError::IncompleteReduction(..) =>
|
&ParserError::MissingQuote(..) => "missing_quote",
|
||||||
"incomplete_reduction",
|
&ParserError::NonPrologChar(..) => "non_prolog_character",
|
||||||
&ParserError::InvalidSingleQuotedCharacter(..) =>
|
&ParserError::ParseBigInt(..) => "cannot_parse_big_int",
|
||||||
"invalid_single_quoted_character",
|
&ParserError::Utf8Error(..) => "utf8_conversion_error",
|
||||||
&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",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -382,39 +402,38 @@ impl From<&IOError> for ParserError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct CompositeOpDir<'a, 'b> {
|
pub struct CompositeOpDir<'a, 'b> {
|
||||||
pub primary_op_dir: Option<&'b OpDir>,
|
pub primary_op_dir: Option<&'b OpDir>,
|
||||||
pub secondary_op_dir: &'a OpDir,
|
pub secondary_op_dir: &'a OpDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> CompositeOpDir<'a, 'b>
|
impl<'a, 'b> CompositeOpDir<'a, 'b> {
|
||||||
{
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(secondary_op_dir: &'a OpDir, primary_op_dir: Option<&'b OpDir>) -> Self {
|
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]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate) fn get(&self, name: ClauseName, fixity: Fixity) -> Option<&OpDirValue> {
|
||||||
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))
|
||||||
let entry =
|
} else {
|
||||||
if let Some(ref primary_op_dir) = &self.primary_op_dir {
|
None
|
||||||
primary_op_dir.get(&(name.clone(), fixity))
|
};
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
entry.or_else(move || self.secondary_op_dir.get(&(name, fixity)))
|
entry.or_else(move || self.secondary_op_dir.get(&(name, fixity)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Fixity {
|
pub enum Fixity {
|
||||||
In, Post, Pre
|
In,
|
||||||
|
Post,
|
||||||
|
Pre,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
@@ -496,28 +515,21 @@ pub enum Constant {
|
|||||||
impl fmt::Display for Constant {
|
impl fmt::Display for Constant {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&Constant::Atom(ref atom, _) =>
|
&Constant::Atom(ref atom, _) => {
|
||||||
if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
|
if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
|
||||||
write!(f, "'{}'", atom.as_str())
|
write!(f, "'{}'", atom.as_str())
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}", atom.as_str())
|
write!(f, "{}", atom.as_str())
|
||||||
},
|
}
|
||||||
&Constant::Char(c) =>
|
}
|
||||||
write!(f, "'{}'", c as u32),
|
&Constant::Char(c) => write!(f, "'{}'", c as u32),
|
||||||
&Constant::EmptyList =>
|
&Constant::EmptyList => write!(f, "[]"),
|
||||||
write!(f, "[]"),
|
&Constant::Fixnum(n) => write!(f, "{}", n),
|
||||||
&Constant::Fixnum(n) =>
|
&Constant::Integer(ref n) => write!(f, "{}", n),
|
||||||
write!(f, "{}", n),
|
&Constant::Rational(ref n) => write!(f, "{}", n),
|
||||||
&Constant::Integer(ref n) =>
|
&Constant::Float(ref n) => write!(f, "{}", n),
|
||||||
write!(f, "{}", n),
|
&Constant::String(ref s) => write!(f, "\"{}\"", &s),
|
||||||
&Constant::Rational(ref n) =>
|
&Constant::Usize(integer) => write!(f, "u{}", integer),
|
||||||
write!(f, "{}", n),
|
|
||||||
&Constant::Float(ref n) =>
|
|
||||||
write!(f, "{}", n),
|
|
||||||
&Constant::String(ref s) =>
|
|
||||||
write!(f, "\"{}\"", &s),
|
|
||||||
&Constant::Usize(integer) =>
|
|
||||||
write!(f, "u{}", integer),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -526,37 +538,27 @@ impl PartialEq for Constant {
|
|||||||
fn eq(&self, other: &Constant) -> bool {
|
fn eq(&self, other: &Constant) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&Constant::Atom(ref atom, _), &Constant::Char(c))
|
(&Constant::Atom(ref atom, _), &Constant::Char(c))
|
||||||
| (&Constant::Char(c), &Constant::Atom(ref atom, _)) => {
|
| (&Constant::Char(c), &Constant::Atom(ref atom, _)) => {
|
||||||
atom.is_char() && Some(c) == atom.as_str().chars().next()
|
atom.is_char() && Some(c) == atom.as_str().chars().next()
|
||||||
},
|
}
|
||||||
(&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) =>
|
(&Constant::Atom(ref a1, _), &Constant::Atom(ref a2, _)) => a1.as_str() == a2.as_str(),
|
||||||
a1.as_str() == a2.as_str(),
|
(&Constant::Char(c1), &Constant::Char(c2)) => c1 == c2,
|
||||||
(&Constant::Char(c1), &Constant::Char(c2)) =>
|
(&Constant::Fixnum(n1), &Constant::Fixnum(n2)) => n1 == n2,
|
||||||
c1 == c2,
|
(&Constant::Fixnum(n1), &Constant::Integer(ref n2))
|
||||||
(&Constant::Fixnum(n1), &Constant::Fixnum(n2)) =>
|
| (&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => {
|
||||||
n1 == n2,
|
|
||||||
(&Constant::Fixnum(n1), &Constant::Integer(ref n2)) |
|
|
||||||
(&Constant::Integer(ref n2), &Constant::Fixnum(n1)) => {
|
|
||||||
if let Some(n2) = n2.to_isize() {
|
if let Some(n2) = n2.to_isize() {
|
||||||
n1 == n2
|
n1 == n2
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&Constant::Integer(ref n1), &Constant::Integer(ref n2)) =>
|
(&Constant::Integer(ref n1), &Constant::Integer(ref n2)) => n1 == n2,
|
||||||
n1 == n2,
|
(&Constant::Rational(ref n1), &Constant::Rational(ref n2)) => n1 == n2,
|
||||||
(&Constant::Rational(ref n1), &Constant::Rational(ref n2)) =>
|
(&Constant::Float(ref n1), &Constant::Float(ref n2)) => n1 == n2,
|
||||||
n1 == n2,
|
(&Constant::String(ref s1), &Constant::String(ref s2)) => &s1 == &s2,
|
||||||
(&Constant::Float(ref n1), &Constant::Float(ref n2)) =>
|
(&Constant::EmptyList, &Constant::EmptyList) => true,
|
||||||
n1 == n2,
|
(&Constant::Usize(u1), &Constant::Usize(u2)) => u1 == u2,
|
||||||
(&Constant::String(ref s1), &Constant::String(ref s2)) => {
|
_ => false,
|
||||||
&s1 == &s2
|
|
||||||
}
|
|
||||||
(&Constant::EmptyList, &Constant::EmptyList) =>
|
|
||||||
true,
|
|
||||||
(&Constant::Usize(u1), &Constant::Usize(u2)) =>
|
|
||||||
u1 == u2,
|
|
||||||
_ => false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -567,7 +569,7 @@ impl Constant {
|
|||||||
pub fn to_atom(self) -> Option<ClauseName> {
|
pub fn to_atom(self) -> Option<ClauseName> {
|
||||||
match self {
|
match self {
|
||||||
Constant::Atom(a, _) => Some(a.defrock_brackets()),
|
Constant::Atom(a, _) => Some(a.defrock_brackets()),
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,7 +577,7 @@ impl Constant {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ClauseName {
|
pub enum ClauseName {
|
||||||
BuiltIn(&'static str),
|
BuiltIn(&'static str),
|
||||||
User(TabledRc<Atom>)
|
User(TabledRc<Atom>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ClauseName {
|
impl fmt::Display for ClauseName {
|
||||||
@@ -622,10 +624,12 @@ impl ClauseName {
|
|||||||
match self {
|
match self {
|
||||||
&ClauseName::User(ref name) => {
|
&ClauseName::User(ref name) => {
|
||||||
let module = name.owning_module();
|
let module = name.owning_module();
|
||||||
ClauseName::User(TabledRc { atom: module.clone(),
|
ClauseName::User(TabledRc {
|
||||||
table: TabledData::new(module) })
|
atom: module.clone(),
|
||||||
},
|
table: TabledData::new(module),
|
||||||
_ => clause_name!("user")
|
})
|
||||||
|
}
|
||||||
|
_ => clause_name!("user"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +637,7 @@ impl ClauseName {
|
|||||||
pub fn to_rc(&self) -> Rc<String> {
|
pub fn to_rc(&self) -> Rc<String> {
|
||||||
match self {
|
match self {
|
||||||
&ClauseName::BuiltIn(s) => Rc::new(s.to_string()),
|
&ClauseName::BuiltIn(s) => Rc::new(s.to_string()),
|
||||||
&ClauseName::User(ref rc) => rc.inner()
|
&ClauseName::User(ref rc) => rc.inner(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,9 +670,7 @@ impl ClauseName {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClauseName::User(ref name) => {
|
ClauseName::User(ref name) => other.has_table(&name.table),
|
||||||
other.has_table(&name.table)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +678,7 @@ impl ClauseName {
|
|||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
&ClauseName::BuiltIn(s) => s,
|
&ClauseName::BuiltIn(s) => s,
|
||||||
&ClauseName::User(ref name) => name.as_ref()
|
&ClauseName::User(ref name) => name.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,17 +690,17 @@ impl ClauseName {
|
|||||||
pub fn defrock_brackets(self) -> Self {
|
pub fn defrock_brackets(self) -> Self {
|
||||||
fn defrock_brackets(s: &str) -> &str {
|
fn defrock_brackets(s: &str) -> &str {
|
||||||
if s.starts_with('(') && s.ends_with(')') {
|
if s.starts_with('(') && s.ends_with(')') {
|
||||||
&s[1 .. s.len() - 1]
|
&s[1..s.len() - 1]
|
||||||
} else {
|
} else {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ClauseName::BuiltIn(s) =>
|
ClauseName::BuiltIn(s) => ClauseName::BuiltIn(defrock_brackets(s)),
|
||||||
ClauseName::BuiltIn(defrock_brackets(s)),
|
ClauseName::User(s) => {
|
||||||
ClauseName::User(s) =>
|
|
||||||
ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table))
|
ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,10 +715,15 @@ impl AsRef<str> for ClauseName {
|
|||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Term {
|
pub enum Term {
|
||||||
AnonVar,
|
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>),
|
Cons(Cell<RegType>, Box<Term>, Box<Term>),
|
||||||
Constant(Cell<RegType>, Constant),
|
Constant(Cell<RegType>, Constant),
|
||||||
Var(Cell<VarReg>, Rc<Var>)
|
Var(Cell<VarReg>, Rc<Var>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Term {
|
impl Term {
|
||||||
@@ -724,30 +731,29 @@ impl Term {
|
|||||||
match self {
|
match self {
|
||||||
&Term::Clause(_, _, _, ref spec) => spec.clone(),
|
&Term::Clause(_, _, _, ref spec) => spec.clone(),
|
||||||
&Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(),
|
&Term::Constant(_, Constant::Atom(_, ref spec)) => spec.clone(),
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_constant(self) -> Option<Constant> {
|
pub fn to_constant(self) -> Option<Constant> {
|
||||||
match self {
|
match self {
|
||||||
Term::Constant(_, c) => Some(c),
|
Term::Constant(_, c) => Some(c),
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_arg(&self) -> Option<&Term> {
|
pub fn first_arg(&self) -> Option<&Term> {
|
||||||
match self {
|
match self {
|
||||||
&Term::Clause(_, _, ref terms, _) =>
|
&Term::Clause(_, _, ref terms, _) => terms.first().map(|bt| bt.as_ref()),
|
||||||
terms.first().map(|bt| bt.as_ref()),
|
_ => None,
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_name(&mut self, new_name: ClauseName) {
|
pub fn set_name(&mut self, new_name: ClauseName) {
|
||||||
match self {
|
match self {
|
||||||
Term::Constant(_, Constant::Atom(ref mut atom, _))
|
Term::Constant(_, Constant::Atom(ref mut atom, _))
|
||||||
| Term::Clause(_, ref mut atom, ..) => {
|
| Term::Clause(_, ref mut atom, ..) => {
|
||||||
*atom = new_name;
|
*atom = new_name;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -755,16 +761,17 @@ impl Term {
|
|||||||
|
|
||||||
pub fn name(&self) -> Option<ClauseName> {
|
pub fn name(&self) -> Option<ClauseName> {
|
||||||
match self {
|
match self {
|
||||||
&Term::Constant(_, Constant::Atom(ref atom, _))
|
&Term::Constant(_, Constant::Atom(ref atom, _)) | &Term::Clause(_, ref atom, ..) => {
|
||||||
| &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
|
Some(atom.clone())
|
||||||
_ => None
|
}
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&Term::Clause(_, _, ref child_terms, ..) => child_terms.len(),
|
&Term::Clause(_, _, ref child_terms, ..) => child_terms.len(),
|
||||||
_ => 0
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::lexical::parse_lossy;
|
|
||||||
use crate::ordered_float::*;
|
|
||||||
use crate::rug::Integer;
|
use crate::rug::Integer;
|
||||||
|
use lexical::parse_lossy;
|
||||||
|
use ordered_float::*;
|
||||||
|
|
||||||
use ast::*;
|
use crate::ast::*;
|
||||||
use tabled_rc::*;
|
use crate::tabled_rc::*;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -11,13 +11,13 @@ use std::io::Read;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
macro_rules! is_not_eof {
|
macro_rules! is_not_eof {
|
||||||
($c:expr) => (
|
($c:expr) => {
|
||||||
match $c {
|
match $c {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(ParserError::UnexpectedEOF) => return Ok(true),
|
Err(ParserError::UnexpectedEOF) => return Ok(true),
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! consume_chars_with {
|
macro_rules! consume_chars_with {
|
||||||
@@ -27,26 +27,26 @@ macro_rules! consume_chars_with {
|
|||||||
Ok(Some(c)) => $token.push(c),
|
Ok(Some(c)) => $token.push(c),
|
||||||
Ok(None) => continue,
|
Ok(None) => continue,
|
||||||
Err(ParserError::UnexpectedChar(..)) => break,
|
Err(ParserError::UnexpectedChar(..)) => break,
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Constant(Constant),
|
Constant(Constant),
|
||||||
Var(Rc<Atom>),
|
Var(Rc<Atom>),
|
||||||
Open, // '('
|
Open, // '('
|
||||||
OpenCT, // '('
|
OpenCT, // '('
|
||||||
Close, // ')'
|
Close, // ')'
|
||||||
OpenList, // '['
|
OpenList, // '['
|
||||||
CloseList, // ']'
|
CloseList, // ']'
|
||||||
OpenCurly, // '{'
|
OpenCurly, // '{'
|
||||||
CloseCurly, // '}'
|
CloseCurly, // '}'
|
||||||
HeadTailSeparator, // '|'
|
HeadTailSeparator, // '|'
|
||||||
Comma, // ','
|
Comma, // ','
|
||||||
End
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Lexer<'a, R: Read> {
|
pub struct Lexer<'a, R: Read> {
|
||||||
@@ -54,17 +54,17 @@ pub struct Lexer<'a, R: Read> {
|
|||||||
pub(crate) reader: &'a mut ParsingStream<R>,
|
pub(crate) reader: &'a mut ParsingStream<R>,
|
||||||
pub(crate) flags: MachineFlags,
|
pub(crate) flags: MachineFlags,
|
||||||
pub(crate) line_num: usize,
|
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> {
|
impl<'a, R: Read + fmt::Debug> fmt::Debug for Lexer<'a, R> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("Lexer")
|
f.debug_struct("Lexer")
|
||||||
.field("atom_tbl", &self.atom_tbl)
|
.field("atom_tbl", &self.atom_tbl)
|
||||||
.field("reader", &"&'a mut ParsingStream<R>") // Hacky solution.
|
.field("reader", &"&'a mut ParsingStream<R>") // Hacky solution.
|
||||||
.field("line_num", &self.line_num)
|
.field("line_num", &self.line_num)
|
||||||
.field("col_num", &self.col_num)
|
.field("col_num", &self.col_num)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,13 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
src: &'a mut ParsingStream<R>,
|
src: &'a mut ParsingStream<R>,
|
||||||
) -> Self {
|
) -> 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 return_char(&mut self, c: char) {
|
||||||
@@ -128,8 +134,7 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn single_line_comment(&mut self) -> Result<(), ParserError>
|
fn single_line_comment(&mut self) -> Result<(), ParserError> {
|
||||||
{
|
|
||||||
loop {
|
loop {
|
||||||
if self.reader.peek().is_none() || new_line_char!(self.skip_char()?) {
|
if self.reader.peek().is_none() || new_line_char!(self.skip_char()?) {
|
||||||
break;
|
break;
|
||||||
@@ -229,8 +234,7 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()?) {
|
if backslash_char!(self.lookahead_char()?) {
|
||||||
let c = self.skip_char()?;
|
let c = self.skip_char()?;
|
||||||
|
|
||||||
@@ -264,14 +268,13 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()?) {
|
if backslash_char!(self.lookahead_char()?) {
|
||||||
let c = self.skip_char()?;
|
let c = self.skip_char()?;
|
||||||
|
|
||||||
if new_line_char!(self.lookahead_char()?) {
|
if new_line_char!(self.lookahead_char()?) {
|
||||||
self.skip_char()?;
|
self.skip_char()?;
|
||||||
return Ok(None)
|
return Ok(None);
|
||||||
} else {
|
} else {
|
||||||
self.return_char(c);
|
self.return_char(c);
|
||||||
}
|
}
|
||||||
@@ -299,8 +302,7 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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()? {
|
let escaped = match self.lookahead_char()? {
|
||||||
'a' => '\u{07}', // UTF-8 alert
|
'a' => '\u{07}', // UTF-8 alert
|
||||||
'b' => '\u{08}', // UTF-8 backspace
|
'b' => '\u{08}', // UTF-8 backspace
|
||||||
@@ -309,20 +311,18 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
't' => '\t',
|
't' => '\t',
|
||||||
'n' => '\n',
|
'n' => '\n',
|
||||||
'r' => '\r',
|
'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()?;
|
self.skip_char()?;
|
||||||
return Ok(escaped);
|
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)
|
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()?;
|
self.skip_char()?;
|
||||||
let c = self.lookahead_char()?;
|
let c = self.lookahead_char()?;
|
||||||
|
|
||||||
@@ -354,12 +354,13 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
|
|
||||||
if backslash_char!(c) {
|
if backslash_char!(c) {
|
||||||
self.skip_char()?;
|
self.skip_char()?;
|
||||||
u32::from_str_radix(&token, radix)
|
u32::from_str_radix(&token, radix).map_or_else(
|
||||||
.map_or_else(
|
|_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
|
||||||
|_| Err(ParserError::ParseBigInt(self.line_num, self.col_num)),
|
|n| {
|
||||||
|n| char::try_from(n)
|
char::try_from(n)
|
||||||
.map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num))
|
.map_err(|_| ParserError::Utf8Error(self.line_num, self.col_num))
|
||||||
)
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// on failure, restore the token characters and backslash.
|
// on failure, restore the token characters and backslash.
|
||||||
self.reader.put_back_all(token.chars().map(Ok));
|
self.reader.put_back_all(token.chars().map(Ok));
|
||||||
@@ -423,11 +424,8 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
Integer::from_str_radix(&token, 16)
|
Integer::from_str_radix(&token, 16)
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.line_num,
|
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.return_char('x');
|
self.return_char('x');
|
||||||
@@ -449,11 +447,8 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
Integer::from_str_radix(&token, 8)
|
Integer::from_str_radix(&token, 8)
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.line_num,
|
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.return_char('o');
|
self.return_char('o');
|
||||||
@@ -475,11 +470,8 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
Integer::from_str_radix(&token, 2)
|
Integer::from_str_radix(&token, 2)
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.line_num,
|
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.return_char('b');
|
self.return_char('b');
|
||||||
@@ -531,12 +523,14 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ParserError::InvalidSingleQuotedCharacter(self.lookahead_char()?))
|
return Err(ParserError::InvalidSingleQuotedCharacter(
|
||||||
|
self.lookahead_char()?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self.get_back_quoted_string() {
|
match self.get_back_quoted_string() {
|
||||||
Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
|
Ok(_) => return Err(ParserError::BackQuotedString(self.line_num, self.col_num)),
|
||||||
Err(e) => return Err(e)
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,12 +569,10 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
isize::from_str_radix(&token, 10)
|
isize::from_str_radix(&token, 10)
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
token.parse::<Integer>()
|
token
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.parse::<Integer>()
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
self.line_num,
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
} else if decimal_digit_char!(self.lookahead_char()?) {
|
} else if decimal_digit_char!(self.lookahead_char()?) {
|
||||||
token.push('.');
|
token.push('.');
|
||||||
@@ -599,7 +591,7 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
|
|
||||||
let c = match self.lookahead_char() {
|
let c = match self.lookahead_char() {
|
||||||
Err(_) => return Ok(self.vacate_with_float(token)),
|
Err(_) => return Ok(self.vacate_with_float(token)),
|
||||||
Ok(c) => c
|
Ok(c) => c,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !sign_char!(c) && !decimal_digit_char!(c) {
|
if !sign_char!(c) && !decimal_digit_char!(c) {
|
||||||
@@ -613,8 +605,8 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.return_char(token.pop().unwrap());
|
self.return_char(token.pop().unwrap());
|
||||||
return Ok(self.vacate_with_float(token));
|
return Ok(self.vacate_with_float(token));
|
||||||
},
|
}
|
||||||
Ok(c) => c
|
Ok(c) => c,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !decimal_digit_char!(c) {
|
if !decimal_digit_char!(c) {
|
||||||
@@ -645,70 +637,65 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
isize::from_str_radix(&token, 10)
|
isize::from_str_radix(&token, 10)
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
token.parse::<Integer>()
|
token
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.parse::<Integer>()
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
self.line_num,
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if token.starts_with('0') && token.len() == 1 {
|
if token.starts_with('0') && token.len() == 1 {
|
||||||
if c == 'x' {
|
if c == 'x' {
|
||||||
self.hexadecimal_constant()
|
self.hexadecimal_constant().or_else(|e| {
|
||||||
.or_else(|e| {
|
if let ParserError::ParseBigInt(..) = e {
|
||||||
if let ParserError::ParseBigInt(..) = e {
|
isize::from_str_radix(&token, 10)
|
||||||
isize::from_str_radix(&token, 10)
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.or_else(|_| {
|
||||||
.or_else(|_| {
|
token
|
||||||
token.parse::<Integer>()
|
.parse::<Integer>()
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| {
|
||||||
self.line_num,
|
ParserError::ParseBigInt(self.line_num, self.col_num)
|
||||||
self.col_num,
|
})
|
||||||
))
|
})
|
||||||
})
|
} else {
|
||||||
} else {
|
Err(e)
|
||||||
Err(e)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
} else if c == 'o' {
|
} else if c == 'o' {
|
||||||
self.octal_constant()
|
self.octal_constant().or_else(|e| {
|
||||||
.or_else(|e| {
|
if let ParserError::ParseBigInt(..) = e {
|
||||||
if let ParserError::ParseBigInt(..) = e {
|
isize::from_str_radix(&token, 10)
|
||||||
isize::from_str_radix(&token, 10)
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.or_else(|_| {
|
||||||
.or_else(|_| {
|
token
|
||||||
token.parse::<Integer>()
|
.parse::<Integer>()
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| {
|
||||||
self.line_num,
|
ParserError::ParseBigInt(self.line_num, self.col_num)
|
||||||
self.col_num,
|
})
|
||||||
))
|
})
|
||||||
})
|
} else {
|
||||||
} else {
|
Err(e)
|
||||||
Err(e)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
} else if c == 'b' {
|
} else if c == 'b' {
|
||||||
self.binary_constant()
|
self.binary_constant().or_else(|e| {
|
||||||
.or_else(|e| {
|
if let ParserError::ParseBigInt(..) = e {
|
||||||
if let ParserError::ParseBigInt(..) = e {
|
isize::from_str_radix(&token, 10)
|
||||||
isize::from_str_radix(&token, 10)
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.or_else(|_| {
|
||||||
.or_else(|_| {
|
token
|
||||||
token.parse::<Integer>()
|
.parse::<Integer>()
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map_err(|_| {
|
||||||
self.line_num,
|
ParserError::ParseBigInt(self.line_num, self.col_num)
|
||||||
self.col_num,
|
})
|
||||||
))
|
})
|
||||||
})
|
} else {
|
||||||
} else {
|
Err(e)
|
||||||
Err(e)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
} else if single_quote_char!(c) {
|
} else if single_quote_char!(c) {
|
||||||
self.skip_char()?;
|
self.skip_char()?;
|
||||||
|
|
||||||
@@ -726,45 +713,39 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.get_single_quoted_char()
|
self.get_single_quoted_char()
|
||||||
.and_then(|c| {
|
.and_then(|c| Ok(Token::Constant(Constant::Fixnum(c as isize))))
|
||||||
Ok(Token::Constant(Constant::Fixnum(c as isize)))
|
|
||||||
})
|
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
self.return_char(c);
|
self.return_char(c);
|
||||||
|
|
||||||
isize::from_str_radix(&token, 10)
|
isize::from_str_radix(&token, 10)
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
token.parse::<Integer>()
|
token
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.parse::<Integer>()
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
self.line_num,
|
.map_err(|_| {
|
||||||
self.col_num,
|
ParserError::ParseBigInt(self.line_num, self.col_num)
|
||||||
))
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
isize::from_str_radix(&token, 10)
|
isize::from_str_radix(&token, 10)
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
token.parse::<Integer>()
|
token
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.parse::<Integer>()
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
self.line_num,
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isize::from_str_radix(&token, 10)
|
isize::from_str_radix(&token, 10)
|
||||||
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
.map(|n| Token::Constant(Constant::Fixnum(n)))
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
token.parse::<Integer>()
|
token
|
||||||
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
.parse::<Integer>()
|
||||||
.map_err(|_| ParserError::ParseBigInt(
|
.map(|n| Token::Constant(Constant::Integer(Rc::new(n))))
|
||||||
self.line_num,
|
.map_err(|_| ParserError::ParseBigInt(self.line_num, self.col_num))
|
||||||
self.col_num,
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -781,18 +762,19 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
Ok(c) if layout_char!(c) || new_line_char!(c) => {
|
Ok(c) if layout_char!(c) || new_line_char!(c) => {
|
||||||
self.skip_char()?;
|
self.skip_char()?;
|
||||||
layout_inserted = true;
|
layout_inserted = true;
|
||||||
},
|
}
|
||||||
Ok(c) if end_line_comment_char!(c) => {
|
Ok(c) if end_line_comment_char!(c) => {
|
||||||
self.single_line_comment()?;
|
self.single_line_comment()?;
|
||||||
layout_inserted = true;
|
layout_inserted = true;
|
||||||
},
|
}
|
||||||
Ok(c) if comment_1_char!(c) =>
|
Ok(c) if comment_1_char!(c) => {
|
||||||
if self.bracketed_comment()? {
|
if self.bracketed_comment()? {
|
||||||
layout_inserted = true;
|
layout_inserted = true;
|
||||||
} else {
|
} else {
|
||||||
more_layout = false;
|
more_layout = false;
|
||||||
},
|
}
|
||||||
_ => more_layout = false
|
}
|
||||||
|
_ => more_layout = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !more_layout {
|
if !more_layout {
|
||||||
@@ -825,8 +807,11 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
|
|
||||||
if c == '(' {
|
if c == '(' {
|
||||||
self.skip_char()?;
|
self.skip_char()?;
|
||||||
return Ok(if layout_inserted { Token::Open }
|
return Ok(if layout_inserted {
|
||||||
else { Token::OpenCT });
|
Token::Open
|
||||||
|
} else {
|
||||||
|
Token::OpenCT
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if c == '.' {
|
if c == '.' {
|
||||||
@@ -839,7 +824,7 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Ok(Token::End);
|
return Ok(Token::End);
|
||||||
},
|
}
|
||||||
Err(ParserError::UnexpectedEOF) => {
|
Err(ParserError::UnexpectedEOF) => {
|
||||||
return Ok(Token::End);
|
return Ok(Token::End);
|
||||||
}
|
}
|
||||||
@@ -891,8 +876,8 @@ impl<'a, R: Read> Lexer<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.name_token(c)
|
self.name_token(c)
|
||||||
},
|
}
|
||||||
Err(e) => Err(e)
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
extern crate lexical;
|
|
||||||
extern crate ordered_float;
|
|
||||||
#[cfg(feature = "rug")]
|
|
||||||
extern crate rug;
|
|
||||||
#[cfg(feature = "num-rug-adapter")]
|
#[cfg(feature = "num-rug-adapter")]
|
||||||
extern crate num_rug_adapter as rug;
|
use num_rug_adapter as rug;
|
||||||
extern crate unicode_reader;
|
#[cfg(feature = "rug")]
|
||||||
|
use rug;
|
||||||
|
|
||||||
#[macro_use] pub mod tabled_rc;
|
#[macro_use]
|
||||||
#[macro_use] pub mod ast;
|
pub mod tabled_rc;
|
||||||
#[macro_use] pub mod macros;
|
#[macro_use]
|
||||||
|
pub mod ast;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod macros;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod put_back_n;
|
pub mod put_back_n;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use ast::*;
|
use crate::ast::*;
|
||||||
use lexer::*;
|
use crate::lexer::*;
|
||||||
use tabled_rc::*;
|
use crate::tabled_rc::*;
|
||||||
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use rug::ops::NegAssign;
|
use crate::rug::ops::NegAssign;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
@@ -16,24 +16,29 @@ enum TokenType {
|
|||||||
Term,
|
Term,
|
||||||
Open,
|
Open,
|
||||||
OpenCT,
|
OpenCT,
|
||||||
OpenList, // '['
|
OpenList, // '['
|
||||||
OpenCurly, // '{'
|
OpenCurly, // '{'
|
||||||
HeadTailSeparator, // '|'
|
HeadTailSeparator, // '|'
|
||||||
Comma, // ','
|
Comma, // ','
|
||||||
Close,
|
Close,
|
||||||
CloseList, // ']'
|
CloseList, // ']'
|
||||||
CloseCurly, // '}'
|
CloseCurly, // '}'
|
||||||
End
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenType {
|
impl TokenType {
|
||||||
fn is_sep(self) -> bool {
|
fn is_sep(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TokenType::HeadTailSeparator | TokenType::OpenCT | TokenType::Open |
|
TokenType::HeadTailSeparator
|
||||||
TokenType::Close | TokenType::OpenList | TokenType::CloseList |
|
| TokenType::OpenCT
|
||||||
TokenType::OpenCurly | TokenType::CloseCurly | TokenType::Comma
|
| TokenType::Open
|
||||||
=> true,
|
| TokenType::Close
|
||||||
_ => false
|
| TokenType::OpenList
|
||||||
|
| TokenType::CloseList
|
||||||
|
| TokenType::OpenCurly
|
||||||
|
| TokenType::CloseCurly
|
||||||
|
| TokenType::Comma => true,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,12 +47,14 @@ impl TokenType {
|
|||||||
struct TokenDesc {
|
struct TokenDesc {
|
||||||
tt: TokenType,
|
tt: TokenType,
|
||||||
priority: usize,
|
priority: usize,
|
||||||
spec: u32
|
spec: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn get_clause_spec(
|
||||||
fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> Option<SharedOpDesc>
|
name: ClauseName,
|
||||||
{
|
arity: usize,
|
||||||
|
op_dir: &CompositeOpDir,
|
||||||
|
) -> Option<SharedOpDesc> {
|
||||||
match arity {
|
match arity {
|
||||||
1 => {
|
1 => {
|
||||||
/* This is a clause with an operator principal functor. Prefix operators
|
/* This is a clause with an operator principal functor. Prefix operators
|
||||||
@@ -60,20 +67,25 @@ fn get_clause_spec(name: ClauseName, arity: usize, op_dir: &CompositeOpDir) -> O
|
|||||||
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::Post) {
|
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::Post) {
|
||||||
return Some(cell.clone());
|
return Some(cell.clone());
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
2 =>
|
2 => {
|
||||||
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::In) {
|
if let Some(OpDirValue(cell)) = op_dir.get(name, Fixity::In) {
|
||||||
return Some(cell.clone());
|
return Some(cell.clone());
|
||||||
},
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option<OpDesc>
|
pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option<OpDesc> {
|
||||||
{
|
let mut op_desc = OpDesc {
|
||||||
let mut op_desc = OpDesc { pre: 0, inf: 0, post: 0, spec: 0 };
|
pre: 0,
|
||||||
|
inf: 0,
|
||||||
|
post: 0,
|
||||||
|
spec: 0,
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) {
|
if let Some(OpDirValue(cell)) = op_dir.get(name.clone(), Fixity::Pre) {
|
||||||
let (pri, spec) = cell.get();
|
let (pri, spec) = cell.get();
|
||||||
@@ -111,8 +123,7 @@ pub fn get_op_desc(name: ClauseName, op_dir: &CompositeOpDir) -> Option<OpDesc>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
d2.priority <= priority
|
||||||
&& is_term!(d3.spec)
|
&& is_term!(d3.spec)
|
||||||
&& is_term!(d1.spec)
|
&& is_term!(d1.spec)
|
||||||
@@ -120,18 +131,15 @@ fn affirm_xfx(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> b
|
|||||||
&& d1.priority < d2.priority
|
&& 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
|
d2.priority <= priority
|
||||||
&& ((is_term!(d3.spec) && d3.priority < d2.priority)
|
&& ((is_term!(d3.spec) && d3.priority < d2.priority)
|
||||||
|| (is_lterm!(d3.spec) && d3.priority == d2.priority))
|
|| (is_lterm!(d3.spec) && d3.priority == d2.priority))
|
||||||
&& is_term!(d1.spec)
|
&& is_term!(d1.spec)
|
||||||
&& d1.priority < d2.priority
|
&& 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
|
d2.priority < priority
|
||||||
&& is_term!(d3.spec)
|
&& is_term!(d3.spec)
|
||||||
&& d3.priority < d2.priority
|
&& d3.priority < d2.priority
|
||||||
@@ -139,49 +147,35 @@ fn affirm_xfy(priority: usize, d2: TokenDesc, d3: TokenDesc, d1: TokenDesc) -> b
|
|||||||
&& d1.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;
|
let is_valid_lterm = is_lterm!(d2.spec) && d2.priority == d1.priority;
|
||||||
(is_term!(d2.spec) && d2.priority < d1.priority) || is_valid_lterm
|
(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
|
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
|
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
|
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 {
|
match tt {
|
||||||
TokenType::Open | TokenType::OpenCT =>
|
TokenType::Open | TokenType::OpenCT => Some(clause_name!("(")),
|
||||||
Some(clause_name!("(")),
|
TokenType::Close => Some(clause_name!(")")),
|
||||||
TokenType::Close =>
|
TokenType::OpenList => Some(clause_name!("[")),
|
||||||
Some(clause_name!(")")),
|
TokenType::CloseList => Some(clause_name!("]")),
|
||||||
TokenType::OpenList =>
|
TokenType::OpenCurly => Some(clause_name!("{")),
|
||||||
Some(clause_name!("[")),
|
TokenType::CloseCurly => Some(clause_name!("}")),
|
||||||
TokenType::CloseList =>
|
TokenType::HeadTailSeparator => Some(clause_name!("|")),
|
||||||
Some(clause_name!("]")),
|
TokenType::Comma => Some(clause_name!(",")),
|
||||||
TokenType::OpenCurly =>
|
TokenType::End => Some(clause_name!(".")),
|
||||||
Some(clause_name!("{")),
|
_ => None,
|
||||||
TokenType::CloseCurly =>
|
|
||||||
Some(clause_name!("}")),
|
|
||||||
TokenType::HeadTailSeparator =>
|
|
||||||
Some(clause_name!("|")),
|
|
||||||
TokenType::Comma =>
|
|
||||||
Some(clause_name!(",")),
|
|
||||||
TokenType::End =>
|
|
||||||
Some(clause_name!(".")),
|
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +184,7 @@ pub struct OpDesc {
|
|||||||
pub pre: usize,
|
pub pre: usize,
|
||||||
pub inf: usize,
|
pub inf: usize,
|
||||||
pub post: usize,
|
pub post: usize,
|
||||||
pub spec: Specifier
|
pub spec: Specifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -201,8 +195,7 @@ pub struct Parser<'a, R: Read> {
|
|||||||
terms: Vec<Term>,
|
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![];
|
let mut tokens = vec![];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -227,10 +220,12 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
atom_tbl: TabledData<Atom>,
|
atom_tbl: TabledData<Atom>,
|
||||||
flags: MachineFlags,
|
flags: MachineFlags,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Parser { lexer: Lexer::new(atom_tbl, flags, stream),
|
Parser {
|
||||||
tokens: vec![],
|
lexer: Lexer::new(atom_tbl, flags, stream),
|
||||||
stack: Vec::new(),
|
tokens: vec![],
|
||||||
terms: Vec::new() }
|
stack: Vec::new(),
|
||||||
|
terms: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -255,50 +250,46 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
fn get_term_name(&mut self, td: TokenDesc) -> Option<(ClauseName, Option<SharedOpDesc>)> {
|
fn get_term_name(&mut self, td: TokenDesc) -> Option<(ClauseName, Option<SharedOpDesc>)> {
|
||||||
match td.tt {
|
match td.tt {
|
||||||
TokenType::HeadTailSeparator => {
|
TokenType::HeadTailSeparator => Some((
|
||||||
Some((clause_name!("|"), Some(SharedOpDesc::new(td.priority, td.spec))))
|
clause_name!("|"),
|
||||||
}
|
Some(SharedOpDesc::new(td.priority, td.spec)),
|
||||||
TokenType::Comma => {
|
)),
|
||||||
Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY))))
|
TokenType::Comma => Some((clause_name!(","), Some(SharedOpDesc::new(1000, XFY)))),
|
||||||
}
|
TokenType::Term => match self.terms.pop() {
|
||||||
TokenType::Term => {
|
Some(Term::Constant(_, Constant::Atom(atom, spec))) => Some((atom, spec)),
|
||||||
match self.terms.pop() {
|
Some(term) => {
|
||||||
Some(Term::Constant(_, Constant::Atom(atom, spec))) =>
|
self.terms.push(term);
|
||||||
Some((atom, spec)),
|
None
|
||||||
Some(term) => {
|
|
||||||
self.terms.push(term);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
_ => 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(arg2) = self.terms.pop() {
|
||||||
if let Some((name, shared_op_desc)) = self.get_term_name(td) {
|
if let Some((name, shared_op_desc)) = self.get_term_name(td) {
|
||||||
if let Some(arg1) = self.terms.pop() {
|
if let Some(arg1) = self.terms.pop() {
|
||||||
let term = Term::Clause(Cell::default(),
|
let term = Term::Clause(
|
||||||
name,
|
Cell::default(),
|
||||||
vec![Box::new(arg1), Box::new(arg2)],
|
name,
|
||||||
shared_op_desc);
|
vec![Box::new(arg1), Box::new(arg2)],
|
||||||
|
shared_op_desc,
|
||||||
|
);
|
||||||
|
|
||||||
self.terms.push(term);
|
self.terms.push(term);
|
||||||
self.stack.push(TokenDesc { tt: TokenType::Term,
|
self.stack.push(TokenDesc {
|
||||||
priority: td.priority,
|
tt: TokenType::Term,
|
||||||
spec });
|
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 arg1) = self.terms.pop() {
|
||||||
if let Some(mut name) = self.terms.pop() {
|
if let Some(mut name) = self.terms.pop() {
|
||||||
if is_postfix!(assoc) {
|
if is_postfix!(assoc) {
|
||||||
@@ -306,52 +297,61 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Term::Constant(_, Constant::Atom(name, shared_op_desc)) = name {
|
if let Term::Constant(_, Constant::Atom(name, shared_op_desc)) = name {
|
||||||
let term = Term::Clause(Cell::default(), name, vec![Box::new(arg1)],
|
let term =
|
||||||
shared_op_desc);
|
Term::Clause(Cell::default(), name, vec![Box::new(arg1)], shared_op_desc);
|
||||||
|
|
||||||
self.terms.push(term);
|
self.terms.push(term);
|
||||||
self.stack.push(TokenDesc { tt: TokenType::Term,
|
self.stack.push(TokenDesc {
|
||||||
priority: td.priority,
|
tt: TokenType::Term,
|
||||||
spec });
|
priority: td.priority,
|
||||||
|
spec,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn promote_atom_op(&mut self, atom: ClauseName, priority: usize, assoc: u32,
|
fn promote_atom_op(
|
||||||
op_dir_val: Option<&OpDirValue>)
|
&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());
|
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.terms
|
||||||
self.stack.push(TokenDesc { tt: TokenType::Term, priority, spec: assoc });
|
.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 {
|
let tt = match token {
|
||||||
Token::Constant(Constant::String(s))
|
Token::Constant(Constant::String(s)) if self.lexer.flags.double_quotes.is_codes() => {
|
||||||
if self.lexer.flags.double_quotes.is_codes() => {
|
let mut list = Term::Constant(Cell::default(), Constant::EmptyList);
|
||||||
let mut list = Term::Constant(Cell::default(), Constant::EmptyList);
|
|
||||||
|
|
||||||
for c in s.chars().rev() {
|
for c in s.chars().rev() {
|
||||||
list = Term::Cons(
|
list = Term::Cons(
|
||||||
|
Cell::default(),
|
||||||
|
Box::new(Term::Constant(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
Box::new(Term::Constant(
|
Constant::Fixnum(c as isize),
|
||||||
Cell::default(),
|
)),
|
||||||
Constant::Fixnum(c as isize),
|
Box::new(list),
|
||||||
)),
|
);
|
||||||
Box::new(list),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.terms.push(list);
|
|
||||||
TokenType::Term
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.terms.push(list);
|
||||||
|
TokenType::Term
|
||||||
|
}
|
||||||
Token::Constant(c) => {
|
Token::Constant(c) => {
|
||||||
self.terms.push(Term::Constant(Cell::default(), c));
|
self.terms.push(Term::Constant(Cell::default(), c));
|
||||||
TokenType::Term
|
TokenType::Term
|
||||||
},
|
}
|
||||||
Token::Var(v) => {
|
Token::Var(v) => {
|
||||||
if v.trim() == "_" {
|
if v.trim() == "_" {
|
||||||
self.terms.push(Term::AnonVar);
|
self.terms.push(Term::AnonVar);
|
||||||
@@ -360,7 +360,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenType::Term
|
TokenType::Term
|
||||||
},
|
}
|
||||||
Token::Comma => TokenType::Comma,
|
Token::Comma => TokenType::Comma,
|
||||||
Token::Open => TokenType::Open,
|
Token::Open => TokenType::Open,
|
||||||
Token::Close => TokenType::Close,
|
Token::Close => TokenType::Close,
|
||||||
@@ -381,18 +381,13 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
if let Some(desc1) = self.stack.pop() {
|
if let Some(desc1) = self.stack.pop() {
|
||||||
if let Some(desc2) = self.stack.pop() {
|
if let Some(desc2) = self.stack.pop() {
|
||||||
if let Some(desc3) = 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);
|
self.push_binary_op(desc2, LTERM);
|
||||||
continue;
|
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);
|
self.push_binary_op(desc2, LTERM);
|
||||||
continue;
|
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);
|
self.push_binary_op(desc2, TERM);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@@ -425,12 +420,12 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_arity_in_brackets(&self) -> Option<usize>
|
fn compute_arity_in_brackets(&self) -> Option<usize> {
|
||||||
{
|
|
||||||
let mut arity = 0;
|
let mut arity = 0;
|
||||||
|
|
||||||
for (i, desc) in self.stack.iter().rev().enumerate() {
|
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 {
|
if let TokenType::Comma = desc.tt {
|
||||||
return None;
|
return None;
|
||||||
} else if is_term!(desc.spec) || is_op!(desc.spec) || is_negate!(desc.spec) {
|
} else if is_term!(desc.spec) || is_op!(desc.spec) || is_negate!(desc.spec) {
|
||||||
@@ -454,8 +449,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool
|
fn reduce_term(&mut self, op_dir: &CompositeOpDir) -> bool {
|
||||||
{
|
|
||||||
if self.stack.is_empty() {
|
if self.stack.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -464,7 +458,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
let arity = match self.compute_arity_in_brackets() {
|
let arity = match self.compute_arity_in_brackets() {
|
||||||
Some(arity) => arity,
|
Some(arity) => arity,
|
||||||
None => return false
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.stack.len() > 2 * arity {
|
if self.stack.len() > 2 * arity {
|
||||||
@@ -490,9 +484,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
if self.atomize_term(&self.terms[idx - 1]).is_some() {
|
if self.atomize_term(&self.terms[idx - 1]).is_some() {
|
||||||
self.stack.truncate(stack_len + 1);
|
self.stack.truncate(stack_len + 1);
|
||||||
|
|
||||||
let mut subterms: Vec<_> = self.terms.drain(idx ..)
|
let mut subterms: Vec<_> = self.terms.drain(idx..).map(|t| Box::new(t)).collect();
|
||||||
.map(|t| Box::new(t))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) {
|
if let Some(name) = self.terms.pop().and_then(|t| self.atomize_term(&t)) {
|
||||||
// reduce the '.' functor to a cons cell if it applies.
|
// reduce the '.' functor to a cons cell if it applies.
|
||||||
@@ -503,11 +495,15 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.terms.push(Term::Cons(Cell::default(), head, tail));
|
self.terms.push(Term::Cons(Cell::default(), head, tail));
|
||||||
} else {
|
} else {
|
||||||
let spec = get_clause_spec(name.clone(), subterms.len(), op_dir);
|
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,
|
if let Some(&mut TokenDesc {
|
||||||
ref mut tt }) = self.stack.last_mut()
|
ref mut priority,
|
||||||
|
ref mut spec,
|
||||||
|
ref mut tt,
|
||||||
|
}) = self.stack.last_mut()
|
||||||
{
|
{
|
||||||
*tt = TokenType::Term;
|
*tt = TokenType::Term;
|
||||||
*priority = 0;
|
*priority = 0;
|
||||||
@@ -523,7 +519,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn devour_whitespace(&mut self) -> Result<(), ParserError> {
|
pub fn devour_whitespace(&mut self) -> Result<(), ParserError> {
|
||||||
self.lexer.scan_for_layout()?;
|
self.lexer.scan_for_layout()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,8 +527,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.stack.clear()
|
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() {
|
if let Some(term) = self.terms.pop() {
|
||||||
let op_desc = self.stack[index - 1];
|
let op_desc = self.stack[index - 1];
|
||||||
|
|
||||||
@@ -548,8 +543,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.terms.extend(terms.into_iter());
|
self.terms.extend(terms.into_iter());
|
||||||
return arity;
|
return arity;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,12 +553,12 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_arity_in_list(&self) -> Option<usize>
|
fn compute_arity_in_list(&self) -> Option<usize> {
|
||||||
{
|
|
||||||
let mut arity = 0;
|
let mut arity = 0;
|
||||||
|
|
||||||
for (i, desc) in self.stack.iter().rev().enumerate() {
|
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 {
|
if let TokenType::Comma = desc.tt {
|
||||||
return None;
|
return None;
|
||||||
} else if is_term!(desc.spec) || is_op!(desc.spec) {
|
} else if is_term!(desc.spec) || is_op!(desc.spec) {
|
||||||
@@ -590,8 +584,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reduce_list(&mut self) -> Result<bool, ParserError>
|
fn reduce_list(&mut self) -> Result<bool, ParserError> {
|
||||||
{
|
|
||||||
if self.stack.is_empty() {
|
if self.stack.is_empty() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@@ -602,7 +595,8 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
td.tt = TokenType::Term;
|
td.tt = TokenType::Term;
|
||||||
td.priority = 0;
|
td.priority = 0;
|
||||||
|
|
||||||
self.terms.push(Term::Constant(Cell::default(), Constant::EmptyList));
|
self.terms
|
||||||
|
.push(Term::Constant(Cell::default(), Constant::EmptyList));
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -611,7 +605,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
let mut arity = match self.compute_arity_in_list() {
|
let mut arity = match self.compute_arity_in_list() {
|
||||||
Some(arity) => arity,
|
Some(arity) => arity,
|
||||||
None => return Ok(false)
|
None => return Ok(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
// we know that self.stack.len() >= 2 by this point.
|
// we know that self.stack.len() >= 2 by this point.
|
||||||
@@ -621,12 +615,15 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator {
|
let end_term = if self.stack[idx].tt != TokenType::HeadTailSeparator {
|
||||||
Term::Constant(Cell::default(), Constant::EmptyList)
|
Term::Constant(Cell::default(), Constant::EmptyList)
|
||||||
} else {
|
} else {
|
||||||
let term =
|
let term = match self.terms.pop() {
|
||||||
match self.terms.pop() {
|
Some(term) => term,
|
||||||
Some(term) => term,
|
_ => {
|
||||||
_ => return Err(ParserError::IncompleteReduction(self.lexer.line_num,
|
return Err(ParserError::IncompleteReduction(
|
||||||
self.lexer.col_num))
|
self.lexer.line_num,
|
||||||
};
|
self.lexer.col_num,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if self.stack[idx].priority > 1000 {
|
if self.stack[idx].priority > 1000 {
|
||||||
arity += self.expand_comma_compacted_terms(idx);
|
arity += self.expand_comma_compacted_terms(idx);
|
||||||
@@ -639,15 +636,17 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
let idx = self.terms.len() - arity;
|
let idx = self.terms.len() - arity;
|
||||||
|
|
||||||
let list = self.terms.drain(idx ..)
|
let list = self.terms.drain(idx..).rev().fold(end_term, |acc, t| {
|
||||||
.rev()
|
Term::Cons(Cell::default(), Box::new(t), Box::new(acc))
|
||||||
.fold(end_term, |acc, t| Term::Cons(Cell::default(),
|
});
|
||||||
Box::new(t),
|
|
||||||
Box::new(acc)));
|
|
||||||
|
|
||||||
self.stack.truncate(list_len);
|
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);
|
self.terms.push(list);
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@@ -664,8 +663,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
td.priority = 0;
|
td.priority = 0;
|
||||||
td.spec = TERM;
|
td.spec = TERM;
|
||||||
|
|
||||||
let term = Term::Constant(Cell::default(),
|
let term = Term::Constant(Cell::default(), atom!("{}", self.lexer.atom_tbl));
|
||||||
atom!("{}", self.lexer.atom_tbl));
|
|
||||||
self.terms.push(term);
|
self.terms.push(term);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@@ -687,17 +685,19 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
let term = match self.terms.pop() {
|
let term = match self.terms.pop() {
|
||||||
Some(term) => term,
|
Some(term) => term,
|
||||||
_ => return Err(ParserError::IncompleteReduction(
|
_ => {
|
||||||
self.lexer.line_num,
|
return Err(ParserError::IncompleteReduction(
|
||||||
self.lexer.col_num,
|
self.lexer.line_num,
|
||||||
))
|
self.lexer.col_num,
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.terms.push(Term::Clause(
|
self.terms.push(Term::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
clause_name!("{}"),
|
clause_name!("{}"),
|
||||||
vec![Box::new(term)],
|
vec![Box::new(term)],
|
||||||
None
|
None,
|
||||||
));
|
));
|
||||||
|
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
@@ -723,29 +723,35 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
let idx = self.stack.len() - 2;
|
let idx = self.stack.len() - 2;
|
||||||
|
|
||||||
match self.stack.remove(idx) {
|
match self.stack.remove(idx) {
|
||||||
td =>
|
td => match td.tt {
|
||||||
match td.tt {
|
TokenType::Open | TokenType::OpenCT => {
|
||||||
TokenType::Open | TokenType::OpenCT => {
|
if self.stack[idx].tt == TokenType::Comma {
|
||||||
if self.stack[idx].tt == TokenType::Comma {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(atom) = sep_to_atom(self.stack[idx].tt) {
|
if let Some(atom) = sep_to_atom(self.stack[idx].tt) {
|
||||||
self.terms.push(Term::Constant(Cell::default(), Constant::Atom(atom, None)));
|
self.terms
|
||||||
}
|
.push(Term::Constant(Cell::default(), Constant::Atom(atom, None)));
|
||||||
|
}
|
||||||
|
|
||||||
self.stack[idx].spec = TERM;
|
self.stack[idx].spec = TERM;
|
||||||
self.stack[idx].tt = TokenType::Term;
|
self.stack[idx].tt = TokenType::Term;
|
||||||
self.stack[idx].priority = 0;
|
self.stack[idx].priority = 0;
|
||||||
true
|
true
|
||||||
},
|
|
||||||
_ => false
|
|
||||||
}
|
}
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_op(&mut self, name: ClauseName, op_dir: &CompositeOpDir) -> Result<bool, ParserError> {
|
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) {
|
if (pre > 0 && inf + post > 0) || is_negate!(spec) {
|
||||||
match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? {
|
match self.tokens.last().ok_or(ParserError::UnexpectedEOF)? {
|
||||||
// do this when layout hasn't been inserted,
|
// do this when layout hasn't been inserted,
|
||||||
@@ -764,7 +770,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
spec & (XFX | XFY | YFX | YF | XF),
|
spec & (XFX | XFY | YFX | YF | XF),
|
||||||
op_dir_val,
|
op_dir_val,
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.reduce_op(inf + post);
|
self.reduce_op(inf + post);
|
||||||
|
|
||||||
@@ -782,11 +788,21 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let op_dir_val = op_dir.get(name.clone(), Fixity::Pre);
|
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 {
|
} else {
|
||||||
let op_dir_val = op_dir.get(name.clone(), Fixity::Pre);
|
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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -807,7 +823,8 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else { // not an operator.
|
} else {
|
||||||
|
// not an operator.
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -815,41 +832,37 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
fn atomize_term(&self, term: &Term) -> Option<ClauseName> {
|
fn atomize_term(&self, term: &Term) -> Option<ClauseName> {
|
||||||
match term {
|
match term {
|
||||||
&Term::Constant(_, ref c) => self.atomize_constant(c),
|
&Term::Constant(_, ref c) => self.atomize_constant(c),
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomize_constant(&self, c: &Constant) -> Option<ClauseName> {
|
fn atomize_constant(&self, c: &Constant) -> Option<ClauseName> {
|
||||||
match c {
|
match c {
|
||||||
&Constant::Atom(ref name, _) => Some(name.clone()),
|
&Constant::Atom(ref name, _) => Some(name.clone()),
|
||||||
&Constant::Char(c) =>
|
&Constant::Char(c) => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
|
||||||
Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
|
&Constant::EmptyList => Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
|
||||||
&Constant::EmptyList =>
|
_ => None,
|
||||||
Some(clause_name!(c.to_string(), self.lexer.atom_tbl)),
|
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn negate_number<N, Negator, ToConstant>(
|
fn negate_number<N, Negator, ToConstant>(&mut self, n: N, negator: Negator, constr: ToConstant)
|
||||||
&mut self,
|
where
|
||||||
n: N,
|
Negator: Fn(N) -> N,
|
||||||
negator: Negator,
|
ToConstant: Fn(N) -> Constant,
|
||||||
constr: ToConstant
|
|
||||||
)
|
|
||||||
where Negator: Fn(N) -> N,
|
|
||||||
ToConstant: Fn(N) -> Constant
|
|
||||||
{
|
{
|
||||||
if let Some(desc) = self.stack.last().cloned() {
|
if let Some(desc) = self.stack.last().cloned() {
|
||||||
if let Some(term) = self.terms.last().cloned() {
|
if let Some(term) = self.terms.last().cloned() {
|
||||||
match term {
|
match term {
|
||||||
Term::Constant(_, Constant::Atom(ref name, _))
|
Term::Constant(_, Constant::Atom(ref name, _))
|
||||||
if name.as_str() == "-" && (is_prefix!(desc.spec) || is_negate!(desc.spec)) => {
|
if name.as_str() == "-"
|
||||||
self.stack.pop();
|
&& (is_prefix!(desc.spec) || is_negate!(desc.spec)) =>
|
||||||
self.terms.pop();
|
{
|
||||||
|
self.stack.pop();
|
||||||
|
self.terms.pop();
|
||||||
|
|
||||||
self.shift(Token::Constant(constr(negator(n))), 0, TERM);
|
self.shift(Token::Constant(constr(negator(n))), 0, TERM);
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -864,38 +877,36 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
Some(t) => {
|
Some(t) => {
|
||||||
t.neg_assign();
|
t.neg_assign();
|
||||||
}
|
}
|
||||||
None => {
|
None => {}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
Token::Constant(Constant::Fixnum(n)) =>
|
Token::Constant(Constant::Fixnum(n)) => self.negate_number(n, |n| -n, Constant::Fixnum),
|
||||||
self.negate_number(n, |n| -n, Constant::Fixnum),
|
Token::Constant(Constant::Integer(n)) => {
|
||||||
Token::Constant(Constant::Integer(n)) =>
|
self.negate_number(n, negate_rc, Constant::Integer)
|
||||||
self.negate_number(n, negate_rc, Constant::Integer),
|
}
|
||||||
Token::Constant(Constant::Rational(n)) =>
|
Token::Constant(Constant::Rational(n)) => {
|
||||||
self.negate_number(n, negate_rc, Constant::Rational),
|
self.negate_number(n, negate_rc, Constant::Rational)
|
||||||
Token::Constant(Constant::Float(n)) =>
|
}
|
||||||
self.negate_number(
|
Token::Constant(Constant::Float(n)) => {
|
||||||
n,
|
self.negate_number(n, |n| OrderedFloat(-n.into_inner()), |n| Constant::Float(n))
|
||||||
|n| OrderedFloat(-n.into_inner()),
|
}
|
||||||
|n| Constant::Float(n)
|
Token::Constant(c) => {
|
||||||
),
|
|
||||||
Token::Constant(c) =>
|
|
||||||
if let Some(name) = self.atomize_constant(&c) {
|
if let Some(name) = self.atomize_constant(&c) {
|
||||||
if !self.shift_op(name, op_dir)? {
|
if !self.shift_op(name, op_dir)? {
|
||||||
self.shift(Token::Constant(c), 0, TERM);
|
self.shift(Token::Constant(c), 0, TERM);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.shift(Token::Constant(c), 0, TERM);
|
self.shift(Token::Constant(c), 0, TERM);
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Token::Var(v) => self.shift(Token::Var(v), 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::OpenCT => self.shift(Token::OpenCT, 1300, DELIMITER),
|
||||||
Token::Close =>
|
Token::Close => {
|
||||||
if !self.reduce_term(op_dir) {
|
if !self.reduce_term(op_dir) {
|
||||||
if !self.reduce_brackets() {
|
if !self.reduce_brackets() {
|
||||||
return Err(ParserError::IncompleteReduction(
|
return Err(ParserError::IncompleteReduction(
|
||||||
@@ -903,23 +914,26 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.lexer.col_num,
|
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()? {
|
if !self.reduce_list()? {
|
||||||
return Err(ParserError::IncompleteReduction(
|
return Err(ParserError::IncompleteReduction(
|
||||||
self.lexer.line_num,
|
self.lexer.line_num,
|
||||||
self.lexer.col_num,
|
self.lexer.col_num,
|
||||||
));
|
));
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER),
|
Token::OpenCurly => self.shift(Token::OpenCurly, 1300, DELIMITER),
|
||||||
Token::CloseCurly =>
|
Token::CloseCurly => {
|
||||||
if !self.reduce_curly()? {
|
if !self.reduce_curly()? {
|
||||||
return Err(ParserError::IncompleteReduction(
|
return Err(ParserError::IncompleteReduction(
|
||||||
self.lexer.line_num,
|
self.lexer.line_num,
|
||||||
self.lexer.col_num,
|
self.lexer.col_num,
|
||||||
));
|
));
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Token::HeadTailSeparator => {
|
Token::HeadTailSeparator => {
|
||||||
/* '|' as an operator must have priority > 1000 and can only be infix.
|
/* '|' 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
|
* See: http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#Res_A78
|
||||||
@@ -930,23 +944,25 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
|
|
||||||
self.reduce_op(priority);
|
self.reduce_op(priority);
|
||||||
self.shift(Token::HeadTailSeparator, priority, spec);
|
self.shift(Token::HeadTailSeparator, priority, spec);
|
||||||
},
|
}
|
||||||
Token::Comma => {
|
Token::Comma => {
|
||||||
self.reduce_op(1000);
|
self.reduce_op(1000);
|
||||||
self.shift(Token::Comma, 1000, XFY);
|
self.shift(Token::Comma, 1000, XFY);
|
||||||
},
|
}
|
||||||
Token::End =>
|
Token::End => match self.stack.last().map(|t| t.tt) {
|
||||||
match self.stack.last().map(|t| t.tt) {
|
Some(TokenType::Open)
|
||||||
Some(TokenType::Open)
|
| Some(TokenType::OpenCT)
|
||||||
| Some(TokenType::OpenCT)
|
| Some(TokenType::OpenList)
|
||||||
| Some(TokenType::OpenList)
|
| Some(TokenType::OpenCurly)
|
||||||
| Some(TokenType::OpenCurly)
|
| Some(TokenType::HeadTailSeparator)
|
||||||
| Some(TokenType::HeadTailSeparator)
|
| Some(TokenType::Comma) => {
|
||||||
| Some(TokenType::Comma)
|
return Err(ParserError::IncompleteReduction(
|
||||||
=> return Err(ParserError::IncompleteReduction(self.lexer.line_num,
|
self.lexer.line_num,
|
||||||
self.lexer.col_num)),
|
self.lexer.col_num,
|
||||||
_ => {}
|
))
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -957,8 +973,7 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.lexer.eof()
|
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)?;
|
self.tokens = read_tokens(&mut self.lexer)?;
|
||||||
|
|
||||||
while let Some(token) = self.tokens.pop() {
|
while let Some(token) = self.tokens.pop() {
|
||||||
@@ -968,21 +983,31 @@ impl<'a, R: Read> Parser<'a, R> {
|
|||||||
self.reduce_op(1400);
|
self.reduce_op(1400);
|
||||||
|
|
||||||
if self.terms.len() > 1 || self.stack.len() > 1 {
|
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() {
|
match self.terms.pop() {
|
||||||
Some(term) => if self.terms.is_empty() {
|
Some(term) => {
|
||||||
Ok(term)
|
if self.terms.is_empty() {
|
||||||
} else {
|
Ok(term)
|
||||||
Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num))
|
} else {
|
||||||
},
|
Err(ParserError::IncompleteReduction(
|
||||||
_ => Err(ParserError::IncompleteReduction(self.lexer.line_num, self.lexer.col_num))
|
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();
|
let mut terms = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
Reference in New Issue
Block a user