From 1339b55ac7b3bb84198ddd186a972cb5e152738d Mon Sep 17 00:00:00 2001 From: Kisaragi Marine Date: Thu, 21 Dec 2023 18:35:35 +0900 Subject: [PATCH] refactor(parser): split file --- package/origlang-cli/src/error.rs | 2 +- package/origlang-cli/src/task/emit.rs | 5 +- package/origlang-cli/src/task/repl.rs | 5 +- .../origlang-compiler-entrypoint/src/lib.rs | 5 +- package/origlang-compiler/src/parser.rs | 110 +----------------- package/origlang-compiler/src/parser/error.rs | 88 ++++++++++++++ .../origlang-compiler/src/parser/recover.rs | 22 ++++ package/origlang-interop/src/lib.rs | 3 +- package/origlang-testsuite/src/main.rs | 6 +- 9 files changed, 131 insertions(+), 115 deletions(-) create mode 100644 package/origlang-compiler/src/parser/error.rs create mode 100644 package/origlang-compiler/src/parser/recover.rs diff --git a/package/origlang-cli/src/error.rs b/package/origlang-cli/src/error.rs index b084331f..f7f5ba56 100644 --- a/package/origlang-cli/src/error.rs +++ b/package/origlang-cli/src/error.rs @@ -1,5 +1,5 @@ use thiserror::Error; -use origlang_compiler::parser::ParserError; +use origlang_compiler::parser::error::ParserError; use origlang_compiler::type_check::error::TypeCheckError; use origlang_runtime::RuntimeError; use crate::args::ReadSourceError; diff --git a/package/origlang-cli/src/task/emit.rs b/package/origlang-cli/src/task/emit.rs index fb649ee9..64669a90 100644 --- a/package/origlang-cli/src/task/emit.rs +++ b/package/origlang-cli/src/task/emit.rs @@ -1,9 +1,10 @@ use thiserror::Error; use origlang_compiler::lexer::Lexer; -use origlang_compiler::parser::{Parser, ParserError}; +use origlang_compiler::parser::Parser; +use origlang_compiler::parser::error::ParserError; use origlang_compiler::type_check::error::TypeCheckError; use origlang_compiler::type_check::TypeChecker; -use origlang_ir::{IR1, IR2, IntoVerbatimSequencedIR}; +use origlang_ir::{IntoVerbatimSequencedIR, IR1, IR2}; use origlang_ir_optimizer::lower::{EachStep, LowerStep, TheTranspiler}; use origlang_ir_optimizer::preset::{NoOptimization, SimpleOptimization}; use crate::args::{EmitPhase, OptimizeLevel, ParseSource, ReadSourceError}; diff --git a/package/origlang-cli/src/task/repl.rs b/package/origlang-cli/src/task/repl.rs index d4b48d7f..c18712ad 100644 --- a/package/origlang-cli/src/task/repl.rs +++ b/package/origlang-cli/src/task/repl.rs @@ -5,8 +5,9 @@ use ariadne::{Report, ReportKind, Source}; use crate::task::Task; use crate::error::TaskExecutionError; use origlang_platform::CTRL_D_NL; -use origlang_compiler::parser::{Parser, ParserErrorInner}; -use origlang_runtime::{PrintToStdout, Runtime, TypeBox}; +use origlang_compiler::parser::Parser; +use origlang_compiler::parser::error::ParserErrorInner; +use origlang_runtime::{PrintToStdout, Runtime}; use origlang_compiler::type_check::TypeChecker; use origlang_ir::{IntoVerbatimSequencedIR, IR2}; use origlang_ir_optimizer::lower::{LowerStep, TheTranspiler}; diff --git a/package/origlang-compiler-entrypoint/src/lib.rs b/package/origlang-compiler-entrypoint/src/lib.rs index d05d5621..91f7a8bf 100644 --- a/package/origlang-compiler-entrypoint/src/lib.rs +++ b/package/origlang-compiler-entrypoint/src/lib.rs @@ -6,8 +6,9 @@ use std::any::type_name; use log::debug; use thiserror::Error; use origlang_ast::Statement; -use origlang_compiler::lexer::token::{Token as LexerToken}; -use origlang_compiler::parser::{Parser, ParserError}; +use origlang_compiler::lexer::token::Token as LexerToken; +use origlang_compiler::parser::Parser; +use origlang_compiler::parser::error::ParserError; use origlang_compiler::type_check::error::TypeCheckError; use origlang_compiler::type_check::TypeChecker; use origlang_diagnostics::{Diagnostic, DiagnosticSink}; diff --git a/package/origlang-compiler/src/parser.rs b/package/origlang-compiler/src/parser.rs index e9926398..9aedf906 100644 --- a/package/origlang-compiler/src/parser.rs +++ b/package/origlang-compiler/src/parser.rs @@ -1,9 +1,6 @@ -use std::fmt::{Display, Formatter}; -use std::num::ParseIntError; use origlang_ast::{AtomicPattern, RootAst, Statement, TypeSignature}; -use origlang_source_span::{SourcePosition as SourcePos, Pointed as WithPosition, Pointed, SourcePosition}; +use origlang_source_span::{Pointed as WithPosition, SourcePosition as SourcePos}; use crate::lexer::Lexer; -use crate::lexer::error::LexerError; use crate::lexer::token::Token; use crate::lexer::token::internal::DisplayToken; @@ -12,108 +9,13 @@ use std::string::ToString; use derive_more::Display; use log::{debug, warn}; use num_traits::Bounded; -use thiserror::{Error as ThisError}; -use crate::parser::ParserErrorInner::EndOfFileError; +use self::error::{ParserError, ParserErrorInner, UnexpectedTupleLiteralElementCount}; +use self::error::ParserErrorInner::EndOfFileError; +use self::recover::PartiallyParseFixCandidate; use crate::parser::TokenKind::IntLiteral; -// TODO: これはWithPositionにできるかもしれないが一旦保留 -#[derive(ThisError, Debug, Eq, PartialEq)] -pub struct ParserError(Pointed); - -impl Display for ParserError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("{} ({})", &self.0.data, &self.0.position)) - } -} - -impl ParserError { - pub fn new(kind: ParserErrorInner, position: SourcePos) -> Self { - Self(Pointed { - data: kind, - position - }) - } - - pub fn kind(&self) -> &ParserErrorInner { - &self.0.data - } - - pub fn position(&self) -> &SourcePosition { - &self.0.position - } -} - -#[derive(ThisError, Debug, Eq, PartialEq)] -#[allow(clippy::module_name_repetitions)] -pub enum ParserErrorInner { - #[error("lexer error: {_0}")] - LexerError(#[from] LexerError), - #[error("unconsumed token found: {token:?}")] - UnconsumedToken { - token: Token - }, - #[error("statement must be terminated by a newline")] - StatementTerminationError, - #[error("EOF Error")] - EndOfFileError, - #[error("Expected {pat}, but got {unmatch:?}")] - UnexpectedToken { - pat: TokenKind, - unmatch: Token, - }, - #[error("Incomplete program snippet. Check hint for fix candidates. hint:{hint:?} state:{intermediate_state:?}")] - PartiallyParsed { - hint: Vec, - intermediate_state: Vec, - }, - #[error("input sequence cannot be parsed as a int literal: {error}")] - UnParsableIntLiteral { - error: ParseIntError - }, - #[error("int literal type of {tp} must be in range ({min}..={max}), but its value is {value}")] - OverflowedLiteral { - tp: Box, - min: i64, - max: i64, - value: i64, - }, - #[error("if expression requires `else` clause")] - IfExpressionWithoutElseClause, - #[error("if expression requires `then` clause and `else` clause")] - IfExpressionWithoutThenClauseAndElseClause, - #[error("tuple literal requires 2 or more elements, but got {_0}")] - InsufficientElementsForTupleLiteral(UnexpectedTupleLiteralElementCount), - #[error("`_` cannot used as right hand side expression")] - UnderscoreCanNotBeRightHandExpression, -} - -#[repr(u8)] -#[derive(Eq, PartialEq, Copy, Clone, Debug, Display)] -pub enum UnexpectedTupleLiteralElementCount { - #[display(fmt = "no elements")] - Zero = 0, - #[display(fmt = "only one element")] - One = 1, -} - -#[derive(Debug, Eq, PartialEq, Clone)] -pub enum IntermediateStateCandidate { - Expression(Expression), -} - -#[derive(Display, Debug, Eq, PartialEq, Clone)] -pub enum PartiallyParseFixCandidate { - #[display(fmt = "No fixes available")] - None, - #[display(fmt = "Insert before")] - InsertBefore { - tokens: Vec, - }, - #[display(fmt = "Insert after")] - InsertAfter { - tokens: Vec, - }, -} +pub mod error; +pub mod recover; #[derive(Display, Debug, Eq, PartialEq, Clone)] pub enum TokenKind { diff --git a/package/origlang-compiler/src/parser/error.rs b/package/origlang-compiler/src/parser/error.rs new file mode 100644 index 00000000..4d25c7b4 --- /dev/null +++ b/package/origlang-compiler/src/parser/error.rs @@ -0,0 +1,88 @@ +use thiserror::Error as ThisError; +use origlang_source_span::{Pointed, SourcePosition as SourcePos, SourcePosition}; +use std::fmt::{Display, Formatter}; +use derive_more::Display; +use std::num::ParseIntError; +use crate::lexer::error::LexerError; +use crate::lexer::token::Token; +use crate::parser::TokenKind; +use crate::parser::recover::{IntermediateStateCandidate, PartiallyParseFixCandidate}; + +#[derive(ThisError, Debug, Eq, PartialEq)] +pub struct ParserError(Pointed); + +impl Display for ParserError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("{} ({})", &self.0.data, &self.0.position)) + } +} + +impl ParserError { + pub fn new(kind: ParserErrorInner, position: SourcePos) -> Self { + Self(Pointed { + data: kind, + position + }) + } + + pub fn kind(&self) -> &ParserErrorInner { + &self.0.data + } + + pub fn position(&self) -> &SourcePosition { + &self.0.position + } +} + +#[derive(ThisError, Debug, Eq, PartialEq)] +#[allow(clippy::module_name_repetitions)] +pub enum ParserErrorInner { + #[error("lexer error: {_0}")] + LexerError(#[from] LexerError), + #[error("unconsumed token found: {token:?}")] + UnconsumedToken { + token: Token + }, + #[error("statement must be terminated by a newline")] + StatementTerminationError, + #[error("EOF Error")] + EndOfFileError, + #[error("Expected {pat}, but got {unmatch:?}")] + UnexpectedToken { + pat: TokenKind, + unmatch: Token, + }, + #[error("Incomplete program snippet. Check hint for fix candidates. hint:{hint:?} state:{intermediate_state:?}")] + PartiallyParsed { + hint: Vec, + intermediate_state: Vec, + }, + #[error("input sequence cannot be parsed as a int literal: {error}")] + UnParsableIntLiteral { + error: ParseIntError + }, + #[error("int literal type of {tp} must be in range ({min}..={max}), but its value is {value}")] + OverflowedLiteral { + tp: Box, + min: i64, + max: i64, + value: i64, + }, + #[error("if expression requires `else` clause")] + IfExpressionWithoutElseClause, + #[error("if expression requires `then` clause and `else` clause")] + IfExpressionWithoutThenClauseAndElseClause, + #[error("tuple literal requires 2 or more elements, but got {_0}")] + InsufficientElementsForTupleLiteral(UnexpectedTupleLiteralElementCount), + #[error("`_` cannot used as right hand side expression")] + UnderscoreCanNotBeRightHandExpression, +} + +#[repr(u8)] +#[derive(Eq, PartialEq, Copy, Clone, Debug, Display)] +pub enum UnexpectedTupleLiteralElementCount { + #[display(fmt = "no elements")] + Zero = 0, + #[display(fmt = "only one element")] + One = 1, +} diff --git a/package/origlang-compiler/src/parser/recover.rs b/package/origlang-compiler/src/parser/recover.rs new file mode 100644 index 00000000..9ee6527f --- /dev/null +++ b/package/origlang-compiler/src/parser/recover.rs @@ -0,0 +1,22 @@ +use derive_more::Display; +use origlang_ast::after_parse::Expression; +use crate::lexer::token::Token; + +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum IntermediateStateCandidate { + Expression(Expression), +} + +#[derive(Display, Debug, Eq, PartialEq, Clone)] +pub enum PartiallyParseFixCandidate { + #[display(fmt = "No fixes available")] + None, + #[display(fmt = "Insert before")] + InsertBefore { + tokens: Vec, + }, + #[display(fmt = "Insert after")] + InsertAfter { + tokens: Vec, + }, +} diff --git a/package/origlang-interop/src/lib.rs b/package/origlang-interop/src/lib.rs index e039d68e..f7572195 100644 --- a/package/origlang-interop/src/lib.rs +++ b/package/origlang-interop/src/lib.rs @@ -6,7 +6,8 @@ use thiserror::Error; use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen::prelude::wasm_bindgen; use web_sys::console; -use origlang_compiler::parser::{Parser, ParserError}; +use origlang_compiler::parser::Parser; +use origlang_compiler::parser::error::ParserError; use origlang_compiler::type_check::error::TypeCheckError; use origlang_compiler::type_check::TypeChecker; use origlang_ir::IntoVerbatimSequencedIR; diff --git a/package/origlang-testsuite/src/main.rs b/package/origlang-testsuite/src/main.rs index d11e5f65..b9ae3f3a 100644 --- a/package/origlang-testsuite/src/main.rs +++ b/package/origlang-testsuite/src/main.rs @@ -10,15 +10,15 @@ fn main() { use log::{debug, info}; use thiserror::Error; -use origlang_compiler::parser::{ParserErrorInner, ParserError}; -use origlang_runtime::{Runtime, TypeBox, Accumulate, DisplayTupleValue}; +use origlang_runtime::{Accumulate, DisplayTupleValue, Runtime, TypeBox}; use origlang_ast::{AtomicPattern, Comment, Identifier, RootAst, Statement, TypeSignature}; use origlang_ast::after_parse::{BinaryOperatorKind, Expression}; +use origlang_compiler::parser::error::{ParserError, ParserErrorInner}; use origlang_compiler::type_check::error::TypeCheckError; use origlang_compiler::type_check::TypeChecker; use origlang_ir::IntoVerbatimSequencedIR; use origlang_ir_optimizer::lower::{EachStep, LowerStep, TheTranspiler}; -use origlang_ir_optimizer::preset::{NoOptimization, SimpleOptimization}; +use origlang_ir_optimizer::preset::NoOptimization; use origlang_source_span::SourcePosition; type Err = TestFailureCause;