This repository has been archived on 2020-09-15. You can view files and clone it, but cannot push or open issues or pull requests.
Files
not-python-old.2020-08-27/src/syn/parser.rs

250 lines
6.7 KiB
Rust
Raw Normal View History

#![allow(dead_code)]
use crate::syn::{ast::*, error::*, lexer::Lexer, span::*, token::*};
use std::{convert::TryFrom, mem};
const EXPR_START: &'static [TokenKind] = &[
TokenKind::Ident,
TokenKind::Num,
TokenKind::Str,
TokenKind::Sym,
TokenKind::LParen,
TokenKind::LBracket,
TokenKind::LBrace,
// TODO unary tokens
];
const VALUE_EXPR_START: &'static [TokenKind] = &[
TokenKind::Ident,
TokenKind::Num,
TokenKind::Str,
TokenKind::Sym,
];
pub struct Parser<'t> {
lexer: Lexer<'t>,
curr_token: Option<Token>,
}
impl<'t> Parser<'t> {
pub fn new(lexer: Lexer<'t>) -> Result<Self> {
let mut parser = Parser {
lexer,
curr_token: None,
};
parser.adv_token()?;
Ok(parser)
}
pub fn is_eof(&self) -> bool {
self.lexer.is_eof()
}
pub fn pos(&self) -> Pos {
self.span().start
}
////////////////////////////////////////////////////////////////////////////////
// Parsing functions
////////////////////////////////////////////////////////////////////////////////
pub fn next_expr(&mut self) -> Result<Expr> {
self.next_bin_expr()
}
fn next_bin_expr(&mut self) -> Result<Expr> {
let lhs = self.next_un_expr()?;
todo!()
}
fn next_un_expr(&mut self) -> Result<Expr> {
todo!()
}
fn next_base_expr(&mut self) -> Result<Expr> {
let token =
self.expect_token_where(|t| VALUE_EXPR_START.contains(&t.kind()), "base expression")?;
let expr: Expr = match token.kind() {
TokenKind::Ident => BaseExpr {
kind: BaseExprKind::Ident,
span: token.span(),
}
.into(),
TokenKind::Num => BaseExpr {
kind: BaseExprKind::Num,
span: token.span(),
}
.into(),
TokenKind::Str => BaseExpr {
kind: BaseExprKind::Str,
span: token.span(),
}
.into(),
TokenKind::Sym => BaseExpr {
kind: BaseExprKind::Sym,
span: token.span(),
}
.into(),
_ => unreachable!(),
};
Ok(expr)
}
fn next_list(&mut self) -> Result<Expr> {
let start_token = self.expect_token_where(|t| t.kind() == TokenKind::LBracket, "start of list (left bracket)")?;
let mut list_items = Vec::new();
while ! matches!(self.curr_token.map(|t| t.kind()), Some(TokenKind::RBrace) | None) {
let expr = self.next_expr()?;
}
let end_token = self.expect_token_where(
|t| t.kind() == TokenKind::RBracket,
"end of list (right bracket)",
)?;
let expr = BaseExpr {
kind: BaseExprKind::List(list_items),
span: start_token.span().union(end_token.span()),
};
Ok(expr.into())
}
////////////////////////////////////////////////////////////////////////////////
// Token matching functions
////////////////////////////////////////////////////////////////////////////////
fn adv_token(&mut self) -> Result<Option<Token>> {
let next_token = self.lexer.next_token()?;
Ok(mem::replace(&mut self.curr_token, next_token))
}
fn match_token_where<P>(&mut self, pred: P) -> Result<Option<Token>>
where
P: Fn(Token) -> bool,
{
match self.curr_token {
Some(curr) if (pred)(curr) => self.adv_token(),
_ => Ok(None),
}
}
fn expect_token_where<P>(&mut self, pred: P, expected: impl ToString) -> Result<Token>
where
P: Fn(Token) -> bool,
{
self.match_token_where(pred)?
.ok_or_else(|| Error::ExpectedGot {
expected: expected.to_string(),
got: self
.curr_token
.map(|token| token.kind().to_string())
.unwrap_or_else(|| "EOF".to_string()),
pos: self.pos(),
})
}
}
impl<'t> Spanned for Parser<'t> {
fn span(&self) -> Span {
self.curr_token
.as_ref()
.map(Spanned::span)
.unwrap_or(Span::default())
}
}
impl<'t> TryFrom<Lexer<'t>> for Parser<'t> {
type Error = Error;
fn try_from(lexer: Lexer<'t>) -> Result<Self> {
Parser::new(lexer)
}
}
impl<'t> TryFrom<&'t str> for Parser<'t> {
type Error = Error;
fn try_from(text: &'t str) -> Result<Self> {
Parser::new(Lexer::new(text))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_adv_token() {
const EXPECTED: &'static [TokenKind] = &[
TokenKind::Num,
TokenKind::Ident,
TokenKind::Sym,
TokenKind::Str,
];
let mut parser = Parser::try_from("1 ident :sym 'string'").unwrap();
for expected in EXPECTED.iter().copied() {
let token = parser.adv_token().unwrap();
let kind = token.unwrap().kind();
assert_eq!(kind, expected);
}
assert!(parser.is_eof());
}
#[test]
fn test_match_token_where() {
let mut parser = Parser::try_from("1 ident :sym 'string'").unwrap();
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Num),
Ok(Some(_))
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Num),
Ok(None)
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Ident),
Ok(Some(_))
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Ident),
Ok(None)
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Sym),
Ok(Some(_))
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Sym),
Ok(None)
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Str),
Ok(Some(_))
));
assert!(matches!(
parser.match_token_where(|token| token.kind() == TokenKind::Str),
Ok(None)
));
assert!(parser.is_eof());
}
#[test]
fn test_base_expr() {
let mut parser = Parser::try_from("1").unwrap();
assert!(matches!(
parser.next_base_expr(),
Ok(
Expr::Base(
BaseExpr {
kind: BaseExprKind::Num,
..
}
)
)
));
}
}