aboutsummaryrefslogtreecommitdiff
path: root/src/parser/parser.rs
diff options
context:
space:
mode:
authorAaditya Dhruv <[email protected]>2025-08-10 22:10:11 -0500
committerAaditya Dhruv <[email protected]>2025-08-10 22:10:11 -0500
commitd862b84ce868353e3482b380d0b68495de12eb6b (patch)
treed114c4b44460b9d1eaf689ea2ffed10c21943ecc /src/parser/parser.rs
parent63dbc54db1c33e341f2e843a6c71807e51a4dd7b (diff)
Add Parser support
- Parser is able to take Lexer tokens and generate AST with Text (Paragraph) and Headings - Scanner has been renamed to Lexer - main.rs has been updated to use the Lexer and Parser
Diffstat (limited to 'src/parser/parser.rs')
-rw-r--r--src/parser/parser.rs151
1 files changed, 145 insertions, 6 deletions
diff --git a/src/parser/parser.rs b/src/parser/parser.rs
index 53aa751..3ac6e82 100644
--- a/src/parser/parser.rs
+++ b/src/parser/parser.rs
@@ -1,13 +1,152 @@
-pub struct Parser {
+use std::iter::Peekable;
+
+use super::lexer::{TokenType, Token, Lexer};
+use crate::types::elements;
+
+struct Text {
+ token: Token,
+ text: String,
+}
+impl Into<elements::Paragraph> for &Text {
+ fn into(self) -> elements::Paragraph {
+ elements::Paragraph::new(self.text.clone())
+ }
+}
+
+struct Heading {
+ level: u8,
+ text: Text,
+}
+impl Into<elements::Heading> for &Heading {
+ fn into(self) -> elements::Heading {
+ elements::Heading::new(self.text.text.clone(), self.level)
+ }
}
-pub struct Text {
- value: String,
+struct Noop {}
+
+pub trait AST {
+ fn convert_to_renderable(&self) -> Box<dyn elements::Renderable>;
+}
+
+impl AST for Text {
+ fn convert_to_renderable(&self) -> Box<dyn elements::Renderable> {
+ let text: elements::Paragraph = self.into();
+ return Box::new(text);
+ }
+}
+impl AST for Heading {
+ fn convert_to_renderable(&self) -> Box<dyn elements::Renderable> {
+ let heading: elements::Heading = self.into();
+ return Box::new(heading);
+ }
}
-pub struct Heading {
- size: u8,
- value: Text,
+impl AST for Noop {
+ fn convert_to_renderable(&self) -> Box<dyn elements::Renderable> {
+ let blank = elements::Paragraph::new(String::new());
+ return Box::new(blank);
+ }
}
pub struct Exp {
+ pub item: Box<dyn AST>,
+}
+
+pub struct Node {
+ pub children: Vec<Exp>,
+}
+
+pub struct Parser {
+ lexer: Lexer,
+ tokens: Peekable<std::vec::IntoIter<Token>>,
+ pub tree: Node,
+}
+
+
+impl Parser {
+ pub fn new(lexer: Lexer) -> Self {
+ let root = Node { children: vec![] };
+ let input_lexer = lexer;
+ let input_tokens = input_lexer.tokens.clone().into_iter().peekable();
+ Parser { lexer: input_lexer, tokens: input_tokens, tree: root }
+ }
+
+ /* Parse a Text block
+ * TEXT
+ */
+ fn text(&mut self) -> Text {
+ match &self.tokens.next() {
+ Some(token) => {
+ if token.token_type == TokenType::TEXT {
+ return Text { token: token.clone(), text: token.value.clone() }
+ }
+ panic!("Invalid expression for text!");
+ },
+ None => { panic!("Invalid expression for text!") }
+ }
+ }
+
+ /* Parse a Heading
+ * HASH heading | HASH text
+ */
+ fn heading(&mut self) -> Heading {
+ let mut heading_size = 0;
+ while self.tokens.peek().unwrap().token_type == TokenType::HASH {
+ heading_size += 1;
+ self.tokens.next();
+ };
+ let heading_text = self.text();
+ return Heading { level: heading_size, text: heading_text }
+ }
+
+ /* exp
+ * text | heading
+ */
+ fn exp(&mut self) -> Exp {
+ let token = self.tokens.peek();
+ if token.is_none() {
+ return Exp {item: Box::new(Noop{}) };
+ }
+ let token = token.unwrap().clone();
+ if token.token_type == TokenType::TEXT {
+ let tree = self.text();
+ return Exp { item: Box::new(tree) };
+ }
+
+ if token.token_type == TokenType::HASH {
+ let tree = self.heading();
+ return Exp { item: Box::new(tree) };
+ }
+
+ panic!("Invalid Exp type!")
+
+ }
+
+ /* Node
+ * exp | exp NEWLINE node
+ */
+ fn node(&mut self) -> Node {
+ let mut node = Node { children: vec![] };
+ let exp = self.exp();
+ node.children.push(exp);
+
+ loop {
+ match self.tokens.peek() {
+ Some(token) => {
+ if token.token_type == TokenType::NEWLINE {
+ self.tokens.next();
+ continue
+ } else {
+ node.children.push(self.exp());
+ }
+ },
+ None => { break }
+ }
+ }
+ return node;
+ }
+
+ pub fn parse(&mut self) {
+ self.tree = self.node();
+ }
}