mirror of
https://github.com/nushell/nushell
synced 2024-12-28 05:53:09 +00:00
Add var usage
This commit is contained in:
parent
e3abadd686
commit
43fd0b6ae9
3 changed files with 49 additions and 14 deletions
|
@ -6,4 +6,5 @@ pub enum ParseError {
|
|||
UnexpectedEof(String, Span),
|
||||
UnknownStatement(Span),
|
||||
Mismatch(String, Span),
|
||||
VariableNotFound(Span),
|
||||
}
|
||||
|
|
|
@ -121,6 +121,22 @@ fn garbage(span: Span) -> Expression {
|
|||
Expression::garbage(span)
|
||||
}
|
||||
|
||||
fn is_identifier_byte(b: u8) -> bool {
|
||||
b != b'.' && b != b'[' && b != b'(' && b != b'{'
|
||||
}
|
||||
|
||||
fn is_identifier(bytes: &[u8]) -> bool {
|
||||
bytes.iter().all(|x| is_identifier_byte(*x))
|
||||
}
|
||||
|
||||
fn is_variable(bytes: &[u8]) -> bool {
|
||||
if bytes.len() > 1 && bytes[0] == b'$' {
|
||||
is_identifier(&bytes[1..])
|
||||
} else {
|
||||
is_identifier(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
fn span(spans: &[Span]) -> Span {
|
||||
let length = spans.len();
|
||||
|
||||
|
@ -254,9 +270,25 @@ impl ParserWorkingSet {
|
|||
span: Span,
|
||||
shape: SyntaxShape,
|
||||
) -> (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) {
|
||||
return (
|
||||
Expression {
|
||||
expr: Expr::Var(var_id),
|
||||
ty,
|
||||
span,
|
||||
},
|
||||
None,
|
||||
);
|
||||
} else {
|
||||
return (garbage(span), Some(ParseError::VariableNotFound(span)));
|
||||
}
|
||||
}
|
||||
|
||||
match shape {
|
||||
SyntaxShape::Number => {
|
||||
if let Ok(token) = String::from_utf8(self.get_span_contents(span).into()) {
|
||||
if let Ok(token) = String::from_utf8(bytes.into()) {
|
||||
self.parse_number(&token, span)
|
||||
} else {
|
||||
(
|
||||
|
@ -280,13 +312,17 @@ impl ParserWorkingSet {
|
|||
self.parse_math_expression(spans)
|
||||
}
|
||||
|
||||
pub fn parse_variable(&mut self, span: Span) -> Option<ParseError> {
|
||||
let contents = self.get_span_contents(span);
|
||||
pub fn parse_variable(&mut self, span: Span) -> (Option<VarId>, Option<ParseError>) {
|
||||
let bytes = self.get_span_contents(span);
|
||||
|
||||
if !contents.is_empty() && contents[0] == b'$' {
|
||||
None
|
||||
if is_variable(bytes) {
|
||||
if let Some((var_id, _, _)) = self.find_variable(bytes) {
|
||||
(Some(var_id), None)
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
} else {
|
||||
Some(ParseError::Mismatch("variable".into(), span))
|
||||
(None, Some(ParseError::Mismatch("variable".into(), span)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,7 +340,7 @@ impl ParserWorkingSet {
|
|||
pub fn parse_let(&mut self, spans: &[Span]) -> (Statement, Option<ParseError>) {
|
||||
let mut error = None;
|
||||
if spans.len() >= 4 && self.parse_keyword(spans[0], b"let").is_none() {
|
||||
let err = self.parse_variable(spans[1]);
|
||||
let (_, err) = self.parse_variable(spans[1]);
|
||||
error = error.or(err);
|
||||
|
||||
let err = self.parse_keyword(spans[2], b"=");
|
||||
|
@ -369,8 +405,6 @@ impl ParserWorkingSet {
|
|||
let (output, err) = lite_parse(&output);
|
||||
error = error.or(err);
|
||||
|
||||
println!("{:?}", output);
|
||||
|
||||
let (output, err) = self.parse_block(&output);
|
||||
error = error.or(err);
|
||||
|
||||
|
|
|
@ -122,15 +122,15 @@ impl ParserWorkingSet {
|
|||
self.scope.push(ScopeFrame::new());
|
||||
}
|
||||
|
||||
pub fn find_variable(&self, name: &[u8]) -> Option<(VarLocation, Type)> {
|
||||
pub fn find_variable(&self, name: &[u8]) -> Option<(VarId, VarLocation, Type)> {
|
||||
for scope in self.scope.iter().rev().enumerate() {
|
||||
if let Some(result) = scope.1.vars.get(name) {
|
||||
if let Some(result) = self.vars.get(result) {
|
||||
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((VarLocation::CurrentScope, result.clone()));
|
||||
return Some((*var_id, VarLocation::CurrentScope, *result));
|
||||
} else {
|
||||
return Some((VarLocation::OuterScope, result.clone()));
|
||||
return Some((*var_id, VarLocation::OuterScope, *result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue