add subcommand parsing

This commit is contained in:
JT 2021-07-18 07:34:43 +12:00
parent 30f54626d3
commit 92f72b4103
3 changed files with 62 additions and 9 deletions

View file

@ -63,6 +63,16 @@ fn main() -> std::io::Result<()> {
.required("block", SyntaxShape::Block, "body of the definition");
working_set.add_decl(sig.into());
let sig = Signature::build("add");
working_set.add_decl(sig.into());
let sig = Signature::build("add it");
working_set.add_decl(sig.into());
let sig = Signature::build("add it together")
.required("x", SyntaxShape::Int, "x value")
.required("y", SyntaxShape::Int, "y value");
working_set.add_decl(sig.into());
ParserState::merge_working_set(&mut parser_state, working_set);
// let file = std::fs::read(&path)?;

View file

@ -643,15 +643,36 @@ impl ParserWorkingSet {
// assume spans.len() > 0?
let name = self.get_span_contents(spans[0]);
if let Some(decl_id) = self.find_decl(name) {
let (call, span, err) = self.parse_internal_call(spans, decl_id);
(
Expression {
expr: Expr::Call(call),
span,
},
err,
)
if self.contains_decl_partial_match(name) {
// potentially subcommand
let mut name = name.to_vec();
let mut pos = 1;
let mut decl_id = None;
while pos < spans.len() {
let mut new_name = name.to_vec();
new_name.push(b' ');
new_name.extend(self.get_span_contents(spans[pos]));
if let Some(did) = self.find_decl(&new_name) {
decl_id = Some(did);
} else {
break;
}
name = new_name;
pos += 1;
}
// parse internal command
if let Some(decl_id) = decl_id {
let (call, span, err) = self.parse_internal_call(&spans[(pos - 1)..], decl_id);
(
Expression {
expr: Expr::Call(call),
span,
},
err,
)
} else {
self.parse_external_call(spans)
}
} else {
self.parse_external_call(spans)
}

View file

@ -256,6 +256,28 @@ impl ParserWorkingSet {
None
}
pub fn contains_decl_partial_match(&self, name: &[u8]) -> bool {
for scope in self.scope.iter().rev() {
for decl in &scope.decls {
if decl.0.starts_with(name) {
return true;
}
}
}
if let Some(permanent_state) = &self.permanent_state {
for scope in permanent_state.scope.iter().rev() {
for decl in &scope.decls {
if decl.0.starts_with(name) {
return true;
}
}
}
}
false
}
pub fn next_var_id(&self) -> VarId {
if let Some(permanent_state) = &self.permanent_state {
let num_permanent_vars = permanent_state.num_vars();