diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..876440e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+publish.sh
+Cargo.toml
+Cargo.lock
+target
diff --git a/README.md b/README.md
index 0d341d6..684e7bb 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,157 @@
- Environment variables
- redirection support
+## BELLOS Usage
+```
+#!/usr/bin/env bellos
+# File: hello_world.bellos
+# Simple Hello World script
+echo "Hello, World!"
+
+# Using variables
+name="Bellos"
+echo "Welcome to $name programming!"
+
+# ----------------------------------------
+
+#!/usr/bin/env bellos
+# File: basic_math.bellos
+
+# Demonstrating arithmetic operations
+a=5
+b=3
+
+sum=$((a + b))
+difference=$((a - b))
+product=$((a * b))
+quotient=$((a / b))
+
+echo "Sum: $sum"
+echo "Difference: $difference"
+echo "Product: $product"
+echo "Quotient: $quotient"
+
+# ----------------------------------------
+
+#!/usr/bin/env bellos
+# File: control_structures.bellos
+
+# Demonstrating if statements and loops
+
+# If statement
+if [ $# -eq 0 ]
+then
+ echo "No arguments provided"
+elif [ $# -eq 1 ]
+then
+ echo "One argument provided: $1"
+else
+ echo "Multiple arguments provided"
+fi
+
+# For loop
+echo "Counting from 1 to 5:"
+for i in 1 2 3 4 5
+do
+ echo $i
+done
+
+# While loop
+echo "Countdown:"
+count=5
+while [ $count -gt 0 ]
+do
+ echo $count
+ count=$((count - 1))
+done
+
+# ----------------------------------------
+
+#!/usr/bin/env bellos
+# File: functions.bellos
+
+# Defining and using functions
+
+function greet() {
+ echo "Hello, $1!"
+}
+
+function add() {
+ echo $(($1 + $2))
+}
+
+# Calling functions
+greet "User"
+result=$(add 3 4)
+echo "3 + 4 = $result"
+
+# ----------------------------------------
+
+#!/usr/bin/env bellos
+# File: file_operations.bellos
+
+# Demonstrating file operations
+
+# Writing to a file
+echo "This is a test file" > test.txt
+echo "Adding another line" >> test.txt
+
+# Reading from a file
+echo "Contents of test.txt:"
+cat test.txt
+
+# Using a while loop to read file line by line
+echo "Reading file line by line:"
+while read -r line
+do
+ echo "Line: $line"
+done < test.txt
+
+# Cleaning up
+rm test.txt
+
+# ----------------------------------------
+
+#!/usr/bin/env bellos
+# File: string_manipulation.bellos
+
+# Demonstrating string manipulation
+
+string="Hello, Bellos!"
+
+# String length
+echo "Length of string: ${#string}"
+
+# Substring
+echo "First 5 characters: ${string:0:5}"
+
+# String replacement
+new_string=${string/Bellos/World}
+echo "Replaced string: $new_string"
+
+# Converting to uppercase
+echo "Uppercase: ${string^^}"
+
+# Converting to lowercase
+echo "Lowercase: ${string,,}"
+```
+
+## Website NPM
+- https://crates.io/crates/bellos
+
+### Installation
+- `cargo add bellos`
+
+```
+Name: bellos
+Version: 0.0.1
+Summary: Bellande Operating System Scripting Programming Language
+Home-page: github.com/RonaldsonBellande/bellos
+Author: Ronaldson Bellande
+Author-email: ronaldsonbellande@gmail.com
+License: GNU General Public License v3.0
+```
## License
diff --git a/git_scripts/.gitignore b/git_scripts/.gitignore
new file mode 100644
index 0000000..e5a7a9c
--- /dev/null
+++ b/git_scripts/.gitignore
@@ -0,0 +1,3 @@
+fix_errors.sh
+push.sh
+repository_recal.sh
diff --git a/src/bellos.rs b/src/bellos.rs
new file mode 100644
index 0000000..6d0b1ed
--- /dev/null
+++ b/src/bellos.rs
@@ -0,0 +1,765 @@
+// Copyright (C) 2024 Bellande Architecture Mechanism Research Innovation Center, Ronaldson Bellande
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use glob::glob;
+use std::collections::HashMap;
+use std::env;
+use std::fs::{self, File};
+use std::io::{self, Read, Write};
+use std::os::unix::io::AsRawFd;
+use std::process::{Child, Command, Stdio};
+use std::sync::{Arc, Mutex};
+use std::thread;
+
+#[derive(Debug, Clone, PartialEq)]
+enum Token {
+ Word(String),
+ Assignment,
+ Pipe,
+ Redirect(String),
+ LeftParen,
+ RightParen,
+ Semicolon,
+ NewLine,
+ If,
+ Then,
+ Else,
+ Fi,
+ While,
+ Do,
+ Done,
+ For,
+ In,
+ Function,
+ Ampersand,
+}
+
+#[derive(Debug, Clone)]
+enum ASTNode {
+ Command {
+ name: String,
+ args: Vec,
+ },
+ Assignment {
+ name: String,
+ value: String,
+ },
+ Pipeline(Vec),
+ Redirect {
+ node: Box,
+ direction: String,
+ target: String,
+ },
+ Block(Vec),
+ If {
+ condition: Box,
+ then_block: Box,
+ else_block: Option>,
+ },
+ While {
+ condition: Box,
+ block: Box,
+ },
+ For {
+ var: String,
+ list: Vec,
+ block: Box,
+ },
+ Function {
+ name: String,
+ body: Box,
+ },
+ Background(Box),
+}
+
+struct Lexer {
+ input: Vec,
+ position: usize,
+}
+
+impl Lexer {
+ fn new(input: String) -> Self {
+ Lexer {
+ input: input.chars().collect(),
+ position: 0,
+ }
+ }
+
+ fn next_token(&mut self) -> Option {
+ self.skip_whitespace();
+
+ if self.position >= self.input.len() {
+ return None;
+ }
+
+ match self.input[self.position] {
+ '=' => {
+ self.position += 1;
+ Some(Token::Assignment)
+ }
+ '|' => {
+ self.position += 1;
+ Some(Token::Pipe)
+ }
+ '>' => {
+ self.position += 1;
+ Some(Token::Redirect(">".to_string()))
+ }
+ '<' => {
+ self.position += 1;
+ Some(Token::Redirect("<".to_string()))
+ }
+ '(' => {
+ self.position += 1;
+ Some(Token::LeftParen)
+ }
+ ')' => {
+ self.position += 1;
+ Some(Token::RightParen)
+ }
+ ';' => {
+ self.position += 1;
+ Some(Token::Semicolon)
+ }
+ '\n' => {
+ self.position += 1;
+ Some(Token::NewLine)
+ }
+ '&' => {
+ self.position += 1;
+ Some(Token::Ampersand)
+ }
+ '"' => Some(self.read_string()),
+ _ => Some(self.read_word()),
+ }
+ }
+
+ fn skip_whitespace(&mut self) {
+ while self.position < self.input.len() && self.input[self.position].is_whitespace() {
+ self.position += 1;
+ }
+ }
+
+ fn read_word(&mut self) -> Token {
+ let start = self.position;
+ while self.position < self.input.len()
+ && !self.input[self.position].is_whitespace()
+ && !matches!(
+ self.input[self.position],
+ '=' | '|' | '>' | '<' | '(' | ')' | ';' | '&' | '\n'
+ )
+ {
+ self.position += 1;
+ }
+ let word: String = self.input[start..self.position].iter().collect();
+ match word.as_str() {
+ "if" => Token::If,
+ "then" => Token::Then,
+ "else" => Token::Else,
+ "fi" => Token::Fi,
+ "while" => Token::While,
+ "do" => Token::Do,
+ "done" => Token::Done,
+ "for" => Token::For,
+ "in" => Token::In,
+ "function" => Token::Function,
+ _ => Token::Word(word),
+ }
+ }
+
+ fn read_string(&mut self) -> Token {
+ self.position += 1; // Skip opening quote
+ let start = self.position;
+ while self.position < self.input.len() && self.input[self.position] != '"' {
+ self.position += 1;
+ }
+ let result = Token::Word(self.input[start..self.position].iter().collect());
+ self.position += 1; // Skip closing quote
+ result
+ }
+}
+
+struct Parser {
+ tokens: Vec,
+ position: usize,
+}
+
+impl Parser {
+ fn new(tokens: Vec) -> Self {
+ Parser {
+ tokens,
+ position: 0,
+ }
+ }
+
+ fn parse(&mut self) -> Result, String> {
+ let mut nodes = Vec::new();
+ while self.position < self.tokens.len() {
+ nodes.push(self.parse_statement()?);
+ self.consume_if(Token::Semicolon);
+ self.consume_if(Token::NewLine);
+ }
+ Ok(nodes)
+ }
+
+ fn parse_statement(&mut self) -> Result {
+ match &self.tokens[self.position] {
+ Token::Word(_) => self.parse_command_or_assignment(),
+ Token::LeftParen => self.parse_block(),
+ Token::If => self.parse_if(),
+ Token::While => self.parse_while(),
+ Token::For => self.parse_for(),
+ Token::Function => self.parse_function(),
+ _ => Err(format!(
+ "Unexpected token: {:?}",
+ self.tokens[self.position]
+ )),
+ }
+ }
+
+ fn parse_command_or_assignment(&mut self) -> Result {
+ let name = match &self.tokens[self.position] {
+ Token::Word(w) => w.clone(),
+ _ => {
+ return Err(format!(
+ "Expected word, found {:?}",
+ self.tokens[self.position]
+ ))
+ }
+ };
+ self.position += 1;
+
+ if self.position < self.tokens.len() && self.tokens[self.position] == Token::Assignment {
+ self.position += 1;
+ let value = match &self.tokens[self.position] {
+ Token::Word(w) => w.clone(),
+ _ => {
+ return Err(format!(
+ "Expected word after assignment, found {:?}",
+ self.tokens[self.position]
+ ))
+ }
+ };
+ self.position += 1;
+ Ok(ASTNode::Assignment { name, value })
+ } else {
+ let mut args = Vec::new();
+ while self.position < self.tokens.len()
+ && !matches!(
+ self.tokens[self.position],
+ Token::Pipe
+ | Token::Redirect(_)
+ | Token::Semicolon
+ | Token::NewLine
+ | Token::Ampersand
+ )
+ {
+ if let Token::Word(w) = &self.tokens[self.position] {
+ args.push(w.clone());
+ self.position += 1;
+ } else {
+ break;
+ }
+ }
+ let command = ASTNode::Command { name, args };
+ self.parse_pipeline_or_redirect(command)
+ }
+ }
+
+ fn parse_pipeline_or_redirect(&mut self, left: ASTNode) -> Result {
+ if self.position >= self.tokens.len() {
+ return Ok(left);
+ }
+
+ match &self.tokens[self.position] {
+ Token::Pipe => {
+ self.position += 1;
+ let right = self.parse_command_or_assignment()?;
+ let pipeline = ASTNode::Pipeline(vec![left, right]);
+ self.parse_pipeline_or_redirect(pipeline)
+ }
+ Token::Redirect(direction) => {
+ self.position += 1;
+ let target = match &self.tokens[self.position] {
+ Token::Word(w) => w.clone(),
+ _ => {
+ return Err(format!(
+ "Expected word after redirect, found {:?}",
+ self.tokens[self.position]
+ ))
+ }
+ };
+ self.position += 1;
+ let redirect = ASTNode::Redirect {
+ node: Box::new(left),
+ direction: direction.clone(),
+ target,
+ };
+ self.parse_pipeline_or_redirect(redirect)
+ }
+ Token::Ampersand => {
+ self.position += 1;
+ Ok(ASTNode::Background(Box::new(left)))
+ }
+ _ => Ok(left),
+ }
+ }
+
+ fn parse_block(&mut self) -> Result {
+ self.position += 1; // Consume left paren
+ let mut statements = Vec::new();
+ while self.position < self.tokens.len() && self.tokens[self.position] != Token::RightParen {
+ statements.push(self.parse_statement()?);
+ self.consume_if(Token::Semicolon);
+ self.consume_if(Token::NewLine);
+ }
+ self.position += 1; // Consume right paren
+ Ok(ASTNode::Block(statements))
+ }
+
+ fn parse_if(&mut self) -> Result {
+ self.position += 1; // Consume 'if'
+ let condition = Box::new(self.parse_statement()?);
+ self.expect_token(Token::Then)?;
+ let then_block = Box::new(self.parse_block()?);
+ let else_block = if self.consume_if(Token::Else) {
+ Some(Box::new(self.parse_block()?))
+ } else {
+ None
+ };
+ self.expect_token(Token::Fi)?;
+ Ok(ASTNode::If {
+ condition,
+ then_block,
+ else_block,
+ })
+ }
+
+ fn parse_while(&mut self) -> Result {
+ self.position += 1; // Consume 'while'
+ let condition = Box::new(self.parse_statement()?);
+ self.expect_token(Token::Do)?;
+ let block = Box::new(self.parse_block()?);
+ self.expect_token(Token::Done)?;
+ Ok(ASTNode::While { condition, block })
+ }
+
+ fn parse_for(&mut self) -> Result {
+ self.position += 1; // Consume 'for'
+ let var = match &self.tokens[self.position] {
+ Token::Word(w) => w.clone(),
+ _ => {
+ return Err(format!(
+ "Expected variable name after 'for', found {:?}",
+ self.tokens[self.position]
+ ))
+ }
+ };
+ self.position += 1;
+ self.expect_token(Token::In)?;
+ let mut list = Vec::new();
+ while self.position < self.tokens.len() && self.tokens[self.position] != Token::Do {
+ if let Token::Word(w) = &self.tokens[self.position] {
+ list.push(w.clone());
+ self.position += 1;
+ } else {
+ break;
+ }
+ }
+ self.expect_token(Token::Do)?;
+ let block = Box::new(self.parse_block()?);
+ self.expect_token(Token::Done)?;
+ Ok(ASTNode::For { var, list, block })
+ }
+
+ fn parse_function(&mut self) -> Result {
+ self.position += 1; // Consume 'function'
+ let name = match &self.tokens[self.position] {
+ Token::Word(w) => w.clone(),
+ _ => {
+ return Err(format!(
+ "Expected function name, found {:?}",
+ self.tokens[self.position]
+ ))
+ }
+ };
+ self.position += 1;
+ let body = Box::new(self.parse_block()?);
+ Ok(ASTNode::Function { name, body })
+ }
+
+ fn expect_token(&mut self, expected: Token) -> Result<(), String> {
+ if self.position < self.tokens.len() && self.tokens[self.position] == expected {
+ self.position += 1;
+ Ok(())
+ } else {
+ Err(format!(
+ "Expected {:?}, found {:?}",
+ expected,
+ self.tokens.get(self.position)
+ ))
+ }
+ }
+
+ fn consume_if(&mut self, token: Token) -> bool {
+ if self.position < self.tokens.len() && self.tokens[self.position] == token {
+ self.position += 1;
+ true
+ } else {
+ false
+ }
+ }
+}
+
+struct Interpreter {
+ variables: HashMap,
+ functions: HashMap,
+ background_jobs: Arc>>,
+}
+
+impl Interpreter {
+ fn new() -> Self {
+ Interpreter {
+ variables: HashMap::new(),
+ functions: HashMap::new(),
+ background_jobs: Arc::new(Mutex::new(Vec::new())),
+ }
+ }
+
+ fn interpret(&mut self, nodes: Vec) -> Result<(), String> {
+ for node in nodes {
+ self.interpret_node(Box::new(node))?;
+ }
+ Ok(())
+ }
+
+ fn interpret_node(&mut self, node: Box) -> Result