eww/src/parser/parser.lalrpop
2021-07-19 14:19:46 +02:00

75 lines
2.2 KiB
Text

use std::str::FromStr;
use crate::parser::{lexer::{Token}, ast::{Ast, Span}, parse_error};
use simplexpr::ast::SimplExpr;
use simplexpr;
use lalrpop_util::ParseError;
grammar(file_id: usize);
extern {
type Location = usize;
type Error = parse_error::ParseError;
enum Token {
"(" => Token::LPren,
")" => Token::RPren,
"[" => Token::LBrack,
"]" => Token::RBrack,
"true" => Token::True,
"false" => Token::False,
"string" => Token::StrLit(<String>),
"number" => Token::NumLit(<String>),
"symbol" => Token::Symbol(<String>),
"keyword" => Token::Keyword(<String>),
"simplexpr" => Token::SimplExpr(<String>),
"comment" => Token::Comment,
}
}
pub Toplevel: (Span, Vec<Ast>) = {
<l:@L> <elems:(<Ast>)*> <r:@R> => (Span(l, r, file_id), elems)
}
pub Ast: Ast = {
<l:@L> "(" <elems:(<Ast>)*> ")" <r:@R> => Ast::List(Span(l, r, file_id), elems),
<l:@L> "[" <elems:(<Ast>)*> "]" <r:@R> => Ast::Array(Span(l, r, file_id), elems),
<l:@L> <expr:SimplExpr> <r:@R> => Ast::SimplExpr(Span(l, r, file_id), expr),
<x:Keyword> => x,
<x:Symbol> => x,
<l:@L> <x:Literal> <r:@R> => Ast::Literal(Span(l, r, file_id), x.into()),
<l:@L> "comment" <r:@R> => Ast::Comment(Span(l, r, file_id)),
};
Keyword: Ast = <l:@L> <x:"keyword"> <r:@R> => Ast::Keyword(Span(l, r, file_id), x[1..].to_string());
Symbol: Ast = <l:@L> <x:"symbol"> <r:@R> => Ast::Symbol(Span(l, r, file_id), x.to_string());
Literal: String = {
<StrLit> => <>,
<Num> => <>,
<Bool> => <>,
};
StrLit: String = {
<x:"string"> => {
x[1..x.len() - 1].to_owned()
},
};
SimplExpr: SimplExpr = {
<l:@L> <x:"simplexpr"> =>? {
let expr = x[1..x.len() - 1].to_string();
simplexpr::parse_string(file_id, &expr).map_err(|e| {
let span = e.get_span().map(|simplexpr::Span(simpl_l, simpl_r, file_id)| Span(1 + l + simpl_l, 1 + l + simpl_r, file_id));
ParseError::User { error: parse_error::ParseError::SimplExpr(span, e) }})
}
}
Num: String = <"number"> => <>.to_string();
Bool: String = {
"true" => "true".to_string(),
"false" => "false".to_string(),
}
// vim:shiftwidth=4