This commit is contained in:
elkowar 2021-07-01 20:38:23 +02:00
parent e21983f92d
commit a06927e356
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
6 changed files with 99 additions and 97 deletions

9
Cargo.lock generated
View file

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
@ -256,6 +258,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "memchr"
version = "2.4.0"
@ -276,6 +284,7 @@ dependencies = [
"itertools",
"lalrpop",
"lalrpop-util",
"maplit",
"regex",
]

View file

@ -13,6 +13,7 @@ lalrpop-util = "0.19.5"
regex = "1"
itertools = "0.10"
anyhow = "1.0"
maplit = "*"
[build-dependencies]
lalrpop = "0.19.5"

View file

@ -1,6 +1,7 @@
use std::{collections::HashMap, iter::FromIterator};
use super::*;
use crate::error::*;
use anyhow::*;
use itertools::Itertools;
use std::collections::LinkedList;
@ -9,34 +10,8 @@ type VarName = String;
type AttrValue = String;
type AttrName = String;
#[derive(Debug, PartialEq, Eq)]
pub enum AstError {
UnexpectedNode,
InvalidDefinition,
WrongExprType(Sp<Expr>),
MissingNode,
}
trait OptionAstErrorExt<T> {
fn or_missing(self) -> Result<T, AstError>;
}
impl<T> OptionAstErrorExt<T> for Option<T> {
fn or_missing(self) -> Result<T, AstError> {
self.ok_or(AstError::MissingNode)
}
}
impl From<WrongExprType> for AstError {
fn from(_: WrongExprType) -> Self {
AstError::WrongExprType
}
}
pub trait FromExpr: Sized {
fn from_expr(e: Expr) -> Result<Self, AstError>;
fn from_sp(e: Sp<Expr>) -> Result<Self, AstError> {
Self::from_expr(e.1)
}
}
impl FromExpr for Expr {
@ -51,7 +26,7 @@ pub enum DefType {
impl FromExpr for DefType {
fn from_expr(e: Expr) -> Result<Self, AstError> {
if let Expr::Symbol(sym) = e {
if let Expr::Symbol(_, sym) = e {
match sym.as_str() {
"defwidget" => Ok(DefType::Widget),
_ => Err(AstError::InvalidDefinition),
@ -65,20 +40,22 @@ impl FromExpr for DefType {
pub struct Definitional<T> {
def_type: DefType,
name: String,
attrs: HashMap<AttrName, Sp<Expr>>,
attrs: HashMap<AttrName, Expr>,
children: Vec<T>,
}
impl<T: FromExpr> FromExpr for Definitional<T> {
fn from_expr(e: Expr) -> Result<Self, AstError> {
if let Expr::List(list) = e {
if let Expr::List(span, list) = e {
let mut iter = itertools::put_back(list.into_iter());
let def_type = DefType::from_sp(iter.next().or_missing()?)?;
let name = iter.next().or_missing()?.1.str()?;
let def_type = DefType::from_expr(iter.next().or_missing()?)?;
let name = iter.next().or_missing()?.as_str()?;
let attrs = parse_key_values(&mut iter);
let children = iter.map(T::from_sp).collect::<Result<Vec<_>, AstError>>()?;
let children = iter
.map(T::from_expr)
.collect::<Result<Vec<_>, AstError>>()?;
Ok(Definitional {
def_type,
name,
@ -93,16 +70,16 @@ impl<T: FromExpr> FromExpr for Definitional<T> {
#[derive(Debug, Eq, PartialEq)]
pub struct Element<T> {
name: String,
attrs: HashMap<AttrName, Sp<Expr>>,
attrs: HashMap<AttrName, Expr>,
children: Vec<T>,
}
impl FromExpr for Element<Sp<Expr>> {
impl FromExpr for Element<Expr> {
fn from_expr(e: Expr) -> Result<Self, AstError> {
if let Expr::List(list) = e {
if let Expr::List(span, list) = e {
let mut iter = itertools::put_back(list.into_iter());
let name = iter.next().or_missing()?.1.str()?;
let name = iter.next().or_missing()?.as_symbol()?;
let attrs = parse_key_values(&mut iter);
Ok(Element {
@ -116,18 +93,18 @@ impl FromExpr for Element<Sp<Expr>> {
}
}
fn parse_key_values<I: Iterator<Item = Sp<Expr>>>(
fn parse_key_values<I: Iterator<Item = Expr>>(
iter: &mut itertools::PutBack<I>,
) -> HashMap<String, Sp<Expr>> {
) -> HashMap<String, Expr> {
let mut data = HashMap::new();
loop {
match iter.next() {
Some(Sp(l, Expr::Keyword(kw), r)) => match iter.next() {
Some(Expr::Keyword(span, kw)) => match iter.next() {
Some(value) => {
data.insert(kw, value);
}
None => {
iter.put_back(Sp(l, Expr::Keyword(kw), r));
iter.put_back(Expr::Keyword(span, kw));
return data;
}
},
@ -149,28 +126,24 @@ mod test {
fn test() {
let parser = parser::ExprParser::new();
assert_eq!(
Element::<Sp<Expr>>::from_expr(
parser
.parse("(box foo :bar 12 :baz \"hi\" foo (bar))")
.unwrap()
Element::<Expr>::from_expr(
parser.parse("(box :bar 12 :baz \"hi\" foo (bar))").unwrap()
)
.unwrap(),
Element {
name: "box".to_string(),
children: vec![
Sp(1, Expr::Symbol("foo".to_string()), 2),
Sp(
2,
Expr::List(vec![Sp(2, Expr::Symbol("bar".to_string()), 3)]),
3
)
],
attrs: {
let mut data = HashMap::new();
data.insert("foo".to_string(), Sp(2, Expr::Number(12), 3));
data.insert("bar".to_string(), Sp(2, Expr::Str("hi".to_string()), 3));
data
attrs: maplit::hashmap! {
":bar".to_string() => Expr::Number(Span(10, 12), 12),
":baz".to_string() => Expr::Str(Span(18, 22), "hi".to_string()),
},
children: vec![
Expr::Symbol(Span(23, 26), "foo".to_string()),
Expr::List(
Span(27, 32),
vec![Expr::Symbol(Span(28, 31), "bar".to_string())]
),
],
}
);
}

18
src/error.rs Normal file
View file

@ -0,0 +1,18 @@
use crate::Expr;
#[derive(Debug, PartialEq, Eq)]
pub enum AstError {
UnexpectedNode,
InvalidDefinition,
WrongExprType(Expr),
MissingNode,
}
pub trait OptionAstErrorExt<T> {
fn or_missing(self) -> Result<T, AstError>;
}
impl<T> OptionAstErrorExt<T> for Option<T> {
fn or_missing(self) -> Result<T, AstError> {
self.ok_or(AstError::MissingNode)
}
}

View file

@ -2,6 +2,8 @@
#![allow(unused)]
mod config;
mod error;
use error::AstError;
use std::ops::Deref;
@ -14,39 +16,43 @@ use lalrpop_util::lalrpop_mod;
lalrpop_mod!(pub parser);
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct Sp<T>(pub usize, pub T, pub usize);
pub struct Span(pub usize, pub usize);
impl<T: std::fmt::Display> std::fmt::Display for Sp<T> {
impl std::fmt::Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<{}- {} -{}>", self.0, self.1, self.2)
write!(f, "<{}..{}>", self.0, self.1)
}
}
#[derive(Debug, Clone)]
pub struct WrongExprType(Sp<Expr>);
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Expr {
List(Vec<Sp<Expr>>),
Table(Vec<(Sp<Expr>, Sp<Expr>)>),
Keyword(String),
Symbol(String),
Str(String),
Number(i32),
List(Span, Vec<Expr>),
Table(Span, Vec<(Expr, Expr)>),
Keyword(Span, String),
Symbol(Span, String),
Str(Span, String),
Number(Span, i32),
Comment,
}
impl Expr {
fn str(self) -> Result<String, WrongExprType> {
use Expr::*;
macro_rules! as_func {
($name:ident<$t:ty> = $p:pat => $value:expr) => {
fn $name(self) -> Result<$t, AstError> {
match self {
Str(x) => Ok(x),
x => Err(WrongExprType(x)),
$p => Ok($value),
x => Err(AstError::WrongExprType(x)),
}
}
};
}
impl Expr {
as_func!(as_str<String> = Expr::Str(_, x) => x);
as_func!(as_symbol<String> = Expr::Symbol(_, x) => x);
fn is_keyword(&self) -> bool {
match self {
Expr::Keyword(_) => true,
Expr::Keyword(_, _) => true,
_ => false,
}
}
@ -56,16 +62,16 @@ impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Expr::*;
match self {
Number(x) => write!(f, "{}", x),
List(x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
Table(x) => write!(
Number(_, x) => write!(f, "{}", x),
List(_, x) => write!(f, "({})", x.iter().map(|e| format!("{}", e)).join(" ")),
Table(_, x) => write!(
f,
"{{{}}}",
x.iter().map(|(k, v)| format!("{} {}", k, v)).join(" ")
),
Keyword(x) => write!(f, "{}", x),
Symbol(x) => write!(f, "{}", x),
Str(x) => write!(f, "{}", x),
Keyword(_, x) => write!(f, "{}", x),
Symbol(_, x) => write!(f, "{}", x),
Str(_, x) => write!(f, "{}", x),
Comment => write!(f, ""),
}
}

View file

@ -1,34 +1,29 @@
use std::str::FromStr;
//use crate::lexer;
use crate::Expr;
use crate::Sp;
use crate::Span;
grammar;
Span<T>: Sp<T> = {
<@L> <T> <@R> => Sp(<>)
};
pub Expr: Expr = {
"(" <elems:(<Span<(<Expr>)>>)+> ")" => Expr::List(elems),
<l:@L> "(" <elems:(<Expr>)+> ")" <r:@R> => Expr::List(Span(l, r), elems),
"{" <elems:(<Span<(<Expr>)>> <Span<(<Expr>)>>)*> "}" => Expr::Table(elems),
<l:@L> "{" <elems:(<(<Expr>)> <(<Expr>)>)*> "}" <r:@R> => Expr::Table(Span(l, r), elems),
<x:Keyword> => x,
<x:Symbol> => x,
<x:StrLit> => Expr::Str(x),
<x:Num> => Expr::Number(x),
<l:@L> <x:StrLit> <r:@R> => Expr::Str(Span(l, r), x),
<l:@L> <x:Num> <r:@R> => Expr::Number(Span(l, r), x),
Comment => Expr::Comment,
};
Keyword: Expr = <r":[^\s]+"> => Expr::Keyword(<>.to_string());
Symbol: Expr = <r"[a-zA-Z_!\?<>/.*-+][^\s{}\(\)]*"> => Expr::Symbol(<>.to_string());
Keyword: Expr = <l:@L> <x:r":[^\s]+"> <r:@R> => Expr::Keyword(Span(l, r), x.to_string());
Symbol: Expr = <l:@L> <x:r"[a-zA-Z_!\?<>/.*-+][^\s{}\(\)]*"> <r:@R> => Expr::Symbol(Span(l, r), x.to_string());
StrLit: String = {
r#""(?:[^"\\]|\\.)*""# => {
let val = <>;
val[1..val.len() - 1].to_owned()
<x:r#""(?:[^"\\]|\\.)*""#> => {
x[1..x.len() - 1].to_owned()
},
}