mirror of
https://github.com/nushell/nushell.git
synced 2024-12-15 19:52:26 +01:00
little bits of progress
This commit is contained in:
parent
43fd0b6ae9
commit
4f89ed5d66
@ -8,5 +8,5 @@ mod span;
|
||||
pub use lex::{lex, LexMode, Token, TokenContents};
|
||||
pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement};
|
||||
pub use parse_error::ParseError;
|
||||
pub use parser_state::{ParserState, ParserWorkingSet, VarLocation};
|
||||
pub use parser_state::{ParserState, ParserWorkingSet};
|
||||
pub use span::Span;
|
||||
|
@ -7,4 +7,5 @@ pub enum ParseError {
|
||||
UnknownStatement(Span),
|
||||
Mismatch(String, Span),
|
||||
VariableNotFound(Span),
|
||||
UnknownCommand(Span),
|
||||
}
|
||||
|
@ -6,9 +6,16 @@ use crate::{
|
||||
LiteBlock, LiteCommand, LiteStatement, ParseError, ParserWorkingSet, Span,
|
||||
};
|
||||
|
||||
pub struct Signature {
|
||||
pub name: String,
|
||||
pub mandatory_positional: Vec<SyntaxShape>,
|
||||
}
|
||||
|
||||
/// The syntactic shapes that values must match to be passed into a command. You can think of this as the type-checking that occurs when you call a function.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SyntaxShape {
|
||||
/// A specific match to a word or symbol
|
||||
Word(Vec<u8>),
|
||||
/// Any syntactic form is allowed
|
||||
Any,
|
||||
/// Strings and string-like bare words are allowed
|
||||
@ -154,39 +161,26 @@ fn span(spans: &[Span]) -> Span {
|
||||
}
|
||||
|
||||
impl ParserWorkingSet {
|
||||
/*
|
||||
fn parse_let(&mut self, command: &LiteCommand) -> (Statement, Option<ParseError>) {
|
||||
|
||||
}
|
||||
fn parse_special_command(&mut self, command: &LiteCommand) -> (Statement, Option<ParseError>) {
|
||||
let command_name = self.get_span_contents(command.parts[0]);
|
||||
println!("{:?}", command_name);
|
||||
match command_name {
|
||||
b"let" => self.parse_let(command),
|
||||
b"def" => self.parse_def(command),
|
||||
b"source" => self.parse_source(command),
|
||||
_ => (
|
||||
Statement::None,
|
||||
Some(ParseError::UnknownStatement(command.parts[0])),
|
||||
),
|
||||
}
|
||||
pub fn parse_external_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||
// TODO: add external parsing
|
||||
(Expression::garbage(spans[0]), None)
|
||||
}
|
||||
|
||||
fn parse_statement(
|
||||
&mut self,
|
||||
block: &mut Block,
|
||||
lite_pipeline: &LiteStatement,
|
||||
) -> Option<ParseError> {
|
||||
match lite_pipeline.commands.len() {
|
||||
0 => None,
|
||||
1 => None,
|
||||
_ => {
|
||||
// pipeline
|
||||
None
|
||||
}
|
||||
pub fn parse_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||
// assume spans.len() > 0?
|
||||
let name = self.get_span_contents(spans[0]);
|
||||
|
||||
if let Some(decl_id) = self.find_decl(name) {
|
||||
let sig = self.get_decl(decl_id).expect("internal error: bad DeclId");
|
||||
|
||||
let mut positional_idx = 0;
|
||||
let mut arg_offset = 1;
|
||||
|
||||
(Expression::garbage(spans[0]), None)
|
||||
} else {
|
||||
self.parse_external_call(spans)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn parse_int(&mut self, token: &str, span: Span) -> (Expression, Option<ParseError>) {
|
||||
if let Some(token) = token.strip_prefix("0x") {
|
||||
@ -272,7 +266,10 @@ impl ParserWorkingSet {
|
||||
) -> (Expression, Option<ParseError>) {
|
||||
let bytes = self.get_span_contents(span);
|
||||
if !bytes.is_empty() && bytes[0] == b'$' {
|
||||
if let Some((var_id, _, ty)) = self.find_variable(bytes) {
|
||||
if let Some(var_id) = self.find_variable(bytes) {
|
||||
let ty = *self
|
||||
.get_variable(var_id)
|
||||
.expect("internal error: invalid VarId");
|
||||
return (
|
||||
Expression {
|
||||
expr: Expr::Var(var_id),
|
||||
@ -316,7 +313,7 @@ impl ParserWorkingSet {
|
||||
let bytes = self.get_span_contents(span);
|
||||
|
||||
if is_variable(bytes) {
|
||||
if let Some((var_id, _, _)) = self.find_variable(bytes) {
|
||||
if let Some(var_id) = self.find_variable(bytes) {
|
||||
(Some(var_id), None)
|
||||
} else {
|
||||
(None, None)
|
||||
|
@ -1,13 +1,11 @@
|
||||
use crate::{ParseError, Span};
|
||||
use crate::{parser::Signature, ParseError, Span};
|
||||
use core::num;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub struct ParserState {
|
||||
files: Vec<(String, Vec<u8>)>,
|
||||
}
|
||||
|
||||
pub enum VarLocation {
|
||||
CurrentScope,
|
||||
OuterScope,
|
||||
vars: Vec<Type>,
|
||||
decls: Vec<Signature>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@ -17,26 +15,22 @@ pub enum Type {
|
||||
}
|
||||
|
||||
pub type VarId = usize;
|
||||
pub type DeclId = usize;
|
||||
|
||||
struct ScopeFrame {
|
||||
vars: HashMap<Vec<u8>, VarId>,
|
||||
decls: HashMap<Vec<u8>, DeclId>,
|
||||
}
|
||||
|
||||
impl ScopeFrame {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
vars: HashMap::new(),
|
||||
decls: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParserWorkingSet {
|
||||
files: Vec<(String, Vec<u8>)>,
|
||||
vars: HashMap<VarId, Type>,
|
||||
permanent_state: Option<Arc<ParserState>>,
|
||||
scope: Vec<ScopeFrame>,
|
||||
}
|
||||
|
||||
impl Default for ParserState {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
@ -45,7 +39,11 @@ impl Default for ParserState {
|
||||
|
||||
impl ParserState {
|
||||
pub fn new() -> Self {
|
||||
Self { files: vec![] }
|
||||
Self {
|
||||
files: vec![],
|
||||
vars: vec![],
|
||||
decls: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge_working_set(this: &mut Arc<ParserState>, mut working_set: ParserWorkingSet) {
|
||||
@ -64,6 +62,22 @@ impl ParserState {
|
||||
self.files.len()
|
||||
}
|
||||
|
||||
pub fn num_vars(&self) -> usize {
|
||||
self.vars.len()
|
||||
}
|
||||
|
||||
pub fn num_decls(&self) -> usize {
|
||||
self.decls.len()
|
||||
}
|
||||
|
||||
pub fn get_var(&self, var_id: VarId) -> Option<&Type> {
|
||||
self.vars.get(var_id)
|
||||
}
|
||||
|
||||
pub fn get_decl(&self, decl_id: VarId) -> Option<&Signature> {
|
||||
self.decls.get(decl_id)
|
||||
}
|
||||
|
||||
pub(crate) fn add_file(&mut self, filename: String, contents: Vec<u8>) -> usize {
|
||||
self.files.push((filename, contents));
|
||||
|
||||
@ -75,11 +89,20 @@ impl ParserState {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParserWorkingSet {
|
||||
files: Vec<(String, Vec<u8>)>,
|
||||
vars: Vec<Type>, // indexed by VarId
|
||||
decls: Vec<Signature>, // indexed by DeclId
|
||||
permanent_state: Option<Arc<ParserState>>,
|
||||
scope: Vec<ScopeFrame>,
|
||||
}
|
||||
|
||||
impl ParserWorkingSet {
|
||||
pub fn new(permanent_state: Option<Arc<ParserState>>) -> Self {
|
||||
Self {
|
||||
files: vec![],
|
||||
vars: HashMap::new(),
|
||||
vars: vec![],
|
||||
decls: vec![],
|
||||
permanent_state,
|
||||
scope: vec![],
|
||||
}
|
||||
@ -122,17 +145,29 @@ impl ParserWorkingSet {
|
||||
self.scope.push(ScopeFrame::new());
|
||||
}
|
||||
|
||||
pub fn find_variable(&self, name: &[u8]) -> Option<(VarId, VarLocation, Type)> {
|
||||
pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
|
||||
for scope in self.scope.iter().rev().enumerate() {
|
||||
if let Some(decl_id) = scope.1.decls.get(name) {
|
||||
return Some(*decl_id);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn next_var_id(&self) -> VarId {
|
||||
if let Some(permanent_state) = &self.permanent_state {
|
||||
let num_permanent_vars = permanent_state.num_vars();
|
||||
num_permanent_vars + self.vars.len()
|
||||
} else {
|
||||
self.vars.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_variable(&self, name: &[u8]) -> Option<VarId> {
|
||||
for scope in self.scope.iter().rev().enumerate() {
|
||||
if let Some(var_id) = scope.1.vars.get(name) {
|
||||
if let Some(result) = self.vars.get(var_id) {
|
||||
if scope.0 == 0 {
|
||||
// Top level
|
||||
return Some((*var_id, VarLocation::CurrentScope, *result));
|
||||
} else {
|
||||
return Some((*var_id, VarLocation::OuterScope, *result));
|
||||
}
|
||||
}
|
||||
return Some(*var_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,19 +175,45 @@ impl ParserWorkingSet {
|
||||
}
|
||||
|
||||
pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId {
|
||||
let next_id = self.next_var_id();
|
||||
|
||||
let last = self
|
||||
.scope
|
||||
.last_mut()
|
||||
.expect("internal error: missing stack frame");
|
||||
|
||||
let next_id = self.vars.len();
|
||||
|
||||
last.vars.insert(name, next_id);
|
||||
|
||||
self.vars.insert(next_id, ty);
|
||||
|
||||
next_id
|
||||
}
|
||||
|
||||
pub fn get_variable(&self, var_id: VarId) -> Option<&Type> {
|
||||
if let Some(permanent_state) = &self.permanent_state {
|
||||
let num_permanent_vars = permanent_state.num_vars();
|
||||
if var_id < num_permanent_vars {
|
||||
permanent_state.get_var(var_id)
|
||||
} else {
|
||||
self.vars.get(var_id - num_permanent_vars)
|
||||
}
|
||||
} else {
|
||||
self.vars.get(var_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_decl(&self, decl_id: DeclId) -> Option<&Signature> {
|
||||
if let Some(permanent_state) = &self.permanent_state {
|
||||
let num_permanent_decls = permanent_state.num_decls();
|
||||
if decl_id < num_permanent_decls {
|
||||
permanent_state.get_decl(decl_id)
|
||||
} else {
|
||||
self.decls.get(decl_id - num_permanent_decls)
|
||||
}
|
||||
} else {
|
||||
self.decls.get(decl_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user