Add var usage

This commit is contained in:
JT 2021-07-01 13:31:02 +12:00
parent e3abadd686
commit 43fd0b6ae9
3 changed files with 49 additions and 14 deletions

View file

@ -6,4 +6,5 @@ pub enum ParseError {
UnexpectedEof(String, Span),
UnknownStatement(Span),
Mismatch(String, Span),
VariableNotFound(Span),
}

View file

@ -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);

View file

@ -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));
}
}
}