Add nu-protocol

This commit is contained in:
JT
2021-09-02 13:29:43 +12:00
parent c4c4d82bf4
commit 3d252a9797
35 changed files with 296 additions and 247 deletions

View File

@ -3,117 +3,13 @@ use std::{
ops::{Index, IndexMut},
};
use crate::{
lex, lite_parse,
parser_state::{Type, VarId},
signature::{Flag, PositionalArg},
BlockId, DeclId, Declaration, LiteBlock, ParseError, ParserWorkingSet, Signature, Span, Token,
TokenContents,
use crate::{lex, lite_parse, LiteBlock, ParseError, ParserWorkingSet, Token, TokenContents};
use nu_protocol::{
span, BlockId, DeclId, Declaration, Flag, PositionalArg, Signature, Span, SyntaxShape, Type,
VarId,
};
/// 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, Clone, PartialEq, Eq)]
pub enum SyntaxShape {
/// A specific match to a word or symbol
Keyword(Vec<u8>, Box<SyntaxShape>),
/// Any syntactic form is allowed
Any,
/// Strings and string-like bare words are allowed
String,
/// A dotted path to navigate the table
ColumnPath,
/// A dotted path to navigate the table (including variable)
FullColumnPath,
/// Only a numeric (integer or decimal) value is allowed
Number,
/// A range is allowed (eg, `1..3`)
Range,
/// Only an integer value is allowed
Int,
/// A filepath is allowed
FilePath,
/// A glob pattern is allowed, eg `foo*`
GlobPattern,
/// A block is allowed, eg `{start this thing}`
Block,
/// A table is allowed, eg `[[first, second]; [1, 2]]`
Table,
/// A table is allowed, eg `[first second]`
List(Box<SyntaxShape>),
/// A filesize value is allowed, eg `10kb`
Filesize,
/// A duration value is allowed, eg `19day`
Duration,
/// An operator
Operator,
/// A math expression which expands shorthand forms on the lefthand side, eg `foo > 1`
/// The shorthand allows us to more easily reach columns inside of the row being passed in
RowCondition,
/// A general math expression, eg `1 + 2`
MathExpression,
/// A variable name
Variable,
/// A variable with optional type, `x` or `x: int`
VarWithOptType,
/// A signature for a definition, `[x:int, --foo]`
Signature,
/// A general expression, eg `1 + 2` or `foo --bar`
Expression,
}
impl SyntaxShape {
pub fn to_type(&self) -> Type {
match self {
SyntaxShape::Any => Type::Unknown,
SyntaxShape::Block => Type::Block,
SyntaxShape::ColumnPath => Type::Unknown,
SyntaxShape::Duration => Type::Duration,
SyntaxShape::Expression => Type::Unknown,
SyntaxShape::FilePath => Type::FilePath,
SyntaxShape::Filesize => Type::Filesize,
SyntaxShape::FullColumnPath => Type::Unknown,
SyntaxShape::GlobPattern => Type::String,
SyntaxShape::Int => Type::Int,
SyntaxShape::List(x) => {
let contents = x.to_type();
Type::List(Box::new(contents))
}
SyntaxShape::Keyword(_, expr) => expr.to_type(),
SyntaxShape::MathExpression => Type::Unknown,
SyntaxShape::Number => Type::Number,
SyntaxShape::Operator => Type::Unknown,
SyntaxShape::Range => Type::Unknown,
SyntaxShape::RowCondition => Type::Bool,
SyntaxShape::Signature => Type::Unknown,
SyntaxShape::String => Type::String,
SyntaxShape::Table => Type::Table,
SyntaxShape::VarWithOptType => Type::Unknown,
SyntaxShape::Variable => Type::Unknown,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operator {
Equal,
@ -404,21 +300,6 @@ fn check_call(command: Span, sig: &Signature, call: &Call) -> Option<ParseError>
}
}
pub fn span(spans: &[Span]) -> Span {
let length = spans.len();
if length == 0 {
Span::unknown()
} else if length == 1 {
spans[0]
} else {
Span {
start: spans[0].start,
end: spans[length - 1].end,
}
}
}
impl<'a> ParserWorkingSet<'a> {
pub fn parse_external_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
// TODO: add external parsing
@ -725,7 +606,7 @@ impl<'a> ParserWorkingSet<'a> {
call.decl_id = decl_id;
call.head = command_span;
let decl = self.get_decl(decl_id).clone();
let signature = self.get_decl(decl_id).signature.clone();
// The index into the positional parameter in the definition
let mut positional_idx = 0;
@ -738,8 +619,7 @@ impl<'a> ParserWorkingSet<'a> {
let arg_span = spans[spans_idx];
// Check if we're on a long flag, if so, parse
let (long_name, arg, err) =
self.parse_long_flag(spans, &mut spans_idx, &decl.signature);
let (long_name, arg, err) = self.parse_long_flag(spans, &mut spans_idx, &signature);
if let Some(long_name) = long_name {
// We found a long flag, like --bar
error = error.or(err);
@ -750,7 +630,7 @@ impl<'a> ParserWorkingSet<'a> {
// Check if we're on a short flag or group of short flags, if so, parse
let (short_flags, err) =
self.parse_short_flags(spans, &mut spans_idx, positional_idx, &decl.signature);
self.parse_short_flags(spans, &mut spans_idx, positional_idx, &signature);
if let Some(short_flags) = short_flags {
error = error.or(err);
@ -774,8 +654,9 @@ impl<'a> ParserWorkingSet<'a> {
}
// Parse a positional arg if there is one
if let Some(positional) = decl.signature.get_positional(positional_idx) {
if let Some(positional) = signature.get_positional(positional_idx) {
//Make sure we leave enough spans for the remaining positionals
let decl = self.get_decl(decl_id);
let end = self.calculate_end_span(&decl, spans, spans_idx, positional_idx);
@ -813,7 +694,7 @@ impl<'a> ParserWorkingSet<'a> {
spans_idx += 1;
}
let err = check_call(command_span, &decl.signature, &call);
let err = check_call(command_span, &signature, &call);
error = error.or(err);
// FIXME: type unknown