schala/schala-lang/src/parsing/mod.rs

127 lines
3.5 KiB
Rust
Raw Normal View History

2021-10-19 22:24:27 -07:00
#![allow(clippy::upper_case_acronyms)]
2021-11-17 01:54:35 -08:00
pub mod combinator;
2021-11-14 04:25:24 -08:00
mod peg_parser;
2021-11-04 21:11:19 -07:00
mod test;
2021-11-18 01:37:05 -08:00
use std::{cell::RefCell, fmt, rc::Rc};
use combinator::Span;
2018-06-04 19:25:40 -07:00
#[cfg(test)]
use crate::ast::{Block, Expression};
2021-11-14 03:55:35 -08:00
use crate::{
ast::{ASTItem, AST},
identifier::{Id, IdStore},
};
2021-11-20 02:26:22 -08:00
pub(crate) type StoreRef = Rc<RefCell<IdStore<ASTItem>>>;
2021-11-14 03:55:35 -08:00
pub struct Parser {
2021-11-20 02:26:22 -08:00
id_store: StoreRef,
2021-11-20 11:04:56 -08:00
use_combinator: bool,
2021-11-14 03:55:35 -08:00
}
impl Parser {
pub(crate) fn new() -> Self {
2021-11-20 02:26:22 -08:00
let id_store: IdStore<ASTItem> = IdStore::new();
2021-11-20 11:04:56 -08:00
Self { id_store: Rc::new(RefCell::new(id_store)), use_combinator: true }
2021-11-14 03:55:35 -08:00
}
pub(crate) fn parse(&mut self, input: &str) -> Result<AST, ParseError> {
2021-11-20 11:04:56 -08:00
if self.use_combinator {
self.parse_comb(input)
} else {
self.parse_peg(input)
}
}
pub(crate) fn parse_peg(&mut self, input: &str) -> Result<AST, ParseError> {
peg_parser::schala_parser::program(input, self).map_err(ParseError::from_peg)
}
2021-11-18 15:17:47 -08:00
pub(crate) fn parse_comb(&mut self, input: &str) -> Result<AST, ParseError> {
2021-11-20 02:26:22 -08:00
let span = Span::new_extra(input, self.id_store.clone());
2021-11-20 02:33:09 -08:00
convert(input, combinator::program(span))
2021-11-18 15:17:47 -08:00
}
#[cfg(test)]
fn expression(&mut self, input: &str) -> Result<Expression, ParseError> {
peg_parser::schala_parser::expression(input, self).map_err(ParseError::from_peg)
}
2021-11-14 03:55:35 -08:00
2021-11-17 16:53:03 -08:00
#[cfg(test)]
fn expression_comb(&mut self, input: &str) -> Result<Expression, ParseError> {
2021-11-20 02:26:22 -08:00
let span = Span::new_extra(input, self.id_store.clone());
2021-11-20 02:33:09 -08:00
convert(input, combinator::expression(span))
2021-11-17 16:53:03 -08:00
}
#[cfg(test)]
fn block(&mut self, input: &str) -> Result<Block, ParseError> {
peg_parser::schala_parser::block(input, self).map_err(ParseError::from_peg)
2021-11-14 03:55:35 -08:00
}
2021-11-18 01:37:05 -08:00
#[cfg(test)]
fn block_comb(&mut self, input: &str) -> Result<Block, ParseError> {
2021-11-20 02:26:22 -08:00
let span = Span::new_extra(input, self.id_store.clone());
2021-11-20 02:33:09 -08:00
convert(input, combinator::block(span))
2021-11-18 01:37:05 -08:00
}
2021-11-14 03:55:35 -08:00
fn fresh(&mut self) -> Id<ASTItem> {
2021-11-20 02:26:22 -08:00
self.id_store.borrow_mut().fresh()
2021-11-14 03:55:35 -08:00
}
}
2021-11-20 02:33:09 -08:00
fn convert<'a, O>(input: &'a str, result: combinator::ParseResult<'a, O>) -> Result<O, ParseError> {
2021-11-20 22:55:11 -08:00
use nom::{error::VerboseError, Finish};
2021-11-20 02:33:09 -08:00
match result.finish() {
Ok((rest, output)) => {
if rest.fragment() != &"" {
return Err(ParseError {
location: Default::default(),
msg: format!("Bad parse state, remaining text: `{}`", rest.fragment()),
});
}
Ok(output)
}
Err(err) => {
let err = VerboseError {
errors: err.errors.into_iter().map(|(sp, kind)| (*sp.fragment(), kind)).collect(),
};
let msg = nom::error::convert_error(input, err);
Err(ParseError { msg, location: (0).into() })
}
}
}
/// Represents a parsing error
#[derive(Debug)]
2017-09-11 02:07:17 -07:00
pub struct ParseError {
pub msg: String,
2021-11-14 02:15:08 -08:00
pub location: Location,
}
impl ParseError {
fn from_peg(err: peg::error::ParseError<peg::str::LineCol>) -> Self {
let msg = err.to_string();
Self { msg, location: err.location.offset.into() }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Location {
pub(crate) offset: usize,
2017-09-11 02:07:17 -07:00
}
2017-09-09 00:31:15 -07:00
impl From<usize> for Location {
fn from(offset: usize) -> Self {
Self { offset }
}
2017-09-11 23:27:15 -07:00
}
impl fmt::Display for Location {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.offset)
}
2018-01-08 05:57:36 -08:00
}