Add parse examples

This commit is contained in:
Jeff 2024-08-07 12:32:18 -04:00
parent e295aebf56
commit 76a67c5117
2 changed files with 79 additions and 1 deletions

View File

@ -7,7 +7,7 @@ use std::num::{ParseFloatError, ParseIntError};
use crate::{Identifier, ReservedIdentifier, Span, Token}; use crate::{Identifier, ReservedIdentifier, Span, Token};
/// Lex the input and return a vector of tokens and their positions. /// Lexes the input and return a vector of tokens and their positions.
/// ///
/// # Examples /// # Examples
/// ``` /// ```

View File

@ -1,7 +1,41 @@
/// Parsing tools.
///
/// This module provides two parsing options:
/// - `parse` convenience function
/// - `Parser` struct, which parses the input a statement at a time
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::{AbstractSyntaxTree, LexError, Lexer, Node, Span, Statement, Token, Value}; use crate::{AbstractSyntaxTree, LexError, Lexer, Node, Span, Statement, Token, Value};
/// Parses the input into an abstract syntax tree.
///
/// # Examples
/// ```
/// # use dust_lang::*;
/// let input = "x = 42";
/// let result = parse(input);
///
/// assert_eq!(
/// result,
/// Ok(AbstractSyntaxTree {
/// nodes: [
/// Node {
/// statement: Statement::Assign(
/// Box::new(Node {
/// statement: Statement::Identifier("x".into()),
/// span: (0, 1),
/// }),
/// Box::new(Node {
/// statement: Statement::Constant(Value::integer(42)),
/// span: (4, 6),
/// })
/// ),
/// span: (0, 6),
/// }
/// ].into(),
/// }),
/// );
/// ```
pub fn parse(input: &str) -> Result<AbstractSyntaxTree, ParseError> { pub fn parse(input: &str) -> Result<AbstractSyntaxTree, ParseError> {
let lexer = Lexer::new(input); let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer); let mut parser = Parser::new(lexer);
@ -20,6 +54,46 @@ pub fn parse(input: &str) -> Result<AbstractSyntaxTree, ParseError> {
Ok(AbstractSyntaxTree { nodes }) Ok(AbstractSyntaxTree { nodes })
} }
/// Low-level tool for parsing the input a statement at a time.
///
/// # Examples
/// ```
/// # use std::collections::VecDeque;
/// # use dust_lang::*;
/// let input = "x = 42";
/// let lexer = Lexer::new(input);
/// let mut parser = Parser::new(lexer);
/// let mut nodes = VecDeque::new();
///
/// loop {
/// let node = parser.parse().unwrap();
///
/// nodes.push_back(node);
///
/// if let Token::Eof = parser.current().0 {
/// break;
/// }
/// }
///
/// assert_eq!(
/// nodes,
/// Into::<VecDeque<Node>>::into([
/// Node {
/// statement: Statement::Assign(
/// Box::new(Node {
/// statement: Statement::Identifier("x".into()),
/// span: (0, 1),
/// }),
/// Box::new(Node {
/// statement: Statement::Constant(Value::integer(42)),
/// span: (4, 6),
/// })
/// ),
/// span: (0, 6),
/// }
/// ]),
/// );
/// ```
pub struct Parser<'src> { pub struct Parser<'src> {
lexer: Lexer<'src>, lexer: Lexer<'src>,
current: (Token, Span), current: (Token, Span),
@ -37,6 +111,10 @@ impl<'src> Parser<'src> {
self.parse_node(0) self.parse_node(0)
} }
pub fn current(&self) -> &(Token, Span) {
&self.current
}
fn next_token(&mut self) -> Result<(), ParseError> { fn next_token(&mut self) -> Result<(), ParseError> {
self.current = self.lexer.next_token()?; self.current = self.lexer.next_token()?;