improve readability and stuff idk and also rustfmt

This commit is contained in:
anna 2021-04-18 17:55:25 +02:00
parent 01e9bd2a48
commit 60076379eb
Signed by: fef
GPG key ID: EC22E476DC2D3D84
5 changed files with 80 additions and 84 deletions

View file

@ -13,10 +13,12 @@ fn main() {
let s = fs::read_to_string(&argv[1]).expect("Cannot open file");
match Config::parse(s.chars()) {
Ok(conf) => for k in conf.keys() {
println!("{:?}", conf.get_node(k));
},
Err(e) => panic!("{:?}", e.msg)
Ok(conf) => {
for k in conf.keys() {
println!("{:?}", conf.get_node(k));
}
}
Err(e) => panic!("{:?}", e.msg),
}
}

View file

@ -32,25 +32,22 @@ impl<'a> Cursor<'a> {
pub fn advance_by(&mut self, n: usize) -> Result<(), usize> {
for i in 0..n {
if self.next() == None {
return Err(i)
return Err(i);
}
}
Ok(())
}
pub fn next_until(&mut self, test: fn (c: char) -> bool) -> String {
pub fn next_until(&mut self, test: fn(c: char) -> bool) -> String {
let mut s = String::new();
for _ in 0.. {
match self.peek() {
Some(c) => if test(c) {
break;
} else {
s.push(c);
self.next();
},
None => break,
while let Some(c) = self.peek() {
if test(c) {
break;
} else {
s.push(c);
self.next();
}
}

View file

@ -1,10 +1,11 @@
// See the end of this file for copyright and license terms.
use std::any::Any;
use std::str::Chars;
mod cursor;
use cursor::Cursor;
use std::any::Any;
mod cursor;
pub struct Lexer<'a> {
cursor: Cursor<'a>,
@ -61,7 +62,7 @@ impl Iterator for Lexer<'_> {
'"' => self.read_string(),
c @ '0'..='9' => Ok(self.read_int_rest(c)),
c @ '1'..='9' => Ok(self.read_int_rest(c)),
c @ 'a'..='z' | c @ 'A'..='Z' => Ok(self.read_keyword_or_ident(c)),
@ -70,7 +71,7 @@ impl Iterator for Lexer<'_> {
}
}
impl <'a> Lexer<'a> {
impl<'a> Lexer<'a> {
pub const fn new(stream: Chars<'a>) -> Lexer<'a> {
Lexer {
cursor: Cursor::new(stream),
@ -97,17 +98,21 @@ impl <'a> Lexer<'a> {
fn read_keyword_or_ident(&mut self, first: char) -> Token {
let kind = match first {
't' => if self.skip_if_match(String::from("rue")) {
TokenKind::TrueKeyword
} else {
TokenKind::Ident(self.read_ident_rest(first))
},
't' => {
if self.skip_if_match(String::from("rue")) {
TokenKind::TrueKeyword
} else {
TokenKind::Ident(self.read_ident_rest(first))
}
}
'f' => if self.skip_if_match(String::from("alse")) {
TokenKind::FalseKeyword
} else {
TokenKind::Ident(self.read_ident_rest(first))
},
'f' => {
if self.skip_if_match(String::from("alse")) {
TokenKind::FalseKeyword
} else {
TokenKind::Ident(self.read_ident_rest(first))
}
}
_ => TokenKind::Ident(self.read_ident_rest(first)),
};
@ -118,10 +123,10 @@ impl <'a> Lexer<'a> {
fn read_ident_rest(&mut self, first: char) -> String {
let mut s = String::from(first);
s += self.cursor.next_until(|c| match c {
'A'..='Z' | 'a'..='z' | '0'..='9' | '_' => false,
_ => true,
}).as_str();
s += self
.cursor
.next_until(|c| !matches!(c, 'A'..='Z' | 'a'..='z' | '0'..='9' | '_'))
.as_str();
s
}
@ -158,26 +163,17 @@ impl <'a> Lexer<'a> {
fn read_int_rest(&mut self, first: char) -> Token {
let mut s = String::from(first);
loop {
match self.cursor.peek() {
Some(c @ '0'..='9') => {
s.push(c);
self.cursor.next();
},
_ => break,
}
}
s.push_str(&self.cursor.next_until(|c| !matches!(c, '0'..='9')));
self.make_token(TokenKind::IntLiteral(
s.parse().expect("this shouldn't be possible lol")
s.parse().expect("this shouldn't be possible lol"),
))
}
fn read_whitespace(&mut self) -> Option<Token> {
let ws = self.cursor.next_until(|c| !is_whitespace(c));
if ws.len() > 0 {
if !ws.is_empty() {
Some(self.make_token(TokenKind::Whitespace(ws)))
} else {
None
@ -193,13 +189,15 @@ impl <'a> Lexer<'a> {
}
}
self.cursor.advance_by(s.len()).expect("this shouldn't be possible lol");
self.cursor
.advance_by(s.len())
.expect("this shouldn't be possible lol");
true
}
fn make_token(&mut self, kind: TokenKind) -> Token {
let t = Token {
kind: kind,
kind,
line: self.token_line,
col: self.token_col,
};
@ -212,10 +210,7 @@ impl <'a> Lexer<'a> {
}
fn is_whitespace(c: char) -> bool {
match c {
' ' | '\n' | '\t' => true,
_ => false,
}
matches!(c, ' ' | '\n' | '\t')
}
pub struct SyntaxError {

View file

@ -1,12 +1,13 @@
// See the end of this file for copyright and license terms.
use std::str::Chars;
use std::collections::HashMap;
use std::str::Chars;
pub mod lex;
use crate::lex::{Lexer, SyntaxError};
pub mod parser;
use parser::Parser;
use std::collections::hash_map::Keys;
@ -25,14 +26,12 @@ impl Config {
Ok(node) => {
let name = node.name.clone();
nodes.insert(name, node);
},
}
Err(err) => return Err(err),
}
}
Ok(Config {
nodes
})
Ok(Config { nodes })
}
pub fn keys(&self) -> Keys<String, Node> {

View file

@ -1,69 +1,72 @@
// See the end of this file for copyright and license terms.
use crate::lex::{Token, TokenKind, Lexer, SyntaxError};
use crate::{Node, NodeVal};
use std::any::Any;
use crate::lex::{Lexer, SyntaxError, Token, TokenKind};
use crate::{Node, NodeVal};
pub struct Parser<'a> {
lexer: Lexer<'a>,
}
impl <'a> Parser<'a> {
impl<'a> Parser<'a> {
pub const fn new(lexer: Lexer<'a>) -> Parser<'a> {
Parser {
lexer
}
Parser { lexer }
}
fn parse_node(&mut self) -> Option<Result<Node, SyntaxError>> {
Some(self.lexer.next()?.and_then(|token| match token.kind {
TokenKind::Ident(name) => {
self.require_kind(TokenKind::Eq ).and_then(|_| {
self.require_next()
}).and_then(|token| match token.kind {
TokenKind::TrueKeyword => self.node_result(name, NodeVal::Bool(true)),
TokenKind::FalseKeyword => self.node_result(name, NodeVal::Bool(false)),
TokenKind::IntLiteral(i) => self.node_result(name, NodeVal::Int(i)),
TokenKind::StringLiteral(s) => self.node_result(name, NodeVal::String(s)),
_ => self.lexer.syntax_error(String::from("Expected a value")),
}).and_then(|node| {
self.require_kind(TokenKind::Semi).and_then(|_| Ok(node))
})
},
_ => self.lexer.syntax_error(String::from("Expected identifier")),
Some(self.lexer.next()?.and_then(|token| {
match token.kind {
TokenKind::Ident(name) => self
.require_kind(TokenKind::Eq)
.and_then(|_| self.require_next())
.and_then(|token| match token.kind {
TokenKind::TrueKeyword => self.node_result(name, NodeVal::Bool(true)),
TokenKind::FalseKeyword => self.node_result(name, NodeVal::Bool(false)),
TokenKind::IntLiteral(i) => self.node_result(name, NodeVal::Int(i)),
TokenKind::StringLiteral(s) => self.node_result(name, NodeVal::String(s)),
_ => self.lexer.syntax_error(String::from("Expected a value")),
})
.and_then(|node| self.require_kind(TokenKind::Semi).and_then(|_| Ok(node))),
_ => self.lexer.syntax_error(String::from("Expected identifier")),
}
}))
}
fn require_kind(&mut self, kind: TokenKind) -> Result<Token, SyntaxError> {
self.require_next().and_then(|token|
self.require_next().and_then(|token| {
if token.kind.type_id() == kind.type_id() {
Ok(token)
} else {
self.lexer.syntax_error(format!("Expected {:?}, got {:?}", kind, token.kind))
self.lexer
.syntax_error(format!("Expected {:?}, got {:?}", kind, token.kind))
}
)
})
}
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")),
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: String::from(name),
name,
val,
}
}
}
impl <'a> Iterator for Parser<'a> {
impl<'a> Iterator for Parser<'a> {
type Item = Result<Node, SyntaxError>;
fn next(&mut self) -> Option<Result<Node, SyntaxError>> {