From 3f1653511bfc2c580a16e78d35a9d2932bfdf1c5 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:19:33 -0600 Subject: [PATCH 1/3] Introduce KError --- kframework/src/error.rs | 28 ++++++++++++++++++++++++++++ kframework/src/lib.rs | 1 + 2 files changed, 29 insertions(+) create mode 100644 kframework/src/error.rs diff --git a/kframework/src/error.rs b/kframework/src/error.rs new file mode 100644 index 0000000..3744423 --- /dev/null +++ b/kframework/src/error.rs @@ -0,0 +1,28 @@ +#[derive(Debug)] +pub enum KError { + KoreLexerError(String), + KoreParseError(String), +} + +impl std::fmt::Display for KError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + KError::KoreParseError(msg) => write!(f, "{msg}"), + KError::KoreLexerError(msg) => write!(f, "{msg}"), + } + } +} + +impl std::error::Error for KError {} + +/// This impl exists so we can change function signatures +/// from returning Result<_, String> to Result<_, KError> +/// without having things break everywhere +impl From for String { + fn from(value: KError) -> Self { + match value { + KError::KoreParseError(msg) => msg, + KError::KoreLexerError(msg) => msg, + } + } +} diff --git a/kframework/src/lib.rs b/kframework/src/lib.rs index bdfddfd..90ae458 100644 --- a/kframework/src/lib.rs +++ b/kframework/src/lib.rs @@ -1 +1,2 @@ +pub mod error; pub mod kore; From 3bc8b4d7aa8dddd65abab0c26f8ca7016ae44047 Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:20:17 -0600 Subject: [PATCH 2/3] Return Result<_, KError> in kore::{syntax, parser, lexer} --- kframework/src/kore/lexer.rs | 27 ++++--- kframework/src/kore/parser.rs | 129 +++++++++++++++++--------------- kframework/src/kore/syntax.rs | 79 ++++++++++++------- kframework/tests/kore/parser.rs | 15 ++-- 4 files changed, 141 insertions(+), 109 deletions(-) diff --git a/kframework/src/kore/lexer.rs b/kframework/src/kore/lexer.rs index 23bf992..f5b3c88 100644 --- a/kframework/src/kore/lexer.rs +++ b/kframework/src/kore/lexer.rs @@ -1,3 +1,4 @@ +use crate::error::KError::{self, KoreLexerError}; use std::str::Chars; #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -86,8 +87,7 @@ impl<'a> Lexer<'a> { } } - pub fn next_token(&mut self) -> Result, String> { - // TODO KoreLexerError + pub fn next_token(&mut self) -> Result, KError> { let la = loop { let Some(la) = self.la else { return Ok(Token { @@ -119,7 +119,7 @@ impl<'a> Lexer<'a> { '[' => self.lbrack(), ']' => self.rbrack(), // Error - _ => return Err(format!("Unexpected character: {:?}", la)), + _ => return Err(KoreLexerError(format!("Unexpected character: {:?}", la))), }; debug_assert!(token.text == &self.text[token.offset..token.offset + token.text.len()]); Ok(token) @@ -138,7 +138,7 @@ impl<'a> Lexer<'a> { Token { ty, text, offset } } - fn string(&mut self) -> Result, String> { + fn string(&mut self) -> Result, KError> { debug_assert!(self.la == Some('"')); let offset = self.offset; let mut len: usize = 1; @@ -199,7 +199,7 @@ impl<'a> Lexer<'a> { Token { ty, text, offset } } - fn symbol_or_ml_conn(&mut self) -> Result, String> { + fn symbol_or_ml_conn(&mut self) -> Result, KError> { debug_assert!(self.la == Some('\\')); let offset = self.offset; @@ -208,7 +208,7 @@ impl<'a> Lexer<'a> { self.consume(); let la = self.la_or_err()?; if !la.is_ascii_alphabetic() { - return Err(format!("Expected letter, got: {:?}", la)); + return Err(KoreLexerError(format!("Expected letter, got: {:?}", la))); } self.consume(); @@ -248,7 +248,7 @@ impl<'a> Lexer<'a> { Ok(Token { ty, text, offset }) } - fn set_var_id(&mut self) -> Result, String> { + fn set_var_id(&mut self) -> Result, KError> { debug_assert!(self.la == Some('@')); let offset = self.offset; @@ -258,7 +258,7 @@ impl<'a> Lexer<'a> { self.consume(); let la = self.la_or_err()?; if !la.is_ascii_alphabetic() { - return Err(format!("Expected letter, got: {:?}", la)); + return Err(KoreLexerError(format!("Expected letter, got: {:?}", la))); } // TODO consume_while or consume_until @@ -383,7 +383,7 @@ impl<'a> Lexer<'a> { } } - fn consume_comment(&mut self) -> Result<(), String> { + fn consume_comment(&mut self) -> Result<(), KError> { debug_assert!(self.la == Some('/')); self.consume(); @@ -420,7 +420,10 @@ impl<'a> Lexer<'a> { } } - _ => Err(format!("Expected '/' or '*', got: {:?}", la)), + _ => Err(KoreLexerError(format!( + "Expected '/' or '*', got: {:?}", + la + ))), } } @@ -433,9 +436,9 @@ impl<'a> Lexer<'a> { res } - fn la_or_err(&self) -> Result { + fn la_or_err(&self) -> Result { self.la - .ok_or_else(|| String::from("Unexpected end of file")) + .ok_or_else(|| KoreLexerError(String::from("Unexpected end of file"))) } } diff --git a/kframework/src/kore/parser.rs b/kframework/src/kore/parser.rs index 6a7d3aa..120ed83 100644 --- a/kframework/src/kore/parser.rs +++ b/kframework/src/kore/parser.rs @@ -2,6 +2,7 @@ use super::lexer::{Lexer, Token, TokenType}; use super::{ App, Definition, Id, Module, Pattern, SVar, Sentence, SetVarId, Sort, Str, SymbolId, Var, }; +use crate::error::KError::{self, KoreParseError}; pub struct Parser<'a> { #[allow(dead_code)] @@ -11,14 +12,13 @@ pub struct Parser<'a> { } impl<'a> Parser<'a> { - pub fn new(text: &'a str) -> Result { - // TODO KoreParserError + pub fn new(text: &'a str) -> Result { let mut lexer = Lexer::new(text); let la = lexer.next_token()?; Ok(Self { text, lexer, la }) } - pub fn definition(&mut self) -> Result { + pub fn definition(&mut self) -> Result { let attrs = self.attrs()?; let mut modules = Vec::new(); while self.la.ty() != TokenType::Eof { @@ -28,7 +28,7 @@ impl<'a> Parser<'a> { Ok(Definition { modules, attrs }) } - pub fn module(&mut self) -> Result { + pub fn module(&mut self) -> Result { self.match_token(TokenType::KwModule)?; let id = self.id()?; let mut sentences = Vec::new(); @@ -45,7 +45,7 @@ impl<'a> Parser<'a> { }) } - pub fn sentence(&mut self) -> Result { + pub fn sentence(&mut self) -> Result { let parse = match self.la.ty() { TokenType::KwImport => Self::import, TokenType::KwSort => Self::ssort, @@ -56,16 +56,16 @@ impl<'a> Parser<'a> { TokenType::KwAxiom => Self::axiom, TokenType::KwClaim => Self::claim, _ => { - return Err(format!( + return Err(KoreParseError(format!( "Expected sentence token, found: {:?}", self.la.ty() - )) + ))) } }; parse(self) } - pub fn pattern(&mut self) -> Result { + pub fn pattern(&mut self) -> Result { let parse = match self.la.ty() { TokenType::Str => Self::str, TokenType::SetVarId => Self::svar, @@ -91,12 +91,17 @@ impl<'a> Parser<'a> { TokenType::MlIn => Self::inn, TokenType::MlNext => Self::next, TokenType::MlRewrites => Self::rewrites, - _ => return Err(format!("Expected pattern token, found: {:?}", self.la.ty())), + _ => { + return Err(KoreParseError(format!( + "Expected pattern token, found: {:?}", + self.la.ty() + ))) + } }; parse(self) } - pub fn sort(&mut self) -> Result { + pub fn sort(&mut self) -> Result { let id = self.id()?; let sort = if self.la.ty() == TokenType::LBrace { let args = self.sorts()?; @@ -111,7 +116,7 @@ impl<'a> Parser<'a> { * Helpers: sentences */ - fn import(&mut self) -> Result { + fn import(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwImport); self.consume()?; let module = self.id()?; @@ -119,7 +124,7 @@ impl<'a> Parser<'a> { Ok(Sentence::Import { module, attrs }) } - fn ssort(&mut self) -> Result { + fn ssort(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwSort); self.consume()?; let id = self.id()?; @@ -133,7 +138,7 @@ impl<'a> Parser<'a> { }) } - fn hooked_sort(&mut self) -> Result { + fn hooked_sort(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwHookedSort); self.consume()?; let id = self.id()?; @@ -147,7 +152,7 @@ impl<'a> Parser<'a> { }) } - fn symbol(&mut self) -> Result { + fn symbol(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwSymbol); self.consume()?; let id = self.symbol_id()?; @@ -166,7 +171,7 @@ impl<'a> Parser<'a> { }) } - fn hooked_symbol(&mut self) -> Result { + fn hooked_symbol(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwHookedSymbol); self.consume()?; let id = self.symbol_id()?; @@ -185,7 +190,7 @@ impl<'a> Parser<'a> { }) } - fn alias(&mut self) -> Result { + fn alias(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwAlias); self.consume()?; let id = self.symbol_id()?; @@ -209,7 +214,7 @@ impl<'a> Parser<'a> { }) } - fn axiom(&mut self) -> Result { + fn axiom(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwAxiom); self.consume()?; let vars = self.sort_vars()?; @@ -222,7 +227,7 @@ impl<'a> Parser<'a> { }) } - fn claim(&mut self) -> Result { + fn claim(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::KwClaim); self.consume()?; let vars = self.sort_vars()?; @@ -239,19 +244,19 @@ impl<'a> Parser<'a> { * Helpers: patterns */ - fn str(&mut self) -> Result { + fn str(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::Str); let s = self.str_()?; Ok(Pattern::Str(s)) } - fn svar(&mut self) -> Result { + fn svar(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::SetVarId); let svar = self.svar_()?; Ok(Pattern::SVar(svar)) } - fn var_or_app(&mut self) -> Result { + fn var_or_app(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::Id); let id = self.id()?; if self.la.ty() == TokenType::Colon { @@ -273,7 +278,7 @@ impl<'a> Parser<'a> { } } - fn app(&mut self) -> Result { + fn app(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::SymbolId); let app = self.app_()?; Ok(Pattern::App(app)) @@ -281,7 +286,7 @@ impl<'a> Parser<'a> { // TODO macros - fn left_assoc(&mut self) -> Result { + fn left_assoc(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlLeftAssoc); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -292,7 +297,7 @@ impl<'a> Parser<'a> { Ok(Pattern::LeftAssoc(app)) } - fn right_assoc(&mut self) -> Result { + fn right_assoc(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlRightAssoc); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -303,7 +308,7 @@ impl<'a> Parser<'a> { Ok(Pattern::RightAssoc(app)) } - fn dv(&mut self) -> Result { + fn dv(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlDv); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -315,7 +320,7 @@ impl<'a> Parser<'a> { Ok(Pattern::Dv { sort, value }) } - fn top(&mut self) -> Result { + fn top(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlTop); self.consume()?; // TODO extract helpers for "{" Sort "}" etc. @@ -327,7 +332,7 @@ impl<'a> Parser<'a> { Ok(Pattern::Top(sort)) } - fn bottom(&mut self) -> Result { + fn bottom(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlBottom); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -338,7 +343,7 @@ impl<'a> Parser<'a> { Ok(Pattern::Bottom(sort)) } - fn not(&mut self) -> Result { + fn not(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlNot); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -353,7 +358,7 @@ impl<'a> Parser<'a> { }) } - fn implies(&mut self) -> Result { + fn implies(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlImplies); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -371,7 +376,7 @@ impl<'a> Parser<'a> { }) } - fn iff(&mut self) -> Result { + fn iff(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlIff); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -389,7 +394,7 @@ impl<'a> Parser<'a> { }) } - fn and(&mut self) -> Result { + fn and(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlAnd); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -399,7 +404,7 @@ impl<'a> Parser<'a> { Ok(Pattern::And { sort, ops }) } - fn or(&mut self) -> Result { + fn or(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlOr); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -409,7 +414,7 @@ impl<'a> Parser<'a> { Ok(Pattern::Or { sort, ops }) } - fn exists(&mut self) -> Result { + fn exists(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlExists); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -427,7 +432,7 @@ impl<'a> Parser<'a> { }) } - fn forall(&mut self) -> Result { + fn forall(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlForall); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -445,7 +450,7 @@ impl<'a> Parser<'a> { }) } - fn mu(&mut self) -> Result { + fn mu(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlMu); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -461,7 +466,7 @@ impl<'a> Parser<'a> { }) } - fn nu(&mut self) -> Result { + fn nu(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlNu); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -477,7 +482,7 @@ impl<'a> Parser<'a> { }) } - fn ceil(&mut self) -> Result { + fn ceil(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlCeil); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -495,7 +500,7 @@ impl<'a> Parser<'a> { }) } - fn floor(&mut self) -> Result { + fn floor(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlFloor); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -513,7 +518,7 @@ impl<'a> Parser<'a> { }) } - fn equals(&mut self) -> Result { + fn equals(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlEquals); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -534,7 +539,7 @@ impl<'a> Parser<'a> { }) } - fn inn(&mut self) -> Result { + fn inn(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlIn); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -555,7 +560,7 @@ impl<'a> Parser<'a> { }) } - fn next(&mut self) -> Result { + fn next(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlNext); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -570,7 +575,7 @@ impl<'a> Parser<'a> { }) } - fn rewrites(&mut self) -> Result { + fn rewrites(&mut self) -> Result { debug_assert!(self.la.ty() == TokenType::MlRewrites); self.consume()?; self.match_token(TokenType::LBrace)?; @@ -592,52 +597,52 @@ impl<'a> Parser<'a> { * Helpers: misc */ - fn id(&mut self) -> Result { + fn id(&mut self) -> Result { let s = self.match_token(TokenType::Id)?; Ok(Id(String::from(s))) } - fn symbol_id(&mut self) -> Result { + fn symbol_id(&mut self) -> Result { match self.la.ty() { TokenType::Id | TokenType::SymbolId => { let s = String::from(self.la.text()); self.consume()?; Ok(SymbolId(s)) } - _ => Err(format!( + _ => Err(KoreParseError(format!( "Expected token {:?} or {:?}, found: {:?}", TokenType::Id, TokenType::SymbolId, self.la.ty() - )), + ))), } } - fn set_var_id(&mut self) -> Result { + fn set_var_id(&mut self) -> Result { let s = self.match_token(TokenType::SetVarId)?; Ok(SetVarId(String::from(s))) } - fn str_(&mut self) -> Result { + fn str_(&mut self) -> Result { let s = self.match_token(TokenType::Str)?; Str::from_kore(&s[1..s.len() - 1]) } - fn var(&mut self) -> Result { + fn var(&mut self) -> Result { let id = self.id()?; self.match_token(TokenType::Colon)?; let sort = self.sort()?; Ok(Var { id, sort }) } - fn svar_(&mut self) -> Result { + fn svar_(&mut self) -> Result { let id = self.set_var_id()?; self.match_token(TokenType::Colon)?; let sort = self.sort()?; Ok(SVar { id, sort }) } - fn app_(&mut self) -> Result { + fn app_(&mut self) -> Result { let symbol = self.symbol_id()?; let sorts = self.sorts()?; let args = self.patterns()?; @@ -652,7 +657,7 @@ impl<'a> Parser<'a> { * Helpers: delimited lists */ - fn sort_vars(&mut self) -> Result, String> { + fn sort_vars(&mut self) -> Result, KError> { self.delimited_list( Self::id, TokenType::LBrace, @@ -661,7 +666,7 @@ impl<'a> Parser<'a> { ) } - fn attrs(&mut self) -> Result, String> { + fn attrs(&mut self) -> Result, KError> { self.delimited_list( Self::app_, TokenType::LBrack, @@ -670,7 +675,7 @@ impl<'a> Parser<'a> { ) } - fn patterns(&mut self) -> Result, String> { + fn patterns(&mut self) -> Result, KError> { self.delimited_list( Self::pattern, TokenType::LParen, @@ -679,7 +684,7 @@ impl<'a> Parser<'a> { ) } - fn sorts(&mut self) -> Result, String> { + fn sorts(&mut self) -> Result, KError> { self.delimited_list( Self::sort, TokenType::LBrace, @@ -688,7 +693,7 @@ impl<'a> Parser<'a> { ) } - fn param_sorts(&mut self) -> Result, String> { + fn param_sorts(&mut self) -> Result, KError> { self.delimited_list( Self::sort, TokenType::LParen, @@ -699,11 +704,11 @@ impl<'a> Parser<'a> { fn delimited_list( &mut self, - parse: fn(&mut Self) -> Result, + parse: fn(&mut Self) -> Result, ldelim: TokenType, rdelim: TokenType, sep: TokenType, - ) -> Result, String> { + ) -> Result, KError> { self.match_token(ldelim)?; let mut elems = Vec::new(); while self.la.ty() != rdelim { @@ -722,21 +727,21 @@ impl<'a> Parser<'a> { * Helpers: lexer management */ - fn match_token(&mut self, expected: TokenType) -> Result<&'a str, String> { + fn match_token(&mut self, expected: TokenType) -> Result<&'a str, KError> { let actual = self.la.ty(); if actual == expected { let text = self.la.text(); self.consume()?; Ok(text) } else { - Err(format!( + Err(KoreParseError(format!( "Expected token {:?}, found: {:?}", expected, actual, - )) + ))) } } - fn consume(&mut self) -> Result<(), String> { + fn consume(&mut self) -> Result<(), KError> { self.la = self.lexer.next_token()?; Ok(()) } diff --git a/kframework/src/kore/syntax.rs b/kframework/src/kore/syntax.rs index a1effe5..7f7732a 100644 --- a/kframework/src/kore/syntax.rs +++ b/kframework/src/kore/syntax.rs @@ -1,26 +1,33 @@ +use crate::error::KError::{self, KoreParseError}; + #[derive(Debug, PartialEq, Eq)] pub struct Id(pub(crate) String); impl Id { - pub fn new(s: String) -> Result { + pub fn new(s: String) -> Result { let mut first_checked = false; for c in s.chars() { if !first_checked { if !c.is_ascii_alphabetic() { - return Err(format!("Expected alphabetic character, got: {:?}", c)); + return Err(KoreParseError(format!( + "Expected alphabetic character, got: {:?}", + c + ))); } first_checked = true; } else if !c.is_ascii_alphanumeric() && c != '\'' && c != '-' { - return Err(format!( + return Err(KoreParseError(format!( "Expected alphanumeric character, '\'' or '-', got: {:?}", c - )); + ))); } } if first_checked { Ok(Id(s)) } else { - Err(String::from("Invalid identifier: empty string")) + Err(KoreParseError(String::from( + "Invalid identifier: empty string", + ))) } } @@ -30,9 +37,9 @@ impl Id { } impl TryFrom for Id { - type Error = String; + type Error = KError; - fn try_from(s: String) -> Result { + fn try_from(s: String) -> Result { Id::new(s) } } @@ -41,7 +48,7 @@ impl TryFrom for Id { pub struct SymbolId(pub(crate) String); impl SymbolId { - pub fn new(s: String) -> Result { + pub fn new(s: String) -> Result { enum State { First, Second, @@ -56,30 +63,33 @@ impl SymbolId { } else if c.is_ascii_alphabetic() { state = State::Rest; } else { - return Err(format!( + return Err(KoreParseError(format!( "Expected alphabetic character or '\\', got: {:?}", c - )); + ))); } } State::Second => { if !c.is_ascii_alphabetic() { - return Err(format!("Expected alphabetic character, got: {:?}", c)); + return Err(KoreParseError(format!( + "Expected alphabetic character, got: {:?}", + c + ))); } state = State::Rest; } State::Rest => { if !c.is_ascii_alphanumeric() && c != '\'' && c != '-' { - return Err(format!( + return Err(KoreParseError(format!( "Expected alphanumeric character, '\'' or '-', got: {:?}", c - )); + ))); } } } } match state { - State::First | State::Second => Err(format!("Invalid symbol: {:?}", s)), + State::First | State::Second => Err(KoreParseError(format!("Invalid symbol: {:?}", s))), State::Rest => Ok(SymbolId(s)), } } @@ -90,9 +100,9 @@ impl SymbolId { } impl TryFrom for SymbolId { - type Error = String; + type Error = KError; - fn try_from(s: String) -> Result { + fn try_from(s: String) -> Result { SymbolId::new(s) } } @@ -101,7 +111,7 @@ impl TryFrom for SymbolId { pub struct SetVarId(pub(crate) String); impl SetVarId { - pub fn new(s: String) -> Result { + pub fn new(s: String) -> Result { enum State { First, Second, @@ -112,28 +122,33 @@ impl SetVarId { match state { State::First => { if c != '@' { - return Err(format!("Expected '@', got: {:?}", c)); + return Err(KoreParseError(format!("Expected '@', got: {:?}", c))); } state = State::Second; } State::Second => { if !c.is_ascii_alphabetic() { - return Err(format!("Expected alphabetic character, got: {:?}", c)); + return Err(KoreParseError(format!( + "Expected alphabetic character, got: {:?}", + c + ))); } state = State::Rest; } State::Rest => { if !c.is_ascii_alphanumeric() && c != '\'' && c != '-' { - return Err(format!( + return Err(KoreParseError(format!( "Expected alphanumeric character, '\'' or '-', got: {:?}", c - )); + ))); } } } } match state { - State::First | State::Second => Err(format!("Invalid set variable: {:?}", s)), + State::First | State::Second => { + Err(KoreParseError(format!("Invalid set variable: {:?}", s))) + } State::Rest => Ok(SetVarId(s)), } } @@ -144,9 +159,9 @@ impl SetVarId { } impl TryFrom for SetVarId { - type Error = String; + type Error = KError; - fn try_from(s: String) -> Result { + fn try_from(s: String) -> Result { SetVarId::new(s) } } @@ -155,7 +170,7 @@ impl TryFrom for SetVarId { pub struct Str(pub String); impl Str { - pub fn from_kore(s: &str) -> Result { + pub fn from_kore(s: &str) -> Result { let mut chars: Vec = Vec::new(); enum State { @@ -196,19 +211,27 @@ impl Str { 'x' => 2, 'u' => 4, 'U' => 8, - _ => return Err(format!("Unexpected escape sequence: \\{}", c)), + _ => { + return Err(KoreParseError(format!( + "Unexpected escape sequence: \\{}", + c + ))) + } }; state = State::CodePoint; } State::CodePoint => { let Some(digit) = c.to_digit(16) else { - return Err(format!("Invalid hex digit: {:?}", c)); + return Err(KoreParseError(format!("Invalid hex digit: {:?}", c))); }; acc = 16 * acc + digit; cnt -= 1; if cnt == 0 { let Some(encoded) = char::from_u32(acc) else { - return Err(format!("Invalid unicode code point: {:x}", acc)); + return Err(KoreParseError(format!( + "Invalid unicode code point: {:x}", + acc + ))); }; chars.push(encoded); acc = 0; diff --git a/kframework/tests/kore/parser.rs b/kframework/tests/kore/parser.rs index 0df704c..be6ef5e 100644 --- a/kframework/tests/kore/parser.rs +++ b/kframework/tests/kore/parser.rs @@ -1,16 +1,17 @@ +use kframework::error::KError; use kframework::kore::{ App, Definition, Id, Module, Parser, Pattern, SVar, Sentence, SetVarId, Sort, SymbolId, Var, }; -fn id>(s: T) -> Result { +fn id>(s: T) -> Result { Id::new(s.into()) } -fn sym>(s: T) -> Result { +fn sym>(s: T) -> Result { SymbolId::new(s.into()) } -fn svid>(s: T) -> Result { +fn svid>(s: T) -> Result { SetVarId::new(s.into()) } @@ -18,7 +19,7 @@ macro_rules! sort_tests { ($($name:ident: $value:expr,)*) => { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), KError> { // Given let (text, expected) = $value; let mut parser = Parser::new(text)?; @@ -53,7 +54,7 @@ macro_rules! pattern_tests { ($($name:ident: $value:expr,)*) => { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), KError> { // Given let (text, expected) = $value; let mut parser = Parser::new(text)?; @@ -318,7 +319,7 @@ macro_rules! sentence_tests { ($($name:ident: $value:expr,)*) => { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), KError> { // Given let (text, expected) = $value; let mut parser = Parser::new(text)?; @@ -425,7 +426,7 @@ sentence_tests! { } #[test] -fn test_definition() -> Result<(), String> { +fn test_definition() -> Result<(), KError> { // Given let text = r#" [foo{}("bar"), baz{}()] From 78452366c8fda5ff4781dac9ccabdf15c7fd5a3d Mon Sep 17 00:00:00 2001 From: Guy Repta <50716988+gtrepta@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:13:14 -0600 Subject: [PATCH 3/3] Remove From for String helper impl. --- kframework/src/error.rs | 12 ------------ kframework/src/kore/syntax.rs | 3 ++- kframework/tests/kore/serde.rs | 16 ++++++++-------- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/kframework/src/error.rs b/kframework/src/error.rs index 3744423..4bf43bd 100644 --- a/kframework/src/error.rs +++ b/kframework/src/error.rs @@ -14,15 +14,3 @@ impl std::fmt::Display for KError { } impl std::error::Error for KError {} - -/// This impl exists so we can change function signatures -/// from returning Result<_, String> to Result<_, KError> -/// without having things break everywhere -impl From for String { - fn from(value: KError) -> Self { - match value { - KError::KoreParseError(msg) => msg, - KError::KoreLexerError(msg) => msg, - } - } -} diff --git a/kframework/src/kore/syntax.rs b/kframework/src/kore/syntax.rs index 7f7732a..a7ec9bc 100644 --- a/kframework/src/kore/syntax.rs +++ b/kframework/src/kore/syntax.rs @@ -420,12 +420,13 @@ pub enum Pattern { #[cfg(test)] mod tests { use super::Str; + use crate::error::KError; macro_rules! str_tests { ($($name:ident: $value:expr,)*) => { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), KError> { // Given let (input, expected) = $value; diff --git a/kframework/tests/kore/serde.rs b/kframework/tests/kore/serde.rs index 2d65cc6..553e796 100644 --- a/kframework/tests/kore/serde.rs +++ b/kframework/tests/kore/serde.rs @@ -8,13 +8,13 @@ macro_rules! sort_tests { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), Box> { // Given let (text, expected) = $value; let sort = Parser::new(text)?.sort()?; // When - let actual = serde_json::to_string_pretty(&sort).map_err(|e| e.to_string())?; + let actual = serde_json::to_string_pretty(&sort)?; // Then assert_eq!(expected, actual); @@ -31,13 +31,13 @@ macro_rules! sort_tests { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), Box> { // Given let (text, json) = $value; let expected = Parser::new(text)?.sort()?; // When - let actual = serde_json::from_str(json).map_err(|e| e.to_string())?; + let actual = serde_json::from_str(json)?; // Then assert_eq!(expected, actual); @@ -85,13 +85,13 @@ macro_rules! pattern_tests { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), Box> { // Given let (text, expected) = $value; let sort = Parser::new(text)?.pattern()?; // When - let actual = serde_json::to_string_pretty(&sort).map_err(|e| e.to_string())?; + let actual = serde_json::to_string_pretty(&sort)?; // Then assert_eq!(expected, actual); @@ -107,13 +107,13 @@ macro_rules! pattern_tests { $( #[test] - fn $name() -> Result<(), String> { + fn $name() -> Result<(), Box> { // Given let (text, json) = $value; let expected = Parser::new(text)?.pattern()?; // When - let actual = serde_json::from_str(json).map_err(|e| e.to_string())?; + let actual = serde_json::from_str(json)?; // Then assert_eq!(expected, actual);