You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
// See the end of this file for copyright and license terms.
|
|
|
|
use crate::lex::{Lexer, SyntaxError, Token, TokenKind};
|
|
use crate::{Node, NodeVal};
|
|
|
|
pub struct Parser<'a> {
|
|
lexer: Lexer<'a>,
|
|
}
|
|
|
|
impl<'a> Parser<'a> {
|
|
pub const fn new(lexer: Lexer<'a>) -> Parser<'a> {
|
|
Parser { lexer }
|
|
}
|
|
|
|
fn parse_node(&mut self) -> Result<Node, SyntaxError> {
|
|
let ident = self.require_kind(TokenKind::Ident)?;
|
|
self.require_kind(TokenKind::Eq)?;
|
|
let val = self.require_next()?;
|
|
let node = match val.kind {
|
|
TokenKind::TrueKeyword => self.node_result(ident.raw, NodeVal::Bool(true)),
|
|
TokenKind::FalseKeyword => self.node_result(ident.raw, NodeVal::Bool(false)),
|
|
TokenKind::IntLiteral => self.node_result(
|
|
ident.raw,
|
|
NodeVal::Int(val.raw.parse().expect("This shouldn't be possible lol")),
|
|
),
|
|
TokenKind::StringLiteral => self.node_result(ident.raw, NodeVal::String(val.raw)),
|
|
_ => self.lexer.syntax_error(String::from("Expected a value")),
|
|
}?;
|
|
self.require_kind(TokenKind::Semi)?;
|
|
Ok(node)
|
|
}
|
|
|
|
fn require_kind(&mut self, kind: TokenKind) -> Result<Token, SyntaxError> {
|
|
if let Some(res) = self.lexer.next() {
|
|
if let Ok(tok) = res {
|
|
if tok.kind == kind {
|
|
Ok(tok)
|
|
} else {
|
|
self.lexer.syntax_error(format!("Expected {:?}, got {:?}", kind, tok.kind))
|
|
}
|
|
} else {
|
|
res
|
|
}
|
|
} else {
|
|
self.lexer.syntax_error(String::from("Unexpected EOF"))
|
|
}
|
|
}
|
|
|
|
fn require_next(&mut self) -> Result<Token, SyntaxError> {
|
|
match self.lexer.next() {
|
|
Some(result) => result,
|
|
None => self
|
|
.lexer
|
|
.syntax_error(String::from("Unexpected end of file")),
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::unnecessary_wraps)] // Convenience wrapper
|
|
fn node_result<T>(&self, name: String, val: NodeVal) -> Result<Node, T> {
|
|
Ok(self.make_node(name, val))
|
|
}
|
|
|
|
fn make_node(&self, name: String, val: NodeVal) -> Node {
|
|
Node { name, val }
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for Parser<'a> {
|
|
type Item = Result<Node, SyntaxError>;
|
|
|
|
fn next(&mut self) -> Option<Result<Node, SyntaxError>> {
|
|
if let Some(Ok(token)) = self.lexer.peek() {
|
|
if token.kind == TokenKind::EOF {
|
|
return None;
|
|
}
|
|
}
|
|
Some(self.parse_node())
|
|
}
|
|
}
|
|
|
|
// Copyright (C) 2021 Fefie <owo@fef.moe>
|
|
// This file is part of gayconf.
|
|
//
|
|
// gayconf is non-violent software: you can use, redistribute,
|
|
// and/or modify it under the terms of the CNPLv6+ as found
|
|
// in the LICENSE file in the source code root directory or
|
|
// at <https://git.pixie.town/thufie/CNPL>.
|
|
//
|
|
// gayconf comes with ABSOLUTELY NO WARRANTY, to the extent
|
|
// permitted by applicable law. See the CNPL for details.
|