Minor WithSource cleanup
This commit is contained in:
parent
a0edf84c01
commit
10a324172b
131
src/ast.rs
131
src/ast.rs
|
@ -1,12 +1,12 @@
|
|||
use std::fmt::Debug;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt::Debug, ops::Deref};
|
||||
|
||||
use logos::{Lexer, Logos};
|
||||
|
||||
#[derive(Logos, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Logos, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[logos(subpattern ident = r"[a-zA-Z][a-zA-Z0-9]*")]
|
||||
pub enum Token {
|
||||
pub enum TokenKind {
|
||||
#[token("(")]
|
||||
ParenOpen,
|
||||
|
||||
|
@ -39,16 +39,16 @@ pub enum Token {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SpannedToken {
|
||||
pub kind: Token,
|
||||
pub struct TokenInner {
|
||||
pub kind: TokenKind,
|
||||
pub content: String,
|
||||
pub source: Arc<Source>,
|
||||
pub range: SourceRange,
|
||||
}
|
||||
|
||||
pub type Token = WithSource<TokenInner>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AstBuilder<'a> {
|
||||
lexer: Lexer<'a, Token>,
|
||||
lexer: Lexer<'a, TokenKind>,
|
||||
source: &'a Arc<Source>,
|
||||
current_row_idx: usize,
|
||||
current_row_start: usize,
|
||||
|
@ -58,7 +58,7 @@ pub struct AstBuilder<'a> {
|
|||
impl<'a> AstBuilder<'a> {
|
||||
pub fn new(source: &'a Arc<Source>) -> Self {
|
||||
Self {
|
||||
lexer: Token::lexer(&source.full),
|
||||
lexer: TokenKind::lexer(&source.full),
|
||||
current_row_idx: 0,
|
||||
current_row_start: 0,
|
||||
paren_level: 0,
|
||||
|
@ -84,17 +84,17 @@ impl<'a> AstBuilder<'a> {
|
|||
self.span_to_range(self.lexer.span())
|
||||
}
|
||||
|
||||
pub fn make_error(&self, kind: ParseErrorKind, range: SourceRange) -> ParseError {
|
||||
ParseError {
|
||||
pub fn with_source<T>(&self, inner: T, range: SourceRange) -> WithSource<T> {
|
||||
WithSource {
|
||||
inner,
|
||||
source: self.source.clone(),
|
||||
kind,
|
||||
range,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn token_to_string(&self, token: SpannedToken) -> ParseResult<WithSource<String>> {
|
||||
pub fn token_to_string(&self, token: Token) -> ParseResult<WithSource<String>> {
|
||||
match token.kind {
|
||||
Token::String => {
|
||||
TokenKind::String => {
|
||||
let slice = self.lexer.slice();
|
||||
let end = slice.len() - 1;
|
||||
let inner = slice[1..end].to_string();
|
||||
|
@ -104,57 +104,56 @@ impl<'a> AstBuilder<'a> {
|
|||
range: token.range,
|
||||
})
|
||||
}
|
||||
Token::Symbol => Ok(WithSource {
|
||||
inner: token.content,
|
||||
TokenKind::Symbol => Ok(WithSource {
|
||||
inner: token.content.clone(),
|
||||
source: token.source,
|
||||
range: token.range,
|
||||
}),
|
||||
Token::Keyword => Ok(WithSource {
|
||||
TokenKind::Keyword => Ok(WithSource {
|
||||
inner: token.content[1..].to_string(),
|
||||
source: token.source,
|
||||
range: token.range,
|
||||
}),
|
||||
_ => Err(self.make_error(
|
||||
ParseErrorKind::UnexpectedToken(token.kind, None),
|
||||
token.range,
|
||||
)),
|
||||
_ => Err(token.map(ParseErrorKind::UnexpectedToken(token.kind, None))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> ParseResult<SpannedToken> {
|
||||
pub fn next(&mut self) -> ParseResult<Token> {
|
||||
loop {
|
||||
let token = self.lexer.next().unwrap_or(Token::Eof);
|
||||
let token = self.lexer.next().unwrap_or(TokenKind::Eof);
|
||||
let span = self.lexer.span();
|
||||
if let Token::Newline = token {
|
||||
if let TokenKind::Newline = token {
|
||||
self.current_row_idx += 1;
|
||||
self.current_row_start = span.start;
|
||||
} else if let Token::Error = token {
|
||||
} else if let TokenKind::Error = token {
|
||||
let range = self.span_to_range(span);
|
||||
break Err(self.make_error(ParseErrorKind::InvalidToken, range));
|
||||
break Err(self.with_source(ParseErrorKind::InvalidToken, range));
|
||||
} else {
|
||||
let range = self.span_to_range(span);
|
||||
|
||||
if let Token::ParenOpen = token {
|
||||
if let TokenKind::ParenOpen = token {
|
||||
self.paren_level += 1;
|
||||
}
|
||||
|
||||
if let Token::ParenClose = token {
|
||||
if let TokenKind::ParenClose = token {
|
||||
if self.paren_level == 0 {
|
||||
return Err(self.make_error(ParseErrorKind::UnmatchedParen, range));
|
||||
return Err(self.with_source(ParseErrorKind::UnmatchedParen, range));
|
||||
}
|
||||
|
||||
self.paren_level -= 1;
|
||||
}
|
||||
|
||||
if let Token::Eof = token {
|
||||
if let TokenKind::Eof = token {
|
||||
if self.paren_level > 0 {
|
||||
return Err(self.make_error(ParseErrorKind::UnmatchedParen, range));
|
||||
return Err(self.with_source(ParseErrorKind::UnmatchedParen, range));
|
||||
}
|
||||
}
|
||||
|
||||
break Ok(SpannedToken {
|
||||
kind: token,
|
||||
content: self.lexer.slice().to_string(),
|
||||
break Ok(Token {
|
||||
inner: TokenInner {
|
||||
kind: token,
|
||||
content: self.lexer.slice().to_string(),
|
||||
},
|
||||
source: self.source.to_owned(),
|
||||
range,
|
||||
});
|
||||
|
@ -162,11 +161,10 @@ impl<'a> AstBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn expect_next(&mut self) -> ParseResult<SpannedToken> {
|
||||
pub fn expect_next(&mut self) -> ParseResult<Token> {
|
||||
let tok = self.next()?;
|
||||
if let Token::Eof = tok.kind {
|
||||
let range = self.span_to_range(self.lexer.span());
|
||||
Err(self.make_error(ParseErrorKind::UnexpectedEof, range))
|
||||
if let TokenKind::Eof = tok.kind {
|
||||
Err(tok.map(ParseErrorKind::UnexpectedEof))
|
||||
} else {
|
||||
Ok(tok)
|
||||
}
|
||||
|
@ -177,9 +175,9 @@ impl<'a> AstBuilder<'a> {
|
|||
let children = loop {
|
||||
let token = self.next()?;
|
||||
match token.kind {
|
||||
Token::Eof => break vec![],
|
||||
Token::ParenClose => break vec![],
|
||||
Token::Keyword => {
|
||||
TokenKind::Eof => break vec![],
|
||||
TokenKind::ParenClose => break vec![],
|
||||
TokenKind::Keyword => {
|
||||
let name = self.token_to_string(token)?;
|
||||
let val = self.expect_value()?;
|
||||
args.insert(Arg { name, val })?;
|
||||
|
@ -191,8 +189,8 @@ impl<'a> AstBuilder<'a> {
|
|||
Ok(TagBody { args, children })
|
||||
}
|
||||
|
||||
pub fn parse_list_from(&mut self, mut token: SpannedToken) -> ParseResult<Vec<Value>> {
|
||||
if let Token::Symbol = token.kind {
|
||||
pub fn parse_list_from(&mut self, mut token: Token) -> ParseResult<Vec<Value>> {
|
||||
if let TokenKind::Symbol = token.kind {
|
||||
let start = token.range.start.clone();
|
||||
let id = self.token_to_string(token)?;
|
||||
let body = self.parse_tag_body()?;
|
||||
|
@ -214,12 +212,12 @@ impl<'a> AstBuilder<'a> {
|
|||
Ok(vals)
|
||||
}
|
||||
|
||||
pub fn parse_value_from(&mut self, token: SpannedToken) -> ParseResult<Option<Value>> {
|
||||
pub fn parse_value_from(&mut self, token: Token) -> ParseResult<Option<Value>> {
|
||||
match token.kind {
|
||||
Token::Eof | Token::ParenClose => Ok(None),
|
||||
Token::String => Ok(Some(self.token_to_string(token)?.to_val_string())),
|
||||
Token::Symbol => Ok(Some(self.token_to_string(token)?.to_val_symbol())),
|
||||
Token::ParenOpen => {
|
||||
TokenKind::Eof | TokenKind::ParenClose => Ok(None),
|
||||
TokenKind::String => Ok(Some(self.token_to_string(token)?.to_val_string())),
|
||||
TokenKind::Symbol => Ok(Some(self.token_to_string(token)?.to_val_symbol())),
|
||||
TokenKind::ParenOpen => {
|
||||
let start = token.range.end;
|
||||
let next = self.expect_next()?;
|
||||
let vals = self.parse_list_from(next)?;
|
||||
|
@ -230,17 +228,14 @@ impl<'a> AstBuilder<'a> {
|
|||
range: start..end,
|
||||
}))
|
||||
}
|
||||
_ => Err(self.make_error(
|
||||
ParseErrorKind::UnexpectedToken(token.kind, None),
|
||||
self.span_to_range(self.lexer.span()),
|
||||
)),
|
||||
_ => Err(token.map(ParseErrorKind::UnexpectedToken(token.kind, None))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_value(&mut self) -> ParseResult<Value> {
|
||||
let next = self.expect_next()?;
|
||||
self.parse_value_from(next)?
|
||||
.ok_or_else(|| self.make_error(ParseErrorKind::UnexpectedEof, self.lexer_range()))
|
||||
.ok_or_else(|| self.with_source(ParseErrorKind::UnexpectedEof, self.lexer_range()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,6 +268,14 @@ impl<T> AsRef<T> for WithSource<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for WithSource<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl WithSource<String> {
|
||||
pub fn to_val_string(self) -> Value {
|
||||
Value {
|
||||
|
@ -291,6 +294,16 @@ impl WithSource<String> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> WithSource<T> {
|
||||
pub fn map<O>(&self, other: O) -> WithSource<O> {
|
||||
WithSource {
|
||||
inner: other,
|
||||
source: self.source.to_owned(),
|
||||
range: self.range.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Args(Vec<Arg>);
|
||||
|
||||
|
@ -303,9 +316,9 @@ impl Args {
|
|||
for existing in self.0.iter() {
|
||||
if arg.name.inner == existing.name.inner {
|
||||
return Err(ParseError {
|
||||
kind: ParseErrorKind::DuplicateArgument(arg.name.inner),
|
||||
source: arg.name.source,
|
||||
range: arg.name.range,
|
||||
inner: ParseErrorKind::DuplicateArgument(arg.name.inner),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -356,20 +369,14 @@ pub struct SourcePosition {
|
|||
}
|
||||
|
||||
pub type SourceRange = Range<SourcePosition>;
|
||||
pub type ParseError = WithSource<ParseErrorKind>;
|
||||
pub type ParseResult<T> = Result<T, ParseError>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParseError {
|
||||
pub source: Arc<Source>,
|
||||
pub range: SourceRange,
|
||||
pub kind: ParseErrorKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ParseErrorKind {
|
||||
InvalidToken,
|
||||
DuplicateArgument(String),
|
||||
UnmatchedParen,
|
||||
UnexpectedToken(Token, Option<Token>),
|
||||
UnexpectedToken(TokenKind, Option<TokenKind>),
|
||||
UnexpectedEof,
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ fn main() {
|
|||
let src_path = std::env::args().nth(1).unwrap();
|
||||
let src = std::fs::read_to_string(src_path).unwrap();
|
||||
|
||||
let mut lexer = ast::Token::lexer(&src);
|
||||
let lexer = ast::TokenKind::lexer(&src);
|
||||
let tokens: Vec<_> = lexer.collect();
|
||||
println!("{:?}", tokens);
|
||||
|
||||
|
|
Loading…
Reference in New Issue