forked from extern/nushell
Add nu-protocol
This commit is contained in:
@ -1,7 +0,0 @@
|
||||
use crate::{BlockId, Signature};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Declaration {
|
||||
pub signature: Box<Signature>,
|
||||
pub body: Option<BlockId>,
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
use crate::parser_state::Type;
|
||||
use crate::ParserWorkingSet;
|
||||
use nu_protocol::{Span, Type};
|
||||
use std::ops::Range;
|
||||
|
||||
pub use crate::Span;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
ExtraTokens(Span),
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{Block, Expr, Expression, ParserWorkingSet, Pipeline, Span, Statement};
|
||||
use crate::{Block, Expr, Expression, ParserWorkingSet, Pipeline, Statement};
|
||||
use nu_protocol::Span;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FlatShape {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{ParseError, Span};
|
||||
use crate::ParseError;
|
||||
use nu_protocol::Span;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum TokenContents {
|
||||
@ -307,4 +308,4 @@ pub fn lex(
|
||||
}
|
||||
}
|
||||
(output, error)
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,14 @@
|
||||
mod declaration;
|
||||
mod errors;
|
||||
mod flatten;
|
||||
mod lex;
|
||||
mod lite_parse;
|
||||
mod parser;
|
||||
mod parser_state;
|
||||
mod signature;
|
||||
mod span;
|
||||
mod type_check;
|
||||
|
||||
pub use declaration::Declaration;
|
||||
pub use errors::ParseError;
|
||||
pub use flatten::FlatShape;
|
||||
pub use lex::{lex, Token, TokenContents};
|
||||
pub use lite_parse::{lite_parse, LiteBlock};
|
||||
pub use parser::{
|
||||
span, Block, Call, Expr, Expression, Import, Operator, Pipeline, Statement, SyntaxShape,
|
||||
VarDecl,
|
||||
};
|
||||
pub use parser_state::{BlockId, DeclId, ParserDelta, ParserState, ParserWorkingSet, Type, VarId};
|
||||
pub use signature::{Flag, PositionalArg, Signature};
|
||||
pub use span::Span;
|
||||
pub use parser::{Block, Call, Expr, Expression, Import, Operator, Pipeline, Statement, VarDecl};
|
||||
pub use parser_state::{ParserDelta, ParserState, ParserWorkingSet};
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::{ParseError, Span, Token, TokenContents};
|
||||
use crate::{ParseError, Token, TokenContents};
|
||||
use nu_protocol::Span;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LiteCommand {
|
||||
|
@ -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
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{parser::Block, Declaration, Span};
|
||||
use crate::parser::Block;
|
||||
use core::panic;
|
||||
use std::{collections::HashMap, fmt::Display, slice::Iter};
|
||||
use nu_protocol::{BlockId, DeclId, Declaration, Span, Type, VarId};
|
||||
use std::{collections::HashMap, slice::Iter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserState {
|
||||
files: Vec<(String, usize, usize)>,
|
||||
file_contents: Vec<u8>,
|
||||
@ -12,49 +12,6 @@ pub struct ParserState {
|
||||
scope: Vec<ScopeFrame>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Type {
|
||||
Int,
|
||||
Float,
|
||||
Bool,
|
||||
String,
|
||||
Block,
|
||||
ColumnPath,
|
||||
Duration,
|
||||
FilePath,
|
||||
Filesize,
|
||||
List(Box<Type>),
|
||||
Number,
|
||||
Nothing,
|
||||
Table,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Display for Type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Type::Block => write!(f, "block"),
|
||||
Type::Bool => write!(f, "bool"),
|
||||
Type::ColumnPath => write!(f, "column path"),
|
||||
Type::Duration => write!(f, "duration"),
|
||||
Type::FilePath => write!(f, "filepath"),
|
||||
Type::Filesize => write!(f, "filesize"),
|
||||
Type::Float => write!(f, "float"),
|
||||
Type::Int => write!(f, "int"),
|
||||
Type::List(l) => write!(f, "list<{}>", l),
|
||||
Type::Nothing => write!(f, "nothing"),
|
||||
Type::Number => write!(f, "number"),
|
||||
Type::String => write!(f, "string"),
|
||||
Type::Table => write!(f, "table"),
|
||||
Type::Unknown => write!(f, "unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type VarId = usize;
|
||||
pub type DeclId = usize;
|
||||
pub type BlockId = usize;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ScopeFrame {
|
||||
vars: HashMap<Vec<u8>, VarId>,
|
||||
@ -136,7 +93,7 @@ impl ParserState {
|
||||
|
||||
pub fn print_decls(&self) {
|
||||
for decl in self.decls.iter().enumerate() {
|
||||
println!("decl{}: {:?}", decl.0, decl.1);
|
||||
println!("decl{}: {:?}", decl.0, decl.1.signature);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,13 +176,11 @@ impl ParserState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserWorkingSet<'a> {
|
||||
permanent_state: &'a ParserState,
|
||||
pub delta: ParserDelta,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParserDelta {
|
||||
files: Vec<(String, usize, usize)>,
|
||||
pub(crate) file_contents: Vec<u8>,
|
||||
|
@ -1,293 +0,0 @@
|
||||
use crate::{parser::SyntaxShape, Declaration, VarId};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Flag {
|
||||
pub long: String,
|
||||
pub short: Option<char>,
|
||||
pub arg: Option<SyntaxShape>,
|
||||
pub required: bool,
|
||||
pub desc: String,
|
||||
// For custom commands
|
||||
pub var_id: Option<VarId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PositionalArg {
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
pub shape: SyntaxShape,
|
||||
// For custom commands
|
||||
pub var_id: Option<VarId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Signature {
|
||||
pub name: String,
|
||||
pub usage: String,
|
||||
pub extra_usage: String,
|
||||
pub required_positional: Vec<PositionalArg>,
|
||||
pub optional_positional: Vec<PositionalArg>,
|
||||
pub rest_positional: Option<PositionalArg>,
|
||||
pub named: Vec<Flag>,
|
||||
pub is_filter: bool,
|
||||
}
|
||||
|
||||
impl PartialEq for Signature {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
&& self.usage == other.usage
|
||||
&& self.required_positional == other.required_positional
|
||||
&& self.optional_positional == other.optional_positional
|
||||
&& self.rest_positional == other.rest_positional
|
||||
&& self.is_filter == other.is_filter
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Signature {}
|
||||
|
||||
impl Signature {
|
||||
pub fn new(name: impl Into<String>) -> Signature {
|
||||
Signature {
|
||||
name: name.into(),
|
||||
usage: String::new(),
|
||||
extra_usage: String::new(),
|
||||
required_positional: vec![],
|
||||
optional_positional: vec![],
|
||||
rest_positional: None,
|
||||
named: vec![],
|
||||
is_filter: false,
|
||||
}
|
||||
}
|
||||
pub fn build(name: impl Into<String>) -> Signature {
|
||||
Signature::new(name.into())
|
||||
}
|
||||
|
||||
/// Add a description to the signature
|
||||
pub fn desc(mut self, usage: impl Into<String>) -> Signature {
|
||||
self.usage = usage.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a required positional argument to the signature
|
||||
pub fn required(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
shape: impl Into<SyntaxShape>,
|
||||
desc: impl Into<String>,
|
||||
) -> Signature {
|
||||
self.required_positional.push(PositionalArg {
|
||||
name: name.into(),
|
||||
desc: desc.into(),
|
||||
shape: shape.into(),
|
||||
var_id: None,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a required positional argument to the signature
|
||||
pub fn optional(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
shape: impl Into<SyntaxShape>,
|
||||
desc: impl Into<String>,
|
||||
) -> Signature {
|
||||
self.optional_positional.push(PositionalArg {
|
||||
name: name.into(),
|
||||
desc: desc.into(),
|
||||
shape: shape.into(),
|
||||
var_id: None,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn rest(mut self, shape: impl Into<SyntaxShape>, desc: impl Into<String>) -> Signature {
|
||||
self.rest_positional = Some(PositionalArg {
|
||||
name: "rest".into(),
|
||||
desc: desc.into(),
|
||||
shape: shape.into(),
|
||||
var_id: None,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add an optional named flag argument to the signature
|
||||
pub fn named(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
shape: impl Into<SyntaxShape>,
|
||||
desc: impl Into<String>,
|
||||
short: Option<char>,
|
||||
) -> Signature {
|
||||
let s = short.map(|c| {
|
||||
debug_assert!(!self.get_shorts().contains(&c));
|
||||
c
|
||||
});
|
||||
self.named.push(Flag {
|
||||
long: name.into(),
|
||||
short: s,
|
||||
arg: Some(shape.into()),
|
||||
required: false,
|
||||
desc: desc.into(),
|
||||
var_id: None,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a required named flag argument to the signature
|
||||
pub fn required_named(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
shape: impl Into<SyntaxShape>,
|
||||
desc: impl Into<String>,
|
||||
short: Option<char>,
|
||||
) -> Signature {
|
||||
let s = short.map(|c| {
|
||||
debug_assert!(!self.get_shorts().contains(&c));
|
||||
c
|
||||
});
|
||||
self.named.push(Flag {
|
||||
long: name.into(),
|
||||
short: s,
|
||||
arg: Some(shape.into()),
|
||||
required: true,
|
||||
desc: desc.into(),
|
||||
var_id: None,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a switch to the signature
|
||||
pub fn switch(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
desc: impl Into<String>,
|
||||
short: Option<char>,
|
||||
) -> Signature {
|
||||
let s = short.map(|c| {
|
||||
debug_assert!(
|
||||
!self.get_shorts().contains(&c),
|
||||
"There may be duplicate short flags, such as -h"
|
||||
);
|
||||
c
|
||||
});
|
||||
|
||||
self.named.push(Flag {
|
||||
long: name.into(),
|
||||
short: s,
|
||||
arg: None,
|
||||
required: false,
|
||||
desc: desc.into(),
|
||||
var_id: None,
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Get list of the short-hand flags
|
||||
pub fn get_shorts(&self) -> Vec<char> {
|
||||
let mut shorts = Vec::new();
|
||||
for Flag { short, .. } in &self.named {
|
||||
if let Some(c) = short {
|
||||
shorts.push(*c);
|
||||
}
|
||||
}
|
||||
shorts
|
||||
}
|
||||
|
||||
pub fn get_positional(&self, position: usize) -> Option<PositionalArg> {
|
||||
if position < self.required_positional.len() {
|
||||
self.required_positional.get(position).cloned()
|
||||
} else if position < (self.required_positional.len() + self.optional_positional.len()) {
|
||||
self.optional_positional
|
||||
.get(position - self.required_positional.len())
|
||||
.cloned()
|
||||
} else {
|
||||
self.rest_positional.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_positionals(&self) -> usize {
|
||||
let mut total = self.required_positional.len() + self.optional_positional.len();
|
||||
|
||||
for positional in &self.required_positional {
|
||||
if let SyntaxShape::Keyword(..) = positional.shape {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
for positional in &self.optional_positional {
|
||||
if let SyntaxShape::Keyword(..) = positional.shape {
|
||||
// Keywords have a required argument, so account for that
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
pub fn num_positionals_after(&self, idx: usize) -> usize {
|
||||
let mut total = 0;
|
||||
let mut curr = 0;
|
||||
|
||||
for positional in &self.required_positional {
|
||||
match positional.shape {
|
||||
SyntaxShape::Keyword(..) => {
|
||||
// Keywords have a required argument, so account for that
|
||||
if curr > idx {
|
||||
total += 2;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if curr > idx {
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
curr += 1;
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
/// Find the matching long flag
|
||||
pub fn get_long_flag(&self, name: &str) -> Option<Flag> {
|
||||
for flag in &self.named {
|
||||
if flag.long == name {
|
||||
return Some(flag.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Find the matching long flag
|
||||
pub fn get_short_flag(&self, short: char) -> Option<Flag> {
|
||||
for flag in &self.named {
|
||||
if let Some(short_flag) = &flag.short {
|
||||
if *short_flag == short {
|
||||
return Some(flag.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<Signature>> for Declaration {
|
||||
fn from(val: Box<Signature>) -> Self {
|
||||
Declaration {
|
||||
signature: val,
|
||||
body: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for Declaration {
|
||||
fn from(val: Signature) -> Self {
|
||||
Declaration {
|
||||
signature: Box::new(val),
|
||||
body: None,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Span {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn new(start: usize, end: usize) -> Span {
|
||||
Span { start, end }
|
||||
}
|
||||
|
||||
pub fn unknown() -> Span {
|
||||
Span { start: 0, end: 0 }
|
||||
}
|
||||
|
||||
pub fn offset(&self, offset: usize) -> Span {
|
||||
Span {
|
||||
start: self.start - offset,
|
||||
end: self.end - offset,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
use crate::{parser::Operator, parser_state::Type, Expr, Expression, ParseError, ParserWorkingSet};
|
||||
use crate::{parser::Operator, Expr, Expression, ParseError, ParserWorkingSet};
|
||||
use nu_protocol::Type;
|
||||
|
||||
impl<'a> ParserWorkingSet<'a> {
|
||||
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
||||
|
Reference in New Issue
Block a user