mirror of https://github.com/rm-dr/daisy
Treeify now handles both left- and right-associative operators
parent
c92670c918
commit
a40ebb7500
|
@ -52,7 +52,6 @@ pub enum Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_args(&mut self) -> Option<&mut VecDeque<Token>> {
|
pub fn get_args(&mut self) -> Option<&mut VecDeque<Token>> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -239,7 +238,78 @@ pub enum Operator {
|
||||||
Power,
|
Power,
|
||||||
|
|
||||||
Negative,
|
Negative,
|
||||||
Factorial
|
Factorial,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operator {
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_binary(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Operator::Negative
|
||||||
|
| Operator::Factorial
|
||||||
|
=> false,
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_left_associative(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Operator::Negative
|
||||||
|
| Operator::Power
|
||||||
|
=> false,
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn into_token(&self, mut args: VecDeque<Token>) -> Token {
|
||||||
|
match self {
|
||||||
|
Operator::Add => Token::Add(args),
|
||||||
|
|
||||||
|
Operator::Multiply
|
||||||
|
| Operator::ImplicitMultiply
|
||||||
|
=> Token::Multiply(args),
|
||||||
|
|
||||||
|
Operator::Subtract => {
|
||||||
|
if args.len() != 2 { panic!() }
|
||||||
|
let a = args.pop_front().unwrap();
|
||||||
|
let b = args.pop_front().unwrap();
|
||||||
|
|
||||||
|
Token::Add(
|
||||||
|
VecDeque::from(vec!(
|
||||||
|
a,
|
||||||
|
Token::Negative(VecDeque::from(vec!(b)))
|
||||||
|
)))
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::Divide => {
|
||||||
|
if args.len() != 2 { panic!() }
|
||||||
|
Token::Divide(args)
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::ModuloLong |
|
||||||
|
Operator::Modulo => {
|
||||||
|
if args.len() != 2 { panic!() }
|
||||||
|
Token::Modulo(args)
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::Power => {
|
||||||
|
if args.len() != 2 { panic!() }
|
||||||
|
Token::Power(args)
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::Negative => {
|
||||||
|
if args.len() != 1 { panic!() }
|
||||||
|
Token::Negative(args)
|
||||||
|
},
|
||||||
|
|
||||||
|
Operator::Factorial => {
|
||||||
|
if args.len() != 1 { panic!() }
|
||||||
|
Token::Factorial(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specifies the location of a token in an input string.
|
/// Specifies the location of a token in an input string.
|
||||||
|
|
|
@ -5,35 +5,11 @@ use crate::parser::LineLocation;
|
||||||
use crate::parser::ParserError;
|
use crate::parser::ParserError;
|
||||||
use crate::parser::Operator;
|
use crate::parser::Operator;
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn select_op(k: Operator, mut new_token_args: VecDeque<Token>) -> Token {
|
|
||||||
match k {
|
|
||||||
Operator::Subtract => {
|
|
||||||
let a = new_token_args.pop_front().unwrap();
|
|
||||||
let b = new_token_args.pop_front().unwrap();
|
|
||||||
|
|
||||||
Token::Add(
|
|
||||||
VecDeque::from(vec!(
|
|
||||||
a,
|
|
||||||
Token::Negative(VecDeque::from(vec!(b)))
|
|
||||||
)))
|
|
||||||
},
|
|
||||||
Operator::Add => Token::Add(new_token_args),
|
|
||||||
Operator::Divide => Token::Divide(new_token_args),
|
|
||||||
Operator::Multiply => Token::Multiply(new_token_args),
|
|
||||||
Operator::ImplicitMultiply => Token::Multiply(new_token_args),
|
|
||||||
Operator::Modulo => Token::Modulo(new_token_args),
|
|
||||||
Operator::ModuloLong => Token::Modulo(new_token_args),
|
|
||||||
Operator::Power => Token::Power(new_token_args),
|
|
||||||
Operator::Negative => Token::Negative(new_token_args),
|
|
||||||
Operator::Factorial => Token::Factorial(new_token_args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn treeify_binary(
|
fn treeify_binary(
|
||||||
mut i: usize,
|
mut i: usize,
|
||||||
g_inner: &mut VecDeque<Token>
|
g_inner: &mut VecDeque<Token>,
|
||||||
) -> Result<usize, (LineLocation, ParserError)> {
|
left_associative: bool
|
||||||
|
) -> Result<(), (LineLocation, ParserError)> {
|
||||||
|
|
||||||
let this: &Token = &g_inner[i];
|
let this: &Token = &g_inner[i];
|
||||||
|
|
||||||
|
@ -46,7 +22,9 @@ fn treeify_binary(
|
||||||
return Err((*l, ParserError::Syntax));
|
return Err((*l, ParserError::Syntax));
|
||||||
}
|
}
|
||||||
|
|
||||||
let right: &Token = {
|
let next: &Token;
|
||||||
|
if left_associative {
|
||||||
|
next = {
|
||||||
if i < g_inner.len()-1 {
|
if i < g_inner.len()-1 {
|
||||||
&g_inner[i+1]
|
&g_inner[i+1]
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,37 +35,36 @@ fn treeify_binary(
|
||||||
return Err((*l, ParserError::Syntax));
|
return Err((*l, ParserError::Syntax));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
next = {
|
||||||
|
if i > 0 {
|
||||||
|
&g_inner[i-1]
|
||||||
|
} else {
|
||||||
|
let l = match this {
|
||||||
|
Token::PreOperator(l, _) => l,
|
||||||
|
_ => panic!()
|
||||||
|
};
|
||||||
|
return Err((*l, ParserError::Syntax));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if let Token::PreOperator(l, o) = right {
|
|
||||||
match o {
|
if let Token::PreOperator(l, o) = next {
|
||||||
// Binary operators
|
if {
|
||||||
Operator::ModuloLong |
|
(!o.is_binary()) &&
|
||||||
Operator::Subtract |
|
!(o.is_left_associative() && left_associative)
|
||||||
Operator::Add |
|
} {
|
||||||
Operator::Divide |
|
// Only right-associative unary operators can follow a binary operator
|
||||||
Operator::Multiply |
|
return Ok(());
|
||||||
Operator::ImplicitMultiply |
|
} else {
|
||||||
Operator::Modulo |
|
|
||||||
Operator::Power |
|
|
||||||
// Right unary operators
|
|
||||||
Operator::Factorial
|
|
||||||
=> {
|
|
||||||
// Binary and right-unary operators cannot
|
|
||||||
// follow a binary operator.
|
|
||||||
let tl = *this.get_line_location();
|
let tl = *this.get_line_location();
|
||||||
return Err((
|
return Err((
|
||||||
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
|
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
|
||||||
ParserError::Syntax
|
ParserError::Syntax
|
||||||
));
|
));
|
||||||
},
|
|
||||||
|
|
||||||
// Left unary operators
|
|
||||||
Operator::Negative => {
|
|
||||||
i += 1;
|
|
||||||
return Ok(i);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Precedence of this operator
|
// Precedence of this operator
|
||||||
|
@ -96,7 +73,13 @@ fn treeify_binary(
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Precedence of the operator contesting the right argument.
|
// Precedence of the operators contesting our arguments
|
||||||
|
let left_val = if i > 1 {
|
||||||
|
match &g_inner[i-2] {
|
||||||
|
Token::PreOperator(_, q) => Some(*q as isize),
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
} else { None };
|
||||||
let right_val = if i < g_inner.len()-2 {
|
let right_val = if i < g_inner.len()-2 {
|
||||||
match &g_inner[i+2] {
|
match &g_inner[i+2] {
|
||||||
Token::PreOperator(_, q) => Some(*q as isize),
|
Token::PreOperator(_, q) => Some(*q as isize),
|
||||||
|
@ -104,8 +87,10 @@ fn treeify_binary(
|
||||||
}
|
}
|
||||||
} else { None };
|
} else { None };
|
||||||
|
|
||||||
|
if {
|
||||||
if right_val.is_none() || this_val > right_val.unwrap() {
|
(left_val.is_none() || this_val >= left_val.unwrap()) &&
|
||||||
|
(right_val.is_none() || this_val >= right_val.unwrap())
|
||||||
|
} {
|
||||||
// This operator has higher precedence, it takes both arguments
|
// This operator has higher precedence, it takes both arguments
|
||||||
let mut left = g_inner.remove(i-1).unwrap();
|
let mut left = g_inner.remove(i-1).unwrap();
|
||||||
let this = g_inner.remove(i-1).unwrap();
|
let this = g_inner.remove(i-1).unwrap();
|
||||||
|
@ -122,118 +107,26 @@ fn treeify_binary(
|
||||||
new_token_args.push_back(left);
|
new_token_args.push_back(left);
|
||||||
new_token_args.push_back(right);
|
new_token_args.push_back(right);
|
||||||
|
|
||||||
g_inner.insert(i-1, select_op(k, new_token_args));
|
g_inner.insert(i-1, k.into_token(new_token_args));
|
||||||
|
|
||||||
if i > 1 { i -= 2; } else { i = 0; }
|
return Ok(());
|
||||||
return Ok(i);
|
|
||||||
} else {
|
} else {
|
||||||
// The operator to the right has higher precedence.
|
return Ok(());
|
||||||
// Move on, don't to anything yet.
|
|
||||||
i += 2;
|
|
||||||
return Ok(i);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn treeify_unaryleft(
|
fn treeify_unary(
|
||||||
mut i: usize,
|
i: usize,
|
||||||
g_inner: &mut VecDeque<Token>
|
g_inner: &mut VecDeque<Token>,
|
||||||
) -> Result<usize, (LineLocation, ParserError)> {
|
left_associative: bool
|
||||||
|
) -> Result<(), (LineLocation, ParserError)> {
|
||||||
|
|
||||||
let this: &Token = &g_inner[i];
|
let this: &Token = &g_inner[i];
|
||||||
let right: &Token = {
|
let next: &Token;
|
||||||
if i < g_inner.len()-1 {
|
if left_associative {
|
||||||
&g_inner[i+1]
|
next = {
|
||||||
} else {
|
|
||||||
let l = match this {
|
|
||||||
Token::PreOperator(l, _) => l,
|
|
||||||
_ => panic!()
|
|
||||||
};
|
|
||||||
return Err((*l, ParserError::Syntax));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if let Token::PreOperator(l, o) = right {
|
|
||||||
match o {
|
|
||||||
// Binary operators
|
|
||||||
Operator::ModuloLong |
|
|
||||||
Operator::Subtract |
|
|
||||||
Operator::Add |
|
|
||||||
Operator::Divide |
|
|
||||||
Operator::Multiply |
|
|
||||||
Operator::ImplicitMultiply |
|
|
||||||
Operator::Modulo |
|
|
||||||
Operator::Power |
|
|
||||||
// Right unary operators
|
|
||||||
Operator::Factorial
|
|
||||||
=> {
|
|
||||||
// Binary and right-unary operators cannot
|
|
||||||
// follow a binary operator.
|
|
||||||
let tl = *this.get_line_location();
|
|
||||||
return Err((
|
|
||||||
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
|
|
||||||
ParserError::Syntax
|
|
||||||
));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Left unary operators
|
|
||||||
Operator::Negative => {
|
|
||||||
i += 1;
|
|
||||||
return Ok(i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Precedence of this operator
|
|
||||||
let this_val: isize = match this {
|
|
||||||
Token::PreOperator(_, q) => *q as isize,
|
|
||||||
_ => panic!()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Precedence of the operator contesting its argument
|
|
||||||
let right_val = if i < g_inner.len()-2 {
|
|
||||||
match &g_inner[i+2] {
|
|
||||||
Token::PreOperator(_, q) => Some(*q as isize),
|
|
||||||
_ => panic!()
|
|
||||||
}
|
|
||||||
} else { None };
|
|
||||||
|
|
||||||
|
|
||||||
if right_val.is_none() || this_val > right_val.unwrap() {
|
|
||||||
let this = g_inner.remove(i).unwrap();
|
|
||||||
let mut right = g_inner.remove(i).unwrap();
|
|
||||||
if let Token::PreGroup(_, _) = right { right = p_treeify(right)?; }
|
|
||||||
|
|
||||||
let k = match this {
|
|
||||||
Token::PreOperator(_, k) => k,
|
|
||||||
_ => panic!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3);
|
|
||||||
new_token_args.push_back(right);
|
|
||||||
|
|
||||||
g_inner.insert(i, select_op(k, new_token_args));
|
|
||||||
|
|
||||||
if i > 0 { i -= 1; } else { i = 0; }
|
|
||||||
return Ok(i);
|
|
||||||
} else {
|
|
||||||
// The operator to the right has higher precedence.
|
|
||||||
// Move on, don't to anything yet.
|
|
||||||
i += 2;
|
|
||||||
return Ok(i);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn treeify_unaryright(
|
|
||||||
mut i: usize,
|
|
||||||
g_inner: &mut VecDeque<Token>
|
|
||||||
) -> Result<usize, (LineLocation, ParserError)> {
|
|
||||||
|
|
||||||
let this: &Token = &g_inner[i];
|
|
||||||
let left: &Token = {
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
&g_inner[i-1]
|
&g_inner[i-1]
|
||||||
} else {
|
} else {
|
||||||
|
@ -244,18 +137,33 @@ fn treeify_unaryright(
|
||||||
return Err((*l, ParserError::Syntax));
|
return Err((*l, ParserError::Syntax));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
next = {
|
||||||
// We need to check the element after unary right operators too.
|
|
||||||
// Bad syntax like `3!3` won't be caught otherwise.
|
|
||||||
let right: Option<&Token> = {
|
|
||||||
if i < g_inner.len()-1 {
|
if i < g_inner.len()-1 {
|
||||||
Some(&g_inner[i+1])
|
&g_inner[i+1]
|
||||||
} else {None}
|
} else {
|
||||||
|
let l = match this {
|
||||||
|
Token::PreOperator(l, _) => l,
|
||||||
|
_ => panic!()
|
||||||
};
|
};
|
||||||
|
return Err((*l, ParserError::Syntax));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if right.is_some() {
|
// We need to check the element after unary operators too.
|
||||||
if let Token::PreOperator(l, o) = right.unwrap() {
|
// Bad syntax like `3!3` won't be caught otherwise.
|
||||||
|
let prev: Option<&Token>;
|
||||||
|
if left_associative {
|
||||||
|
prev = if i < g_inner.len()-1 { Some(&g_inner[i+1]) } else {None};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
prev = if i > 0 { Some(&g_inner[i-1]) } else {None};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev.is_some() {
|
||||||
|
if let Token::PreOperator(l, o) = prev.unwrap() {
|
||||||
match o {
|
match o {
|
||||||
// Left unary operators
|
// Left unary operators
|
||||||
Operator::Negative => {
|
Operator::Negative => {
|
||||||
|
@ -275,13 +183,14 @@ fn treeify_unaryright(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Token::PreOperator(l, _) = left {
|
|
||||||
|
|
||||||
|
if let Token::PreOperator(l, _) = next {
|
||||||
let tl = *this.get_line_location();
|
let tl = *this.get_line_location();
|
||||||
return Err((
|
return Err((
|
||||||
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
|
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
|
||||||
ParserError::Syntax
|
ParserError::Syntax
|
||||||
));
|
));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Precedence of this operator
|
// Precedence of this operator
|
||||||
|
@ -290,19 +199,32 @@ fn treeify_unaryright(
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Precedence of the operator contesting its argument.
|
// Precedence of the operator contesting its argument
|
||||||
let left_val = if i >= 2 {
|
let next_val = if left_associative {
|
||||||
|
if i > 1 {
|
||||||
match &g_inner[i-2] {
|
match &g_inner[i-2] {
|
||||||
Token::PreOperator(_, q) => Some(*q as isize),
|
Token::PreOperator(_, q) => Some(*q as isize),
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
}
|
}
|
||||||
} else { None };
|
} else { None }
|
||||||
|
} else {
|
||||||
|
if i < g_inner.len()-2 {
|
||||||
|
match &g_inner[i+2] {
|
||||||
|
Token::PreOperator(_, q) => Some(*q as isize),
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
} else { None }
|
||||||
|
};
|
||||||
|
|
||||||
|
if next_val.is_none() || this_val > next_val.unwrap() {
|
||||||
if left_val.is_none() || this_val > left_val.unwrap() {
|
|
||||||
let this = g_inner.remove(i).unwrap();
|
let this = g_inner.remove(i).unwrap();
|
||||||
let mut left = g_inner.remove(i-1).unwrap();
|
let mut next;
|
||||||
if let Token::PreGroup(_, _) = left { left = p_treeify(left)?; }
|
if left_associative {
|
||||||
|
next = g_inner.remove(i-1).unwrap();
|
||||||
|
} else {
|
||||||
|
next = g_inner.remove(i).unwrap();
|
||||||
|
}
|
||||||
|
if let Token::PreGroup(_, _) = next { next = p_treeify(next)?; }
|
||||||
|
|
||||||
let k = match this {
|
let k = match this {
|
||||||
Token::PreOperator(_, k) => k,
|
Token::PreOperator(_, k) => k,
|
||||||
|
@ -310,17 +232,19 @@ fn treeify_unaryright(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3);
|
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3);
|
||||||
new_token_args.push_back(left);
|
new_token_args.push_back(next);
|
||||||
|
|
||||||
g_inner.insert(i-1, select_op(k, new_token_args));
|
if left_associative {
|
||||||
|
g_inner.insert(i-1, k.into_token(new_token_args));
|
||||||
|
} else {
|
||||||
|
g_inner.insert(i, k.into_token(new_token_args));
|
||||||
|
}
|
||||||
|
|
||||||
if i > 2 { i -= 2; } else { i = 0; }
|
return Ok(());
|
||||||
return Ok(i);
|
|
||||||
} else {
|
} else {
|
||||||
// The operator to the right has higher precedence.
|
// The operator to the right has higher precedence.
|
||||||
// Move on, don't to anything yet.
|
// Move on, don't to anything yet.
|
||||||
i += 1;
|
return Ok(());
|
||||||
return Ok(i);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -334,37 +258,52 @@ pub fn p_treeify(
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut i: usize = 0;
|
let mut left_associative = true;
|
||||||
|
let mut j: i64 = 0;
|
||||||
while g_inner.len() > 1 {
|
while g_inner.len() > 1 {
|
||||||
|
|
||||||
|
|
||||||
|
if j <= -1 {
|
||||||
|
left_associative = true;
|
||||||
|
j = 0;
|
||||||
|
} else if j >= g_inner.len() as i64 {
|
||||||
|
left_associative = false;
|
||||||
|
j = (g_inner.len() - 1) as i64;
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = j as usize;
|
||||||
let this_op = match &g_inner[i] {
|
let this_op = match &g_inner[i] {
|
||||||
Token::PreOperator(_, o) => o,
|
Token::PreOperator(_, o) => o,
|
||||||
_ => { i+=1; continue; }
|
_ => {
|
||||||
|
if left_associative { j += 1 } else { j -= 1 };
|
||||||
|
continue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match this_op {
|
if left_associative {
|
||||||
Operator::ModuloLong |
|
if this_op.is_left_associative() {
|
||||||
Operator::Subtract |
|
if this_op.is_binary() {
|
||||||
Operator::Add |
|
treeify_binary(i, g_inner, left_associative)?;
|
||||||
Operator::Divide |
|
} else {
|
||||||
Operator::Multiply |
|
treeify_unary(i, g_inner, left_associative)?;
|
||||||
Operator::ImplicitMultiply |
|
}
|
||||||
Operator::Modulo |
|
}
|
||||||
Operator::Power
|
j += 1
|
||||||
=> { i = treeify_binary(i, g_inner)?; },
|
} else {
|
||||||
|
if !this_op.is_left_associative() {
|
||||||
Operator::Negative
|
if this_op.is_binary() {
|
||||||
=> { i = treeify_unaryleft(i, g_inner)?; },
|
treeify_binary(i, g_inner, left_associative)?;
|
||||||
|
} else {
|
||||||
Operator::Factorial
|
treeify_unary(i, g_inner, left_associative)?;
|
||||||
=> { i = treeify_unaryright(i, g_inner)?; }
|
}
|
||||||
|
}
|
||||||
};
|
j -= 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g = g_inner.pop_front().unwrap();
|
g = g_inner.pop_front().unwrap();
|
||||||
|
|
||||||
// Catch the edge case where the entire group we're given
|
// Catch edge cases
|
||||||
// consists of one operator. This is always a syntax error.
|
|
||||||
match g {
|
match g {
|
||||||
Token::PreOperator(l, _) => {
|
Token::PreOperator(l, _) => {
|
||||||
return Err((l, ParserError::Syntax));
|
return Err((l, ParserError::Syntax));
|
||||||
|
|
Loading…
Reference in New Issue