wip parser
This commit is contained in:
parent
73817529d6
commit
7988c8a2e1
5 changed files with 324 additions and 1 deletions
123
src/ast.rs
Normal file
123
src/ast.rs
Normal 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
9
src/env.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
struct Environment {
|
||||
variables: HashMap<String, String>
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
44
src/expand.rs
Normal file
44
src/expand.rs
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
17
src/main.rs
17
src/main.rs
|
@ -4,6 +4,11 @@ use {
|
|||
tiny_ansi::TinyAnsi
|
||||
};
|
||||
|
||||
mod ast;
|
||||
mod env;
|
||||
mod parse;
|
||||
//mod expand;
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
|
||||
|
||||
pub fn get_type_str(cmd: &str, item: &str) -> Option<String> {
|
||||
|
@ -30,6 +35,18 @@ fn main() {
|
|||
let mut success = true;
|
||||
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();
|
||||
for pipeline in std::io::BufReader::new(stdin).lines() {
|
||||
let mut last_cmd = String::new();
|
||||
|
|
130
src/parse.rs
Normal file
130
src/parse.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue