Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: replace unreachable!() with a bug report #28

Merged
merged 2 commits into from
Jan 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/lexer/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ pub fn tokenize(state: &mut State) -> SyntaxResult<Token> {
kind: TokenKind::Null,
..
} => (TokenKind::FullyQualifiedIdentifier, b"\\null".into()),
s => unreachable!("{:?}", s),
_ => {
crate::lexer_bail!(state, unreachable_code("unexpected token after backslash"))
}
}
}
[b'\\', ..] => {
Expand Down Expand Up @@ -414,7 +416,10 @@ pub fn tokenize(state: &mut State) -> SyntaxResult<Token> {
(kind, buffer.into())
}
}
[] => unreachable!(),
[] => crate::lexer_bail!(
state,
unreachable_code("reached end of input without tokenizing anything")
),
};

Ok(Token {
Expand Down
13 changes: 13 additions & 0 deletions src/lexer/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use crate::lexer::state::State;
#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum LexerIssueCode {
/// An unreachable code was encountered.
UnreachableCode = 0,

/// An unclosed string literal was encountered.
///
/// Example:
Expand Down Expand Up @@ -44,6 +47,16 @@ pub enum LexerIssueCode {
UnrecognizableToken = 4,
}

pub(crate) fn unreachable_code<M: Into<String>>(state: &State, message: M) -> Issue {
let position = state.bytes.position();

Issue::bug(LexerIssueCode::UnreachableCode, message).with_source(
state.source.name(),
position,
position + 1,
)
}

pub(crate) fn unclosed_string_literal(state: &State, from: usize) -> Issue {
Issue::error(
LexerIssueCode::UnclosedStringLiteral,
Expand Down
7 changes: 6 additions & 1 deletion src/parser/internal/definition/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ fn concrete_method_definition(
Ok(Some(method))
}
MethodDefinitionReference::Abstract(_)
| MethodDefinitionReference::AbstractConstructor(_) => unreachable!(),
| MethodDefinitionReference::AbstractConstructor(_) => {
crate::parser_bail!(
state,
unreachable_code("unexpected abstract method in enum definition")
)
}
}
}
7 changes: 6 additions & 1 deletion src/parser/internal/definition/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ fn interface_definition_member(
Ok(InterfaceDefinitionMember::Constructor(ctor))
}
MethodDefinitionReference::ConcreteConstructor(_)
| MethodDefinitionReference::Concrete(_) => unreachable!(),
| MethodDefinitionReference::Concrete(_) => {
crate::parser_bail!(
state,
unreachable_code("unexpected concrete method in interface definition")
)
}
}
}
}
5 changes: 4 additions & 1 deletion src/parser/internal/expression/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ fn anonymous_class_expression_member(
return Ok(AnonymousClassExpressionMember::ConcreteConstructor(ctor));
}
MethodDefinitionReference::Abstract(_)
| MethodDefinitionReference::AbstractConstructor(_) => unreachable!(),
| MethodDefinitionReference::AbstractConstructor(_) => crate::parser_bail!(
state,
unreachable_code("unexpected abstract method in anonymous class")
),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/parser/internal/expression/infix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ pub fn infix(
dot: position,
right,
}),
_ => unreachable!(),
_ => crate::parser_bail!(state, unreachable_code("unexpected operator")),
}
}
})
Expand Down
6 changes: 3 additions & 3 deletions src/parser/internal/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn for_precedence(state: &mut State, precedence: Precedence) -> ParseResult<
}

if postfix::is_postfix(kind) {
let left_precedence = Precedence::postfix(kind);
let left_precedence = Precedence::postfix(state, kind)?;

if left_precedence < precedence {
break;
Expand All @@ -74,7 +74,7 @@ pub fn for_precedence(state: &mut State, precedence: Precedence) -> ParseResult<
}

if infix::is_infix(state, kind) {
let right_precedence = Precedence::infix(kind);
let right_precedence = Precedence::infix(state, kind)?;

if right_precedence < precedence {
break;
Expand Down Expand Up @@ -677,7 +677,7 @@ expressions! {
increment: position,
right: Box::new(for_precedence(state, Precedence::Prefix)?)
}),
_ => unreachable!(),
_ => crate::parser_bail!(state, unreachable_code("unexpected operator"))
};

Ok(expr)
Expand Down
2 changes: 1 addition & 1 deletion src/parser/internal/expression/postfix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ pub fn postfix(state: &mut State, left: Expression, kind: &TokenKind) -> ParseRe
decrement: position,
})
}
_ => unreachable!(),
_ => crate::parser_bail!(state, unreachable_code("unexpected operation")),
})
}

Expand Down
62 changes: 35 additions & 27 deletions src/parser/internal/expression/precedence.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::lexer::token::TokenKind;
use crate::parser::result::ParseResult;
use crate::parser::state::State;

pub enum Associativity {
Non,
Expand Down Expand Up @@ -40,46 +42,52 @@ pub enum Precedence {
}

impl Precedence {
pub fn infix(kind: &TokenKind) -> Self {
pub fn infix(state: &mut State, kind: &TokenKind) -> ParseResult<Self> {
use TokenKind::*;

match kind {
Pow => Self::Pow,
Instanceof | Is | As | Into => Self::TypeCheck,
In => Self::ArrayContains,
Asterisk | Slash | Percent => Self::MulDivMod,
Plus | Minus => Self::AddSub,
LeftShift | RightShift => Self::BitShift,
Dot => Self::Concat,
LessThan | LessThanEquals | GreaterThan | GreaterThanEquals => Self::LtGt,
Pow => Ok(Self::Pow),
Instanceof | Is | As | Into => Ok(Self::TypeCheck),
In => Ok(Self::ArrayContains),
Asterisk | Slash | Percent => Ok(Self::MulDivMod),
Plus | Minus => Ok(Self::AddSub),
LeftShift | RightShift => Ok(Self::BitShift),
Dot => Ok(Self::Concat),
LessThan | LessThanEquals | GreaterThan | GreaterThanEquals => Ok(Self::LtGt),
DoubleEquals | BangEquals | TripleEquals | BangDoubleEquals | Spaceship => {
Self::Equality
Ok(Self::Equality)
}
Ampersand => Self::BitwiseAnd,
Caret => Self::BitwiseXor,
Pipe => Self::BitwiseOr,
BooleanAnd => Self::And,
BooleanOr => Self::Or,
DoubleQuestion => Self::NullCoalesce,
Question | QuestionColon => Self::Ternary,
Ampersand => Ok(Self::BitwiseAnd),
Caret => Ok(Self::BitwiseXor),
Pipe => Ok(Self::BitwiseOr),
BooleanAnd => Ok(Self::And),
BooleanOr => Ok(Self::Or),
DoubleQuestion => Ok(Self::NullCoalesce),
Question | QuestionColon => Ok(Self::Ternary),
Equals | PlusEquals | MinusEquals | AsteriskEquals | PowEquals | SlashEquals
| DotEquals | AndEquals | DoubleQuestionEquals | PercentEquals | AmpersandEquals
| PipeEquals | CaretEquals | LeftShiftEquals | RightShiftEquals => Self::Assignment,
Yield => Self::Yield,
DoubleDot => Self::Range,
_ => unreachable!("precedence for op {:?}", kind),
| PipeEquals | CaretEquals | LeftShiftEquals | RightShiftEquals => Ok(Self::Assignment),
Yield => Ok(Self::Yield),
DoubleDot => Ok(Self::Range),
_ => crate::parser_bail!(
state,
unreachable_code(format!("unexpected precedence for operator {:?}", kind))
),
}
}

pub fn postfix(kind: &TokenKind) -> Self {
pub fn postfix(state: &mut State, kind: &TokenKind) -> ParseResult<Self> {
use TokenKind::*;

match kind {
DoubleQuestion => Self::NullCoalesce,
Increment | Decrement => Self::IncDec,
LeftParen | Generic | LeftBracket => Self::CallDim,
Arrow | QuestionArrow | DoubleColon => Self::ObjectAccess,
_ => unreachable!("postfix precedence for op {:?}", kind),
DoubleQuestion => Ok(Self::NullCoalesce),
Increment | Decrement => Ok(Self::IncDec),
LeftParen | Generic | LeftBracket => Ok(Self::CallDim),
Arrow | QuestionArrow | DoubleColon => Ok(Self::ObjectAccess),
_ => crate::parser_bail!(
state,
unreachable_code(format!("unexpected precedence for operator {:?}", kind))
),
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/parser/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ use crate::tree::Node;
#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum ParserIssueCode {
/// An unreachable code was encountered.
UnreachableCode = 0,

/// PHP opening tag is not supported ( code = 1 )
///
/// Example:
Expand Down Expand Up @@ -703,6 +706,16 @@ pub enum ParserIssueCode {
LiteralTypeCannotBeUsedInIntersection = 47,
}

pub(crate) fn unreachable_code<M: Into<String>>(state: &ParserState, message: M) -> Issue {
let token = state.iterator.current();

Issue::bug(ParserIssueCode::UnreachableCode, message).with_source(
state.source.name(),
token.position,
token.position + token.value.len(),
)
}

pub(crate) fn php_opening_tag_not_supported(state: &ParserState, token: &Token) -> Issue {
Issue::error(
ParserIssueCode::PHPOpeningTagNotSupported,
Expand Down