diff options
| author | Elizabeth Alexander Hunt <lizhunt@amazon.com> | 2026-08-14 15:22:49 -0700 |
|---|---|---|
| committer | Elizabeth Alexander Hunt <lizhunt@amazon.com> | 2026-08-14 15:22:49 -0700 |
| commit | b38ce2a67114cab3e3416d602a58a17f58e27c96 (patch) | |
| tree | fa72ad1f6f096231c325301ab2dedd288d091df0 | |
| parent | ca16123c89f5731e2a3096d3780e641d071280d6 (diff) | |
| download | gock-main.tar.gz gock-main.zip | |
| -rw-r--r-- | src/main.rs | 140 |
1 files changed, 100 insertions, 40 deletions
diff --git a/src/main.rs b/src/main.rs index 7736a08..48ccbe3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,27 @@ enum TokenType { Eof, } +impl fmt::Display for TokenType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let chars = match self { + TokenType::Lparen => "(", + TokenType::Rparen => ")", + TokenType::Lbracket => "[", + TokenType::Rbracket => "]", + TokenType::Lbrace => "{", + TokenType::Rbrace => "}", + TokenType::Colon => ":", + TokenType::Semicolon => ";", + TokenType::Arrow => "->", + TokenType::Comma => ",", + TokenType::Equals => "=", + TokenType::Identifier(name) => name, + TokenType::Eof => "", + }; + write!(f, "{}", chars) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct Blame { line: usize, @@ -65,6 +86,11 @@ impl Lexer { }; for (i, c) in text.char_indices() { + // HACK for two-char type shi + if c == '>' { + continue; + } + let lookahead = text.chars().nth(i.saturating_add(1)); let singlechar = match c { '(' => Some(TokenType::Lparen), @@ -107,17 +133,6 @@ impl Lexer { } } -enum Atomic { - Unit, - Bool, - Int, -} - -enum SimpleType { - Arrow(Box<(SimpleType, SimpleType)>), - Atom(Atomic), -} - type Identifier = String; struct Binding { @@ -164,7 +179,7 @@ impl fmt::Display for Arguments { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Arguments(")?; for v in &self.0 { - write!(f, "\t{}", v)?; + write!(f, "{} ", v)?; } write!(f, ")") } @@ -180,7 +195,7 @@ impl fmt::Display for Assignments { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Assignments(")?; for v in &self.0 { - write!(f, "\t{}", v)?; + write!(f, "{} ", v)?; } write!(f, ")") } @@ -188,7 +203,14 @@ impl fmt::Display for Assignments { impl fmt::Display for Binding { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Binding({}, {})", self.name, "TYPE TODO") + write!( + f, + "Binding({}, {})", + self.name, + self.arg_type + .as_ref() + .unwrap_or(&TypeDeclaration::BaseType(String::from("None"))) + ) } } @@ -237,6 +259,23 @@ enum ParsingFailure { PastTokens, } +impl fmt::Display for Blame { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Blame({}, {})", self.line, self.char) + } +} + +impl fmt::Display for ParsingFailure { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParsingFailure::Blame(blame, reason) => { + write!(f, "ParsingFailure({}, {})", blame, reason) + } + ParsingFailure::PastTokens => write!(f, "ParsingFailure(PastTokens)"), + } + } +} + impl Parser { fn peek(&mut self) -> Result<&Token, ParsingFailure> { return self @@ -282,33 +321,21 @@ impl Parser { fn parse_type_declaration(&mut self) -> Result<TypeDeclaration, ParsingFailure> { self.consume_if_match_nomsg(|it| (*it).token == TokenType::Lparen)?; - let my_type = self.consume_if_and_map( - |it| match ((*it).token).clone() { - // unfortunately, gotta clone to make the borrow checker happy. maybe i'll come back to this :3 - TokenType::Identifier(name) => Some(name.clone()), - _ => None, - }, - String::from("BWA"), - ); - if let Ok(name) = my_type { - return Ok(TypeDeclaration::BaseType(name as Identifier)); + let type_name = self.parse_identifier(); + if let Ok(name) = type_name { + self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rparen)?; + println!("{}", name); + return Ok(TypeDeclaration::BaseType(name)); } let left = self.parse_type_declaration()?; self.consume_if_match_nomsg(|it| (*it).token == TokenType::Arrow)?; let right = self.parse_type_declaration()?; + self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rparen)?; return Ok(TypeDeclaration::Arrow(Box::new((left, right)))); } fn parse_binding(&mut self) -> Result<Binding, ParsingFailure> { - let name = self.consume_if_and_map( - |it| match ((*it).token).clone() { - // unfortunately, gotta clone to make the borrow checker happy. maybe i'll come back to this :3 - TokenType::Identifier(name) => Some(name), - _ => None, - }, - String::from("Expected identifier"), - )?; - + let name = self.parse_identifier()?; let val = self.consume_if_match_nomsg(|it| (*it).token == TokenType::Colon); if val.is_ok() { let blame = val.unwrap().blame; @@ -373,9 +400,13 @@ impl Parser { } } self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rbracket)?; + self.consume_if_match_nomsg(|it| (*it).token == TokenType::Lbrace)?; + let body = self.parse_computation()?; + println!("{}", self.peek()?.token); + self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rbrace)?; return Ok(Abstraction { arguments: Arguments(arguments), - body: Box::new(self.parse_computation()?), + body: Box::new(body), }); } @@ -389,6 +420,17 @@ impl Parser { }); } + fn parse_identifier(&mut self) -> Result<Identifier, ParsingFailure> { + self.consume_if_and_map( + |it| match ((*it).token).clone() { + // unfortunately, gotta clone to make the borrow checker happy. maybe i'll come back to this :3 + TokenType::Identifier(name) => Some(name), + _ => None, + }, + String::from("Expected identifier"), + ) + } + fn parse_computation(&mut self) -> Result<Computation, ParsingFailure> { let next = self.peek()?.clone(); return match next.token { @@ -396,10 +438,10 @@ impl Parser { if identifier == String::from("let") { Ok(Computation::LetStatement(self.parse_let_statement()?)) } else { - Ok(Computation::Identifier(identifier)) + Ok(Computation::Identifier(self.parse_identifier()?)) } } - TokenType::Lbrace => Ok(Computation::Abstraction(self.parse_abstraction()?)), + TokenType::Lbracket => Ok(Computation::Abstraction(self.parse_abstraction()?)), TokenType::Lparen => Ok(Computation::Application(self.parse_application()?)), _ => Err(ParsingFailure::Blame( next.blame, @@ -514,7 +556,21 @@ mod tests { } ); assert_eq!( - analysis[21], + analysis[8], + Token { + token: TokenType::Lparen, + blame: Blame { line: 1, char: 3 } + } + ); + assert_eq!( + analysis[18], + Token { + token: TokenType::Rbrace, + blame: Blame { line: 1, char: 20 } + } + ); + assert_eq!( + analysis[20], Token { token: TokenType::Eof, blame: Blame { line: 2, char: 0 } @@ -524,10 +580,14 @@ mod tests { #[test] fn test_parse() { - let prog = "let Identity: ((Int) -> (Int)) = [a] { a }; in Identity"; + let prog = "let Identity: ((Int) -> (Int)) =\n[a] { a }; in Identity"; let tokens = Lexer::analyze(prog); let mut parser = Parser::new(tokens); - let ast = parser.parse_computation().ok(); - println!("{}", ast.unwrap()); + match parser.parse_computation() { + Ok(parsed) => println!("{}", parsed), + Err(err) => println!("err {}", err), + }; + // let ast = parser.parse_computation().ok(); + // println!("{}", ast.unwrap()); } } |
