mirror of
https://github.com/nushell/nushell.git
synced 2024-12-16 12:12:19 +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 lex::{lex, LexMode, Token, TokenContents};
|
||||||
pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement};
|
pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement};
|
||||||
pub use parse_error::ParseError;
|
pub use parse_error::ParseError;
|
||||||
pub use parser_state::{ParserState, ParserWorkingSet, VarLocation};
|
pub use parser_state::{ParserState, ParserWorkingSet};
|
||||||
pub use span::Span;
|
pub use span::Span;
|
||||||
|
@ -7,4 +7,5 @@ pub enum ParseError {
|
|||||||
UnknownStatement(Span),
|
UnknownStatement(Span),
|
||||||
Mismatch(String, Span),
|
Mismatch(String, Span),
|
||||||
VariableNotFound(Span),
|
VariableNotFound(Span),
|
||||||
|
UnknownCommand(Span),
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,16 @@ use crate::{
|
|||||||
LiteBlock, LiteCommand, LiteStatement, ParseError, ParserWorkingSet, Span,
|
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.
|
/// 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 {
|
pub enum SyntaxShape {
|
||||||
|
/// A specific match to a word or symbol
|
||||||
|
Word(Vec<u8>),
|
||||||
/// Any syntactic form is allowed
|
/// Any syntactic form is allowed
|
||||||
Any,
|
Any,
|
||||||
/// Strings and string-like bare words are allowed
|
/// Strings and string-like bare words are allowed
|
||||||
@ -154,39 +161,26 @@ fn span(spans: &[Span]) -> Span {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ParserWorkingSet {
|
impl ParserWorkingSet {
|
||||||
/*
|
pub fn parse_external_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||||
fn parse_let(&mut self, command: &LiteCommand) -> (Statement, Option<ParseError>) {
|
// TODO: add external parsing
|
||||||
|
(Expression::garbage(spans[0]), None)
|
||||||
}
|
|
||||||
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])),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_statement(
|
pub fn parse_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
|
||||||
&mut self,
|
// assume spans.len() > 0?
|
||||||
block: &mut Block,
|
let name = self.get_span_contents(spans[0]);
|
||||||
lite_pipeline: &LiteStatement,
|
|
||||||
) -> Option<ParseError> {
|
if let Some(decl_id) = self.find_decl(name) {
|
||||||
match lite_pipeline.commands.len() {
|
let sig = self.get_decl(decl_id).expect("internal error: bad DeclId");
|
||||||
0 => None,
|
|
||||||
1 => None,
|
let mut positional_idx = 0;
|
||||||
_ => {
|
let mut arg_offset = 1;
|
||||||
// pipeline
|
|
||||||
None
|
(Expression::garbage(spans[0]), None)
|
||||||
}
|
} else {
|
||||||
|
self.parse_external_call(spans)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn parse_int(&mut self, token: &str, span: Span) -> (Expression, Option<ParseError>) {
|
pub fn parse_int(&mut self, token: &str, span: Span) -> (Expression, Option<ParseError>) {
|
||||||
if let Some(token) = token.strip_prefix("0x") {
|
if let Some(token) = token.strip_prefix("0x") {
|
||||||
@ -272,7 +266,10 @@ impl ParserWorkingSet {
|
|||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
let bytes = self.get_span_contents(span);
|
let bytes = self.get_span_contents(span);
|
||||||
if !bytes.is_empty() && bytes[0] == b'$' {
|
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 (
|
return (
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(var_id),
|
expr: Expr::Var(var_id),
|
||||||
@ -316,7 +313,7 @@ impl ParserWorkingSet {
|
|||||||
let bytes = self.get_span_contents(span);
|
let bytes = self.get_span_contents(span);
|
||||||
|
|
||||||
if is_variable(bytes) {
|
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)
|
(Some(var_id), None)
|
||||||
} else {
|
} else {
|
||||||
(None, None)
|
(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};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
pub struct ParserState {
|
pub struct ParserState {
|
||||||
files: Vec<(String, Vec<u8>)>,
|
files: Vec<(String, Vec<u8>)>,
|
||||||
}
|
vars: Vec<Type>,
|
||||||
|
decls: Vec<Signature>,
|
||||||
pub enum VarLocation {
|
|
||||||
CurrentScope,
|
|
||||||
OuterScope,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
@ -17,26 +15,22 @@ pub enum Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type VarId = usize;
|
pub type VarId = usize;
|
||||||
|
pub type DeclId = usize;
|
||||||
|
|
||||||
struct ScopeFrame {
|
struct ScopeFrame {
|
||||||
vars: HashMap<Vec<u8>, VarId>,
|
vars: HashMap<Vec<u8>, VarId>,
|
||||||
|
decls: HashMap<Vec<u8>, DeclId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeFrame {
|
impl ScopeFrame {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
vars: HashMap::new(),
|
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 {
|
impl Default for ParserState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
@ -45,7 +39,11 @@ impl Default for ParserState {
|
|||||||
|
|
||||||
impl ParserState {
|
impl ParserState {
|
||||||
pub fn new() -> Self {
|
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) {
|
pub fn merge_working_set(this: &mut Arc<ParserState>, mut working_set: ParserWorkingSet) {
|
||||||
@ -64,6 +62,22 @@ impl ParserState {
|
|||||||
self.files.len()
|
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 {
|
pub(crate) fn add_file(&mut self, filename: String, contents: Vec<u8>) -> usize {
|
||||||
self.files.push((filename, contents));
|
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 {
|
impl ParserWorkingSet {
|
||||||
pub fn new(permanent_state: Option<Arc<ParserState>>) -> Self {
|
pub fn new(permanent_state: Option<Arc<ParserState>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
files: vec![],
|
files: vec![],
|
||||||
vars: HashMap::new(),
|
vars: vec![],
|
||||||
|
decls: vec![],
|
||||||
permanent_state,
|
permanent_state,
|
||||||
scope: vec![],
|
scope: vec![],
|
||||||
}
|
}
|
||||||
@ -122,17 +145,29 @@ impl ParserWorkingSet {
|
|||||||
self.scope.push(ScopeFrame::new());
|
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() {
|
for scope in self.scope.iter().rev().enumerate() {
|
||||||
if let Some(var_id) = scope.1.vars.get(name) {
|
if let Some(var_id) = scope.1.vars.get(name) {
|
||||||
if let Some(result) = self.vars.get(var_id) {
|
return Some(*var_id);
|
||||||
if scope.0 == 0 {
|
|
||||||
// Top level
|
|
||||||
return Some((*var_id, VarLocation::CurrentScope, *result));
|
|
||||||
} else {
|
|
||||||
return Some((*var_id, VarLocation::OuterScope, *result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,19 +175,45 @@ impl ParserWorkingSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId {
|
pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId {
|
||||||
|
let next_id = self.next_var_id();
|
||||||
|
|
||||||
let last = self
|
let last = self
|
||||||
.scope
|
.scope
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.expect("internal error: missing stack frame");
|
.expect("internal error: missing stack frame");
|
||||||
|
|
||||||
let next_id = self.vars.len();
|
|
||||||
|
|
||||||
last.vars.insert(name, next_id);
|
last.vars.insert(name, next_id);
|
||||||
|
|
||||||
self.vars.insert(next_id, ty);
|
self.vars.insert(next_id, ty);
|
||||||
|
|
||||||
next_id
|
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)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user