cl-parser: General cleanup and maintenance
- Made infallible rules infallible - Don't double-check keywords where keywords are required. - Of course, this change means rules aren't self-contained - Rename the `Call` precedence level - Made member-access operators left-associative - Removed the useless `Nothing` error type. :(
This commit is contained in:
parent
f315fb5af7
commit
a56ee38b15
@ -29,8 +29,6 @@ pub enum ErrorKind {
|
|||||||
ExpectedParsing {
|
ExpectedParsing {
|
||||||
want: Parsing,
|
want: Parsing,
|
||||||
},
|
},
|
||||||
/// No rules matched
|
|
||||||
Nothing,
|
|
||||||
/// Indicates unfinished code
|
/// Indicates unfinished code
|
||||||
Todo,
|
Todo,
|
||||||
}
|
}
|
||||||
@ -134,13 +132,8 @@ impl Display for ErrorKind {
|
|||||||
ErrorKind::UnmatchedCurlyBraces => write!(f, "Unmatched curly braces"),
|
ErrorKind::UnmatchedCurlyBraces => write!(f, "Unmatched curly braces"),
|
||||||
ErrorKind::UnmatchedSquareBrackets => write!(f, "Unmatched square brackets"),
|
ErrorKind::UnmatchedSquareBrackets => write!(f, "Unmatched square brackets"),
|
||||||
ErrorKind::Unexpected(t) => write!(f, "Encountered unexpected token `{t}`"),
|
ErrorKind::Unexpected(t) => write!(f, "Encountered unexpected token `{t}`"),
|
||||||
ErrorKind::ExpectedToken { want: e, got: g } => {
|
ErrorKind::ExpectedToken { want: e, got: g } => write!(f, "Expected `{e}`, got `{g}`"),
|
||||||
write!(f, "Expected `{e}`, got `{g}`")
|
ErrorKind::ExpectedParsing { want } => write!(f, "Expected {want}"),
|
||||||
}
|
|
||||||
ErrorKind::ExpectedParsing { want } => {
|
|
||||||
write!(f, "Expected {want}")
|
|
||||||
}
|
|
||||||
ErrorKind::Nothing => write!(f, "Nothing found"),
|
|
||||||
ErrorKind::Todo => write!(f, "TODO:"),
|
ErrorKind::Todo => write!(f, "TODO:"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,6 @@ const fn sep<'t, T>(
|
|||||||
/// Parses constructions of the form `(f ~until)*`
|
/// Parses constructions of the form `(f ~until)*`
|
||||||
///
|
///
|
||||||
/// where `~until` is a negative lookahead assertion
|
/// where `~until` is a negative lookahead assertion
|
||||||
#[allow(dead_code)]
|
|
||||||
const fn rep<'t, T>(
|
const fn rep<'t, T>(
|
||||||
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
|
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
|
||||||
until: Punct,
|
until: Punct,
|
||||||
@ -187,7 +186,7 @@ impl<'t> Parser<'t> {
|
|||||||
let start = self.loc();
|
let start = self.loc();
|
||||||
Ok(Item {
|
Ok(Item {
|
||||||
attrs: self.attributes()?,
|
attrs: self.attributes()?,
|
||||||
vis: self.visibility()?,
|
vis: self.visibility(),
|
||||||
kind: self.itemkind()?,
|
kind: self.itemkind()?,
|
||||||
extents: Span(start, self.loc()),
|
extents: Span(start, self.loc()),
|
||||||
})
|
})
|
||||||
@ -204,21 +203,20 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [Path]
|
/// Parses a [Path]
|
||||||
///
|
///
|
||||||
/// See also: [Parser::path_part], [Parser::identifier]
|
/// See also: [Parser::path_part], [Parser::identifier]
|
||||||
|
///
|
||||||
|
/// [Path] = `::`? ([PathPart] `::`)* [PathPart]?
|
||||||
pub fn path(&mut self) -> PResult<Path> {
|
pub fn path(&mut self) -> PResult<Path> {
|
||||||
const PARSING: Parsing = Parsing::PathExpr;
|
const PARSING: Parsing = Parsing::PathExpr;
|
||||||
let absolute = matches!(
|
let absolute = self.match_op(Punct::ColonColon, PARSING).is_ok();
|
||||||
self.peek_kind(PARSING)?,
|
let mut parts = vec![];
|
||||||
TokenKind::Punct(Punct::ColonColon)
|
|
||||||
);
|
while let Ok(path_part) = self.path_part() {
|
||||||
if absolute {
|
parts.push(path_part);
|
||||||
self.consume_peeked();
|
if self.match_op(Punct::ColonColon, PARSING).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut parts = vec![self.path_part()?];
|
|
||||||
while let Ok(TokenKind::Punct(Punct::ColonColon)) = self.peek_kind(PARSING) {
|
|
||||||
self.consume_peeked();
|
|
||||||
parts.push(self.path_part()?);
|
|
||||||
}
|
|
||||||
Ok(Path { absolute, parts })
|
Ok(Path { absolute, parts })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,15 +224,11 @@ impl<'t> Parser<'t> {
|
|||||||
///
|
///
|
||||||
/// See also: [Parser::stmtkind]
|
/// See also: [Parser::stmtkind]
|
||||||
pub fn stmt(&mut self) -> PResult<Stmt> {
|
pub fn stmt(&mut self) -> PResult<Stmt> {
|
||||||
const PARSING: Parsing = Parsing::Stmt;
|
|
||||||
let start = self.loc();
|
let start = self.loc();
|
||||||
Ok(Stmt {
|
Ok(Stmt {
|
||||||
kind: self.stmtkind()?,
|
kind: self.stmtkind()?,
|
||||||
semi: match self.peek_kind(PARSING) {
|
semi: match self.match_op(Punct::Semi, Parsing::Stmt) {
|
||||||
Ok(TokenKind::Punct(Punct::Semi)) => {
|
Ok(_) => Semi::Terminated,
|
||||||
self.consume_peeked();
|
|
||||||
Semi::Terminated
|
|
||||||
}
|
|
||||||
_ => Semi::Unterminated,
|
_ => Semi::Unterminated,
|
||||||
},
|
},
|
||||||
extents: Span(start, self.loc()),
|
extents: Span(start, self.loc()),
|
||||||
@ -260,8 +254,8 @@ impl<'t> Parser<'t> {
|
|||||||
sep(Self::meta, Punct::Comma, BRACKETS.1, Parsing::Attrs),
|
sep(Self::meta, Punct::Comma, BRACKETS.1, Parsing::Attrs),
|
||||||
BRACKETS,
|
BRACKETS,
|
||||||
Parsing::Attrs,
|
Parsing::Attrs,
|
||||||
);
|
)(self)?;
|
||||||
Ok(Attrs { meta: meta(self)? })
|
Ok(Attrs { meta })
|
||||||
}
|
}
|
||||||
/// Parses a single [attribute](Meta)
|
/// Parses a single [attribute](Meta)
|
||||||
pub fn meta(&mut self) -> PResult<Meta> {
|
pub fn meta(&mut self) -> PResult<Meta> {
|
||||||
@ -308,7 +302,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [`type` alias](Alias)
|
/// Parses a [`type` alias](Alias)
|
||||||
pub fn parse_alias(&mut self) -> PResult<Alias> {
|
pub fn parse_alias(&mut self) -> PResult<Alias> {
|
||||||
const PARSING: Parsing = Parsing::Alias;
|
const PARSING: Parsing = Parsing::Alias;
|
||||||
self.match_type(TokenKind::Type, PARSING)?;
|
self.consume_peeked();
|
||||||
|
|
||||||
let out = Ok(Alias {
|
let out = Ok(Alias {
|
||||||
to: self.identifier()?,
|
to: self.identifier()?,
|
||||||
@ -325,7 +319,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [compile-time constant](Const)
|
/// Parses a [compile-time constant](Const)
|
||||||
pub fn parse_const(&mut self) -> PResult<Const> {
|
pub fn parse_const(&mut self) -> PResult<Const> {
|
||||||
const PARSING: Parsing = Parsing::Const;
|
const PARSING: Parsing = Parsing::Const;
|
||||||
self.match_type(TokenKind::Const, PARSING)?;
|
self.consume_peeked();
|
||||||
|
|
||||||
let out = Ok(Const {
|
let out = Ok(Const {
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
@ -345,10 +339,10 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [`static` item](Static)
|
/// Parses a [`static` item](Static)
|
||||||
pub fn parse_static(&mut self) -> PResult<Static> {
|
pub fn parse_static(&mut self) -> PResult<Static> {
|
||||||
const PARSING: Parsing = Parsing::Static;
|
const PARSING: Parsing = Parsing::Static;
|
||||||
self.match_type(TokenKind::Static, PARSING)?;
|
self.consume_peeked();
|
||||||
|
|
||||||
let out = Ok(Static {
|
let out = Ok(Static {
|
||||||
mutable: self.mutability()?,
|
mutable: self.mutability(),
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
ty: {
|
ty: {
|
||||||
self.match_op(Punct::Colon, PARSING)?;
|
self.match_op(Punct::Colon, PARSING)?;
|
||||||
@ -365,8 +359,7 @@ impl<'t> Parser<'t> {
|
|||||||
|
|
||||||
/// Parses a [Module]
|
/// Parses a [Module]
|
||||||
pub fn parse_module(&mut self) -> PResult<Module> {
|
pub fn parse_module(&mut self) -> PResult<Module> {
|
||||||
const PARSING: Parsing = Parsing::Module;
|
self.consume_peeked();
|
||||||
self.match_type(TokenKind::Mod, PARSING)?;
|
|
||||||
|
|
||||||
Ok(Module { name: self.identifier()?, kind: self.modulekind()? })
|
Ok(Module { name: self.identifier()?, kind: self.modulekind()? })
|
||||||
}
|
}
|
||||||
@ -392,7 +385,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [Function] definition
|
/// Parses a [Function] definition
|
||||||
pub fn parse_function(&mut self) -> PResult<Function> {
|
pub fn parse_function(&mut self) -> PResult<Function> {
|
||||||
const PARSING: Parsing = Parsing::Function;
|
const PARSING: Parsing = Parsing::Function;
|
||||||
self.match_type(TokenKind::Fn, PARSING)?;
|
self.consume_peeked();
|
||||||
|
|
||||||
let name = self.identifier()?;
|
let name = self.identifier()?;
|
||||||
let (bind, types) = delim(Self::parse_params, PARENS, PARSING)(self)?;
|
let (bind, types) = delim(Self::parse_params, PARENS, PARSING)(self)?;
|
||||||
@ -436,7 +429,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a single function [parameter](Param)
|
/// Parses a single function [parameter](Param)
|
||||||
pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> {
|
pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> {
|
||||||
Ok((
|
Ok((
|
||||||
Param { mutability: self.mutability()?, name: self.identifier()? },
|
Param { mutability: self.mutability(), name: self.identifier()? },
|
||||||
{
|
{
|
||||||
self.match_op(Punct::Colon, Parsing::Param)?;
|
self.match_op(Punct::Colon, Parsing::Param)?;
|
||||||
self.tykind()?
|
self.tykind()?
|
||||||
@ -447,7 +440,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses a [`struct` definition](Struct)
|
/// Parses a [`struct` definition](Struct)
|
||||||
pub fn parse_struct(&mut self) -> PResult<Struct> {
|
pub fn parse_struct(&mut self) -> PResult<Struct> {
|
||||||
const PARSING: Parsing = Parsing::Struct;
|
const PARSING: Parsing = Parsing::Struct;
|
||||||
self.match_type(TokenKind::Struct, PARSING)?;
|
self.consume_peeked();
|
||||||
|
|
||||||
Ok(Struct {
|
Ok(Struct {
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
@ -492,7 +485,7 @@ impl<'t> Parser<'t> {
|
|||||||
pub fn struct_member(&mut self) -> PResult<StructMember> {
|
pub fn struct_member(&mut self) -> PResult<StructMember> {
|
||||||
const PARSING: Parsing = Parsing::StructMember;
|
const PARSING: Parsing = Parsing::StructMember;
|
||||||
Ok(StructMember {
|
Ok(StructMember {
|
||||||
vis: self.visibility()?,
|
vis: self.visibility(),
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
ty: {
|
ty: {
|
||||||
self.match_op(Punct::Colon, PARSING)?;
|
self.match_op(Punct::Colon, PARSING)?;
|
||||||
@ -504,8 +497,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// Parses an [`enum`](Enum) definition
|
/// Parses an [`enum`](Enum) definition
|
||||||
pub fn parse_enum(&mut self) -> PResult<Enum> {
|
pub fn parse_enum(&mut self) -> PResult<Enum> {
|
||||||
const PARSING: Parsing = Parsing::Enum;
|
const PARSING: Parsing = Parsing::Enum;
|
||||||
|
self.consume_peeked();
|
||||||
self.match_type(TokenKind::Enum, PARSING)?;
|
|
||||||
|
|
||||||
Ok(Enum {
|
Ok(Enum {
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
@ -578,8 +570,7 @@ impl<'t> Parser<'t> {
|
|||||||
|
|
||||||
pub fn parse_impl(&mut self) -> PResult<Impl> {
|
pub fn parse_impl(&mut self) -> PResult<Impl> {
|
||||||
const PARSING: Parsing = Parsing::Impl;
|
const PARSING: Parsing = Parsing::Impl;
|
||||||
|
self.consume_peeked();
|
||||||
self.match_type(TokenKind::Impl, PARSING)?;
|
|
||||||
|
|
||||||
Ok(Impl {
|
Ok(Impl {
|
||||||
target: self.parse_impl_kind()?,
|
target: self.parse_impl_kind()?,
|
||||||
@ -605,19 +596,19 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visibility(&mut self) -> PResult<Visibility> {
|
/// [Visibility] = `pub`?
|
||||||
if let TokenKind::Pub = self.peek_kind(Parsing::Visibility)? {
|
pub fn visibility(&mut self) -> Visibility {
|
||||||
self.consume_peeked();
|
match self.match_type(TokenKind::Pub, Parsing::Visibility) {
|
||||||
return Ok(Visibility::Public);
|
Ok(_) => Visibility::Public,
|
||||||
};
|
Err(_) => Visibility::Private,
|
||||||
Ok(Visibility::Private)
|
}
|
||||||
}
|
}
|
||||||
pub fn mutability(&mut self) -> PResult<Mutability> {
|
/// [Mutability] = `mut`?
|
||||||
if let TokenKind::Mut = self.peek_kind(Parsing::Mutability)? {
|
pub fn mutability(&mut self) -> Mutability {
|
||||||
self.consume_peeked();
|
match self.match_type(TokenKind::Mut, Parsing::Mutability) {
|
||||||
return Ok(Mutability::Mut);
|
Ok(_) => Mutability::Mut,
|
||||||
};
|
Err(_) => Mutability::Not,
|
||||||
Ok(Mutability::Not)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +666,7 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
}
|
}
|
||||||
Ok(TyRef { count, mutable: self.mutability()?, to: self.path()? })
|
Ok(TyRef { count, mutable: self.mutability(), to: self.path()? })
|
||||||
}
|
}
|
||||||
/// [TyFn] = `fn` [TyTuple] (-> [Ty])?
|
/// [TyFn] = `fn` [TyTuple] (-> [Ty])?
|
||||||
pub fn tyfn(&mut self) -> PResult<TyFn> {
|
pub fn tyfn(&mut self) -> PResult<TyFn> {
|
||||||
@ -726,6 +717,7 @@ impl<'t> Parser<'t> {
|
|||||||
TokenKind::Identifier => PathPart::Ident(self.identifier()?),
|
TokenKind::Identifier => PathPart::Ident(self.identifier()?),
|
||||||
t => return Err(self.error(Unexpected(t), PARSING)),
|
t => return Err(self.error(Unexpected(t), PARSING)),
|
||||||
};
|
};
|
||||||
|
// Note: this relies on identifier not peeking
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
@ -754,9 +746,9 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_let(&mut self) -> PResult<Let> {
|
pub fn parse_let(&mut self) -> PResult<Let> {
|
||||||
self.match_type(TokenKind::Let, Parsing::Let)?;
|
self.consume_peeked();
|
||||||
Ok(Let {
|
Ok(Let {
|
||||||
mutable: self.mutability()?,
|
mutable: self.mutability(),
|
||||||
name: self.identifier()?,
|
name: self.identifier()?,
|
||||||
ty: if Ok(TokenKind::Punct(Punct::Colon)) == self.peek_kind(Parsing::Let) {
|
ty: if Ok(TokenKind::Punct(Punct::Colon)) == self.peek_kind(Parsing::Let) {
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
@ -787,7 +779,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// See also: [Parser::expr]
|
/// See also: [Parser::expr]
|
||||||
pub fn exprkind(&mut self, power: u8) -> PResult<ExprKind> {
|
pub fn exprkind(&mut self, power: u8) -> PResult<ExprKind> {
|
||||||
let parsing = Parsing::ExprKind;
|
let parsing = Parsing::ExprKind;
|
||||||
//
|
// Prefix expressions
|
||||||
let mut head = match self.peek_kind(Parsing::Unary)? {
|
let mut head = match self.peek_kind(Parsing::Unary)? {
|
||||||
literal_like!() => self.literal()?.into(),
|
literal_like!() => self.literal()?.into(),
|
||||||
path_like!() => self.path()?.into(),
|
path_like!() => self.path()?.into(),
|
||||||
@ -821,12 +813,13 @@ impl<'t> Parser<'t> {
|
|||||||
fn from_postfix(op: Punct) -> Option<Precedence> {
|
fn from_postfix(op: Punct) -> Option<Precedence> {
|
||||||
Some(match op {
|
Some(match op {
|
||||||
Punct::LBrack => Precedence::Index,
|
Punct::LBrack => Precedence::Index,
|
||||||
Punct::LParen => Precedence::Postfix,
|
Punct::LParen => Precedence::Call,
|
||||||
_ => None?,
|
_ => None?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Ok(TokenKind::Punct(op)) = self.peek_kind(parsing) {
|
while let Ok(TokenKind::Punct(op)) = self.peek_kind(parsing) {
|
||||||
|
// Postfix expressions
|
||||||
if let Some((before, ())) = from_postfix(op).and_then(Precedence::postfix) {
|
if let Some((before, ())) = from_postfix(op).and_then(Precedence::postfix) {
|
||||||
if before < power {
|
if before < power {
|
||||||
break;
|
break;
|
||||||
@ -974,7 +967,7 @@ impl<'t> Parser<'t> {
|
|||||||
};
|
};
|
||||||
self.consume_peeked();
|
self.consume_peeked();
|
||||||
}
|
}
|
||||||
Ok(AddrOf { count, mutable: self.mutability()?, expr: self.exprkind(0)?.into() })
|
Ok(AddrOf { count, mutable: self.mutability(), expr: self.exprkind(0)?.into() })
|
||||||
}
|
}
|
||||||
/// [Literal] = [LITERAL](TokenKind::Literal) | `true` | `false`
|
/// [Literal] = [LITERAL](TokenKind::Literal) | `true` | `false`
|
||||||
pub fn literal(&mut self) -> PResult<Literal> {
|
pub fn literal(&mut self) -> PResult<Literal> {
|
||||||
@ -1021,7 +1014,7 @@ impl<'t> Parser<'t> {
|
|||||||
|
|
||||||
/// [While] = `while` [Expr] [Block] [Else]?
|
/// [While] = `while` [Expr] [Block] [Else]?
|
||||||
pub fn parse_while(&mut self) -> PResult<While> {
|
pub fn parse_while(&mut self) -> PResult<While> {
|
||||||
self.match_type(TokenKind::While, Parsing::While)?;
|
self.consume_peeked();
|
||||||
Ok(While {
|
Ok(While {
|
||||||
cond: self.expr()?.into(),
|
cond: self.expr()?.into(),
|
||||||
pass: self.block()?.into(),
|
pass: self.block()?.into(),
|
||||||
@ -1031,7 +1024,7 @@ impl<'t> Parser<'t> {
|
|||||||
/// [If] = <code>`if` [Expr] [Block] [Else]?</code>
|
/// [If] = <code>`if` [Expr] [Block] [Else]?</code>
|
||||||
#[rustfmt::skip] // second line is barely not long enough
|
#[rustfmt::skip] // second line is barely not long enough
|
||||||
pub fn parse_if(&mut self) -> PResult<If> {
|
pub fn parse_if(&mut self) -> PResult<If> {
|
||||||
self.match_type(TokenKind::If, Parsing::If)?;
|
self.consume_peeked();
|
||||||
Ok(If {
|
Ok(If {
|
||||||
cond: self.expr()?.into(),
|
cond: self.expr()?.into(),
|
||||||
pass: self.block()?.into(),
|
pass: self.block()?.into(),
|
||||||
@ -1040,7 +1033,7 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
/// [For]: `for` Pattern (TODO) `in` [Expr] [Block] [Else]?
|
/// [For]: `for` Pattern (TODO) `in` [Expr] [Block] [Else]?
|
||||||
pub fn parse_for(&mut self) -> PResult<For> {
|
pub fn parse_for(&mut self) -> PResult<For> {
|
||||||
self.match_type(TokenKind::For, Parsing::For)?;
|
self.consume_peeked();
|
||||||
let bind = self.identifier()?;
|
let bind = self.identifier()?;
|
||||||
self.match_type(TokenKind::In, Parsing::For)?;
|
self.match_type(TokenKind::In, Parsing::For)?;
|
||||||
Ok(For {
|
Ok(For {
|
||||||
@ -1076,8 +1069,8 @@ pub enum Precedence {
|
|||||||
Factor,
|
Factor,
|
||||||
Term,
|
Term,
|
||||||
Unary,
|
Unary,
|
||||||
Postfix,
|
|
||||||
Member, // left-associative
|
Member, // left-associative
|
||||||
|
Call,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Precedence {
|
impl Precedence {
|
||||||
@ -1095,13 +1088,13 @@ impl Precedence {
|
|||||||
let level = self.level();
|
let level = self.level();
|
||||||
match self {
|
match self {
|
||||||
Self::Unary => None,
|
Self::Unary => None,
|
||||||
Self::Member | Self::Assign => Some((level + 1, level)),
|
Self::Assign => Some((level + 1, level)),
|
||||||
_ => Some((level, level + 1)),
|
_ => Some((level, level + 1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn postfix(self) -> Option<(u8, ())> {
|
pub fn postfix(self) -> Option<(u8, ())> {
|
||||||
match self {
|
match self {
|
||||||
Self::Index | Self::Postfix => Some((self.level(), ())),
|
Self::Index | Self::Call => Some((self.level(), ())),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1116,7 +1109,7 @@ impl From<BinaryKind> for Precedence {
|
|||||||
fn from(value: BinaryKind) -> Self {
|
fn from(value: BinaryKind) -> Self {
|
||||||
use BinaryKind as Op;
|
use BinaryKind as Op;
|
||||||
match value {
|
match value {
|
||||||
Op::Call => Precedence::Postfix,
|
Op::Call => Precedence::Call,
|
||||||
Op::Dot => Precedence::Member,
|
Op::Dot => Precedence::Member,
|
||||||
Op::Mul | Op::Div | Op::Rem => Precedence::Term,
|
Op::Mul | Op::Div | Op::Rem => Precedence::Term,
|
||||||
Op::Add | Op::Sub => Precedence::Factor,
|
Op::Add | Op::Sub => Precedence::Factor,
|
||||||
|
Loading…
Reference in New Issue
Block a user