wip parser

This commit is contained in:
Michael Sippel 2023-10-15 11:47:06 +02:00
parent 73817529d6
commit 7988c8a2e1
Signed by: senvas
GPG key ID: F96CF119C34B64A6
5 changed files with 324 additions and 1 deletions

123
src/ast.rs Normal file
View file

@ -0,0 +1,123 @@
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
#[derive(Debug)]
pub enum Command {
Simple {
assignments: Vec<(String, Word)>,
command_word: Word,
redirections: Vec<Redirection>
},
Pipeline(Vec<Command>),
Sequence(Vec<Command>),
ShortCircuitConjection(Vec<Command>),
ShortCircuitDisjunction(Vec<Command>),
Negation(Command),
While {
condition: Command,
loop_body: Command
},
For {
varname: String,
sequence: Word,
loop_body: Command
}
If {
condition: Command,
then_branch: Command,
else_branch: Command
},
Case {
expr: Word,
cases: Vec<(Word, Command)>
},
Function {
name: String,
body: Command
}
}
/*
* We are all luminous beings.
* Why then, do we not appear before each
* other radiant in our illumination ?
*/
/*
* Bewteen the idea
* And the reality
* Between the motion
* And the act
* Falls the Shadow
* (T.S. Eliot)
*/
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
#[derive(Debug)]
pub struct Word {
pub segments: Vec<WordSegment>
}
#[derive(Debug)]
pub enum WordSegment {
FieldSeparator,
Tilde(String),
Literal(String),
Parameter(String, ParameterFormat),
Subshell(Command),
DoubleQuote(Word),
}
#[derive(Debug)]
pub enum ParameterFormat {
Normal,
Length,
Default(Word),
Assign(Word),
Error(Word),
Alt(Word),
Sub(ParamSubSide, ParamSubMode, Word),
}
#[derive(Debug)]
pub enum ParamSubMode {
Shortest, Longest
}
#[derive(Debug)]
pub enum ParamSubSide {
Prefix, Suffix
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
#[derive(Debug)]
pub struct Redirection {
redirection_type: RedirectionType,
fd: u64,
target: Word
}
#[derive(Debug)]
pub enum RedirectionType {
File(FileRedirectionType),
Dup(DupRedirectionType),
Heredoc // '<<'
}
#[derive(Debug)]
pub enum FileRedirectionType {
In, // '<'
InOut, // '<>'
Out, // '>'
OutReplace, // '>|'
OutAppend, // '>|'
}
#[derive(Debug)]
pub enum DupRedirectionType {
In, // '<&'
Out // '>&'
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\

9
src/env.rs Normal file
View file

@ -0,0 +1,9 @@
use std::collections::HashMap;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
struct Environment {
variables: HashMap<String, String>
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\

44
src/expand.rs Normal file
View file

@ -0,0 +1,44 @@
use crate::ast::*;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
impl Word {
pub fn (&mut self, env: &Environment) {
for x in self.0.iter_mut() {
x.expand_tilde();
match x {
Word::Tilde => Word::Literal( env.get_home() ),
other => other,
}
}
}
pub fn expand(&self) -> Vec<String> {
let mut fields = Vec::new();
for seg in self.segments.iter() {
//
}
fields
}
pub fn split_field(&mut self) {
}
}
impl WordSegment {
pub fn split_field(&self) -> Word {
match self {
}
}
pub fn expand(&self) -> Word {
match
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\

View file

@ -4,6 +4,11 @@ use {
tiny_ansi::TinyAnsi tiny_ansi::TinyAnsi
}; };
mod ast;
mod env;
mod parse;
//mod expand;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
pub fn get_type_str(cmd: &str, item: &str) -> Option<String> { pub fn get_type_str(cmd: &str, item: &str) -> Option<String> {
@ -30,6 +35,18 @@ fn main() {
let mut success = true; let mut success = true;
let mut dict = TypeDict::new(); let mut dict = TypeDict::new();
let stdin = std::io::stdin();
for line in std::io::BufReader::new(stdin).lines() {
if let Ok(line) = line {
let mut lex = parse::WordLexer::from( line.chars() );
for word in lex {
eprintln!("word-segment: {:?}", word);
}
}
}
return;
let stdin = std::io::stdin(); let stdin = std::io::stdin();
for pipeline in std::io::BufReader::new(stdin).lines() { for pipeline in std::io::BufReader::new(stdin).lines() {
let mut last_cmd = String::new(); let mut last_cmd = String::new();

130
src/parse.rs Normal file
View file

@ -0,0 +1,130 @@
use {
crate::ast::*,
std::iter::{Peekable, FromIterator},
};
pub struct WordLexer<It>
where It: Iterator<Item = char> {
chars: Peekable<It>
}
impl<It> From<It> for WordLexer<It>
where It: Iterator<Item = char> {
fn from(iter: It) -> Self {
WordLexer {
chars: iter.into_iter().peekable()
}
}
}
#[derive(Debug)]
pub enum LexError {
UnexpectedEnd(char)
}
impl<It> WordLexer<It>
where It: Iterator<Item = char> {
fn collect_until(&mut self, close: char) -> Result<String, LexError> {
let mut val = String::new();
while let Some(c) = self.chars.peek().cloned() {
if c == close {
return Ok(val)
} else {
self.chars.next();
val.push(c);
}
}
if close.is_whitespace() {
Ok(val)
} else {
Err(LexError::UnexpectedEnd(close))
}
}
}
impl<It> Iterator for WordLexer<It>
where It: Iterator<Item = char> {
type Item = Result<WordSegment, LexError>;
fn next(&mut self) -> Option<Result<WordSegment, LexError>> {
match self.chars.peek().cloned() {
Some('~') => {
self.chars.next();
match self.collect_until(' ') {
Ok(s) => Some(Ok(WordSegment::Tilde(s))),
Err(e) => Some(Err(e))
}
}
Some('"') => {
self.chars.next();
match self.collect_until('"') {
Ok(s) => {
self.chars.next();
let word = Word {
segments: WordLexer { chars: s.chars().peekable() }
.scan((), |_, x| x.ok())
.collect::<Vec<_>>()
};
Some(Ok(WordSegment::DoubleQuote(word)))
},
Err(e) => Some(Err(e))
}
},
Some('\'') => {
self.chars.next();
match self.collect_until('\'') {
Ok(s) => {
self.chars.next();
Some(Ok(WordSegment::Literal(s)))
},
Err(e) => Some(Err(e))
}
},
Some('$') => {
self.chars.next();
match self.chars.peek() {
Some('{') => {
self.chars.next();
match self.collect_until('}') {
Ok(s) => {
self.chars.next();
Some(Ok(WordSegment::Variable(s)))
}
Err(e) => Some(Err(e))
}
}
_ => {
match self.collect_until(' ') {
Ok(s) => {
Some(Ok(WordSegment::Variable(s)))
}
Err(e) => Some(Err(e))
}
}
}
}
Some(c) => {
while let Some(c) = self.chars.peek() {
if c.is_whitespace() {
self.chars.next();
} else {
return match self.collect_until(' ') {
Ok(s) => {
Some(Ok(WordSegment::Literal(s)))
}
Err(e) => Some(Err(e))
};
}
}
None
}
None => {
None
}
}
}
}