mirror of
https://github.com/nushell/nushell
synced 2024-12-28 14:03:09 +00:00
Merge pull request #132 from jonathandturner/parse_cleanup
Clean up old parser code
This commit is contained in:
commit
4643c9b3a9
29 changed files with 31 additions and 20713 deletions
|
@ -11,7 +11,7 @@ use crate::commands::classified::{
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
crate use crate::errors::ShellError;
|
crate use crate::errors::ShellError;
|
||||||
use crate::evaluate::Scope;
|
use crate::evaluate::Scope;
|
||||||
use crate::parser::parse2::span::Spanned;
|
use crate::parser::parse::span::Spanned;
|
||||||
use crate::parser::registry;
|
use crate::parser::registry;
|
||||||
use crate::parser::{Pipeline, PipelineElement, TokenNode};
|
use crate::parser::{Pipeline, PipelineElement, TokenNode};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ use clap::{App, Arg};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
crate use parser::parse2::text::Text;
|
crate use parser::parse::text::Text;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let matches = App::new("nu shell")
|
let matches = App::new("nu shell")
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
crate mod hir;
|
crate mod hir;
|
||||||
crate mod parse2;
|
crate mod parse;
|
||||||
crate mod parse_command;
|
crate mod parse_command;
|
||||||
crate mod registry;
|
crate mod registry;
|
||||||
|
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
|
|
||||||
crate use hir::baseline_parse_tokens::baseline_parse_tokens;
|
crate use hir::baseline_parse_tokens::baseline_parse_tokens;
|
||||||
crate use parse2::call_node::CallNode;
|
crate use parse::call_node::CallNode;
|
||||||
crate use parse2::files::Files;
|
crate use parse::files::Files;
|
||||||
crate use parse2::flag::Flag;
|
crate use parse::flag::Flag;
|
||||||
crate use parse2::operator::Operator;
|
crate use parse::operator::Operator;
|
||||||
crate use parse2::parser::{nom_input, pipeline};
|
crate use parse::parser::{nom_input, pipeline};
|
||||||
crate use parse2::pipeline::{Pipeline, PipelineElement};
|
crate use parse::pipeline::{Pipeline, PipelineElement};
|
||||||
crate use parse2::span::{Span, Spanned};
|
crate use parse::span::{Span, Spanned};
|
||||||
crate use parse2::text::Text;
|
crate use parse::text::Text;
|
||||||
crate use parse2::token_tree::TokenNode;
|
crate use parse::token_tree::TokenNode;
|
||||||
crate use parse2::tokens::{RawToken, Token};
|
crate use parse::tokens::{RawToken, Token};
|
||||||
crate use parse2::unit::Unit;
|
crate use parse::unit::Unit;
|
||||||
crate use parse_command::parse_command;
|
crate use parse_command::parse_command;
|
||||||
crate use registry::CommandRegistry;
|
crate use registry::CommandRegistry;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
crate mod expression;
|
|
||||||
crate mod expression_builder;
|
|
||||||
crate mod module;
|
|
||||||
crate mod module_builder;
|
|
||||||
crate mod parser_utils;
|
|
||||||
|
|
||||||
crate use expression::{
|
|
||||||
Bare, Binary, Block, Call, Expression, Flag, Leaf, Operator, ParameterIdentifier,
|
|
||||||
Parenthesized, Path, Pipeline, RawExpression, Unit, Variable,
|
|
||||||
};
|
|
||||||
crate use expression_builder::ExpressionBuilder;
|
|
||||||
crate use module::{Module};
|
|
||||||
crate use module_builder::ModuleBuilder;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
crate use module::RawItem;
|
|
|
@ -1,540 +0,0 @@
|
||||||
use crate::parser::lexer::{Span, Spanned};
|
|
||||||
use crate::prelude::*;
|
|
||||||
use adhoc_derive::FromStr;
|
|
||||||
use derive_new::new;
|
|
||||||
use getset::Getters;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use std::io::Write;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
|
||||||
pub enum Operator {
|
|
||||||
Equal,
|
|
||||||
NotEqual,
|
|
||||||
LessThan,
|
|
||||||
GreaterThan,
|
|
||||||
LessThanOrEqual,
|
|
||||||
GreaterThanOrEqual,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Operator {
|
|
||||||
pub fn print(&self) -> String {
|
|
||||||
self.as_str().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
match *self {
|
|
||||||
Operator::Equal => "==",
|
|
||||||
Operator::NotEqual => "!=",
|
|
||||||
Operator::LessThan => "<",
|
|
||||||
Operator::GreaterThan => ">",
|
|
||||||
Operator::LessThanOrEqual => "<=",
|
|
||||||
Operator::GreaterThanOrEqual => ">=",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Operator {
|
|
||||||
fn from(input: &str) -> Operator {
|
|
||||||
Operator::from_str(input).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Operator {
|
|
||||||
type Err = ();
|
|
||||||
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
|
|
||||||
match input {
|
|
||||||
"==" => Ok(Operator::Equal),
|
|
||||||
"!=" => Ok(Operator::NotEqual),
|
|
||||||
"<" => Ok(Operator::LessThan),
|
|
||||||
">" => Ok(Operator::GreaterThan),
|
|
||||||
"<=" => Ok(Operator::LessThanOrEqual),
|
|
||||||
">=" => Ok(Operator::GreaterThanOrEqual),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub struct Expression {
|
|
||||||
crate expr: RawExpression,
|
|
||||||
crate span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Deref for Expression {
|
|
||||||
type Target = RawExpression;
|
|
||||||
|
|
||||||
fn deref(&self) -> &RawExpression {
|
|
||||||
&self.expr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Expression {
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
self.expr.print()
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn as_external_arg(&self) -> String {
|
|
||||||
self.expr.as_external_arg()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum RawExpression {
|
|
||||||
Leaf(Leaf),
|
|
||||||
Flag(Flag),
|
|
||||||
Parenthesized(Box<Parenthesized>),
|
|
||||||
Block(Box<Block>),
|
|
||||||
Binary(Box<Binary>),
|
|
||||||
Path(Box<Path>),
|
|
||||||
Call(Box<Call>),
|
|
||||||
VariableReference(Variable),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RawExpression {
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
RawExpression::Call(c) => c.print(),
|
|
||||||
RawExpression::Leaf(l) => l.print(),
|
|
||||||
RawExpression::Flag(f) => f.print(),
|
|
||||||
RawExpression::Parenthesized(p) => p.print(),
|
|
||||||
RawExpression::Block(b) => b.print(),
|
|
||||||
RawExpression::VariableReference(r) => r.print(),
|
|
||||||
RawExpression::Path(p) => p.print(),
|
|
||||||
RawExpression::Binary(b) => b.print(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn as_external_arg(&self) -> String {
|
|
||||||
match self {
|
|
||||||
RawExpression::Call(c) => c.as_external_arg(),
|
|
||||||
RawExpression::Leaf(l) => l.as_external_arg(),
|
|
||||||
RawExpression::Flag(f) => f.as_external_arg(),
|
|
||||||
RawExpression::Parenthesized(p) => p.as_external_arg(),
|
|
||||||
RawExpression::Block(b) => b.as_external_arg(),
|
|
||||||
RawExpression::VariableReference(r) => r.as_external_arg(),
|
|
||||||
RawExpression::Path(p) => p.as_external_arg(),
|
|
||||||
RawExpression::Binary(b) => b.as_external_arg(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn as_string(&self) -> Option<String> {
|
|
||||||
match self {
|
|
||||||
RawExpression::Leaf(Leaf::String(s)) => Some(s.to_string()),
|
|
||||||
RawExpression::Leaf(Leaf::Bare(path)) => Some(path.to_string()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn as_bare(&self) -> Option<String> {
|
|
||||||
match self {
|
|
||||||
RawExpression::Leaf(Leaf::Bare(p)) => Some(p.to_string()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn as_block(&self) -> Option<Block> {
|
|
||||||
match self {
|
|
||||||
RawExpression::Block(block) => Some(*block.clone()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn is_flag(&self, value: &str) -> bool {
|
|
||||||
match self {
|
|
||||||
RawExpression::Flag(Flag::Longhand(f)) if value == f => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, new)]
|
|
||||||
pub struct Block {
|
|
||||||
crate expr: Expression,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Block {
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
format!("{{ {} }}", self.expr.print())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
format!("{{ {} }}", self.expr.as_external_arg())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, new)]
|
|
||||||
pub struct Parenthesized {
|
|
||||||
crate expr: Expression,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parenthesized {
|
|
||||||
fn print(&self) -> String {
|
|
||||||
format!("({})", self.expr.print())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
format!("({})", self.expr.as_external_arg())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Getters, new)]
|
|
||||||
pub struct Path {
|
|
||||||
#[get = "crate"]
|
|
||||||
head: Expression,
|
|
||||||
|
|
||||||
#[get = "crate"]
|
|
||||||
tail: Vec<Spanned<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Path {
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
let mut out = self.head.print();
|
|
||||||
|
|
||||||
for item in self.tail.iter() {
|
|
||||||
out.push_str(&format!(".{}", item.item));
|
|
||||||
}
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn as_external_arg(&self) -> String {
|
|
||||||
let mut out = self.head.as_external_arg();
|
|
||||||
|
|
||||||
for item in self.tail.iter() {
|
|
||||||
out.push_str(&format!(".{}", item.item));
|
|
||||||
}
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum Variable {
|
|
||||||
It,
|
|
||||||
Other(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Variable {
|
|
||||||
crate fn from_string(s: &str) -> Variable {
|
|
||||||
match s {
|
|
||||||
"it" => ast::Variable::It,
|
|
||||||
_ => ast::Variable::Other(s.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Variable::It => format!("$it"),
|
|
||||||
Variable::Other(s) => format!("${}", s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
self.print()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, new, Getters)]
|
|
||||||
pub struct Bare {
|
|
||||||
#[get = "crate"]
|
|
||||||
body: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for Bare {
|
|
||||||
fn from(input: String) -> Bare {
|
|
||||||
Bare { body: input }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Bare {
|
|
||||||
fn from(input: &str) -> Bare {
|
|
||||||
Bare {
|
|
||||||
body: input.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bare {
|
|
||||||
crate fn from_string(string: impl Into<String>) -> Bare {
|
|
||||||
Bare {
|
|
||||||
body: string.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn to_string(&self) -> String {
|
|
||||||
self.body.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, FromStr)]
|
|
||||||
pub enum Unit {
|
|
||||||
#[adhoc(regex = "^B$")]
|
|
||||||
B,
|
|
||||||
#[adhoc(regex = "^KB$")]
|
|
||||||
KB,
|
|
||||||
#[adhoc(regex = "^MB$")]
|
|
||||||
MB,
|
|
||||||
#[adhoc(regex = "^GB$")]
|
|
||||||
GB,
|
|
||||||
#[adhoc(regex = "^TB$")]
|
|
||||||
TB,
|
|
||||||
#[adhoc(regex = "^PB$")]
|
|
||||||
PB,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Unit {
|
|
||||||
fn from(input: &str) -> Unit {
|
|
||||||
Unit::from_str(input).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Unit {
|
|
||||||
crate fn to_string(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Unit::B => "B",
|
|
||||||
Unit::KB => "KB",
|
|
||||||
Unit::MB => "MB",
|
|
||||||
Unit::GB => "GB",
|
|
||||||
Unit::TB => "TB",
|
|
||||||
Unit::PB => "PB",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum RawParameterIdentifier {
|
|
||||||
#[allow(unused)]
|
|
||||||
Bare(Spanned<Bare>),
|
|
||||||
Var(Spanned<Variable>),
|
|
||||||
ShorthandFlag(Spanned<String>),
|
|
||||||
LonghandFlag(Spanned<String>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RawParameterIdentifier {
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
RawParameterIdentifier::Bare(b) => b.to_string(),
|
|
||||||
RawParameterIdentifier::Var(v) => v.print(),
|
|
||||||
RawParameterIdentifier::ShorthandFlag(f) => f.to_string(),
|
|
||||||
RawParameterIdentifier::LonghandFlag(f) => f.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type ParameterIdentifier = Spanned<RawParameterIdentifier>;
|
|
||||||
|
|
||||||
impl ParameterIdentifier {
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn bare(bare: Spanned<Bare>, span: impl Into<Span>) -> ParameterIdentifier {
|
|
||||||
let id = RawParameterIdentifier::Bare(bare);
|
|
||||||
Spanned::from_item(id, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn var(var: Spanned<Variable>, span: impl Into<Span>) -> ParameterIdentifier {
|
|
||||||
let id = RawParameterIdentifier::Var(var);
|
|
||||||
Spanned::from_item(id, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flag(flag: Spanned<String>, span: impl Into<Span>) -> ParameterIdentifier {
|
|
||||||
let id = RawParameterIdentifier::LonghandFlag(flag);
|
|
||||||
Spanned::from_item(id, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shorthand(flag: Spanned<String>, span: impl Into<Span>) -> ParameterIdentifier {
|
|
||||||
let id = RawParameterIdentifier::ShorthandFlag(flag);
|
|
||||||
Spanned::from_item(id, span)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum Leaf {
|
|
||||||
String(String),
|
|
||||||
Bare(Bare),
|
|
||||||
Boolean(bool),
|
|
||||||
Int(i64),
|
|
||||||
Unit(i64, Unit),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Leaf {
|
|
||||||
fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Leaf::String(s) => format!("{:?}", s),
|
|
||||||
Leaf::Bare(path) => format!("{}", path.to_string()),
|
|
||||||
Leaf::Boolean(b) => format!("{}", b),
|
|
||||||
Leaf::Int(i) => format!("{}", i),
|
|
||||||
Leaf::Unit(i, unit) => format!("{}{:?}", i, unit),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Leaf::String(s) => {
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
format!("{}", s)
|
|
||||||
}
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
format!("\"{}\"", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Leaf::Bare(path) => format!("{}", path.to_string()),
|
|
||||||
Leaf::Boolean(b) => format!("{}", b),
|
|
||||||
Leaf::Int(i) => format!("{}", i),
|
|
||||||
Leaf::Unit(i, unit) => format!("{}{:?}", i, unit),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub struct Binary {
|
|
||||||
crate left: Expression,
|
|
||||||
crate operator: Spanned<Operator>,
|
|
||||||
crate right: Expression,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Binary {
|
|
||||||
crate fn new(
|
|
||||||
left: impl Into<Expression>,
|
|
||||||
operator: Spanned<Operator>,
|
|
||||||
right: impl Into<Expression>,
|
|
||||||
) -> Binary {
|
|
||||||
Binary {
|
|
||||||
left: left.into(),
|
|
||||||
operator,
|
|
||||||
right: right.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Binary {
|
|
||||||
fn print(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
self.left.print(),
|
|
||||||
self.operator.print(),
|
|
||||||
self.right.print()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
self.left.as_external_arg(),
|
|
||||||
self.operator.print(),
|
|
||||||
self.right.as_external_arg()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum Flag {
|
|
||||||
Shorthand(String),
|
|
||||||
Longhand(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Flag {
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
Flag::Shorthand(s) => format!("-{}", s),
|
|
||||||
Flag::Longhand(s) => format!("--{}", s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn as_external_arg(&self) -> String {
|
|
||||||
self.print()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, new)]
|
|
||||||
pub struct Call {
|
|
||||||
crate name: Expression,
|
|
||||||
crate args: Option<Vec<Expression>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(Expression, Vec<Expression>)> for Call {
|
|
||||||
fn from(input: (Expression, Vec<Expression>)) -> Call {
|
|
||||||
Call {
|
|
||||||
name: input.0,
|
|
||||||
args: if input.1.len() == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(input.1)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Expression> for Call {
|
|
||||||
fn from(input: Expression) -> Call {
|
|
||||||
Call {
|
|
||||||
name: input,
|
|
||||||
args: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Call {
|
|
||||||
fn as_external_arg(&self) -> String {
|
|
||||||
let mut out = vec![];
|
|
||||||
|
|
||||||
write!(out, "{}", self.name.as_external_arg()).unwrap();
|
|
||||||
|
|
||||||
if let Some(args) = &self.args {
|
|
||||||
for arg in args.iter() {
|
|
||||||
write!(out, " {}", arg.as_external_arg()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String::from_utf8_lossy(&out).into_owned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print(&self) -> String {
|
|
||||||
let mut out = vec![];
|
|
||||||
|
|
||||||
write!(out, "{}", self.name.print()).unwrap();
|
|
||||||
|
|
||||||
if let Some(args) = &self.args {
|
|
||||||
for arg in args.iter() {
|
|
||||||
write!(out, " {}", arg.print()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String::from_utf8_lossy(&out).into_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(new, Debug, Eq, PartialEq, Clone)]
|
|
||||||
pub struct Pipeline {
|
|
||||||
crate commands: Vec<Expression>,
|
|
||||||
crate trailing: Span,
|
|
||||||
crate span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pipeline {
|
|
||||||
crate fn from_parts(
|
|
||||||
command: Expression,
|
|
||||||
rest: Vec<Expression>,
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> Pipeline {
|
|
||||||
let mut commands = vec![command];
|
|
||||||
commands.extend(rest);
|
|
||||||
|
|
||||||
Pipeline {
|
|
||||||
commands,
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
itertools::join(self.commands.iter().map(|i| i.print()), " | ")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,401 +0,0 @@
|
||||||
use crate::parser::lexer::{Span, Spanned};
|
|
||||||
use derive_new::new;
|
|
||||||
|
|
||||||
use crate::parser::ast::{self, Expression, RawExpression};
|
|
||||||
|
|
||||||
#[derive(new)]
|
|
||||||
pub struct ExpressionBuilder {
|
|
||||||
#[new(default)]
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
impl ExpressionBuilder {
|
|
||||||
pub fn op(&mut self, input: impl Into<ast::Operator>) -> Spanned<ast::Operator> {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
let (start, end) = self.consume(input.as_str());
|
|
||||||
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_op(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_op(
|
|
||||||
input: impl Into<ast::Operator>,
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> Spanned<ast::Operator> {
|
|
||||||
Spanned {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
item: input.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string(&mut self, input: impl Into<String>) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
let (start, _) = self.consume("\"");
|
|
||||||
self.consume(&input);
|
|
||||||
let (_, end) = self.consume("\"");
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_string(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_string(input: impl Into<String>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Leaf(ast::Leaf::String(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bare(&mut self, input: impl Into<ast::Bare>) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
let (start, end) = self.consume(input.body());
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_bare(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_bare(input: impl Into<ast::Bare>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Leaf(ast::Leaf::Bare(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn boolean(&mut self, input: impl Into<bool>) -> Expression {
|
|
||||||
let boolean = input.into();
|
|
||||||
|
|
||||||
let (start, end) = match boolean {
|
|
||||||
true => self.consume("$yes"),
|
|
||||||
false => self.consume("$no"),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_boolean(boolean, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_boolean(input: impl Into<bool>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Leaf(ast::Leaf::Boolean(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn int(&mut self, input: impl Into<i64>) -> Expression {
|
|
||||||
let int = input.into();
|
|
||||||
|
|
||||||
let (start, end) = self.consume(&int.to_string());
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_int(int, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_int(input: impl Into<i64>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Leaf(ast::Leaf::Int(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unit(&mut self, input: (impl Into<i64>, impl Into<ast::Unit>)) -> Expression {
|
|
||||||
let (int, unit) = (input.0.into(), input.1.into());
|
|
||||||
|
|
||||||
let (start, _) = self.consume(&int.to_string());
|
|
||||||
let (_, end) = self.consume(&unit.to_string());
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_unit((int, unit), start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_unit(
|
|
||||||
input: (impl Into<i64>, impl Into<ast::Unit>),
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> Expression {
|
|
||||||
let (int, unit) = (input.0.into(), input.1.into());
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Leaf(ast::Leaf::Unit(int, unit)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flag(&mut self, input: impl Into<String>) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
let (start, _) = self.consume("--");
|
|
||||||
let (_, end) = self.consume(&input);
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_flag(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_flag(input: impl Into<String>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Flag(ast::Flag::Longhand(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shorthand(&mut self, input: impl Into<String>) -> Expression {
|
|
||||||
let int = input.into();
|
|
||||||
|
|
||||||
let size = int.to_string().len();
|
|
||||||
|
|
||||||
let start = self.pos;
|
|
||||||
let end = self.pos + size + 1;
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_shorthand(int, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_shorthand(input: impl Into<String>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Flag(ast::Flag::Shorthand(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parens(
|
|
||||||
&mut self,
|
|
||||||
input: impl FnOnce(&mut ExpressionBuilder) -> Expression,
|
|
||||||
) -> Expression {
|
|
||||||
let (start, _) = self.consume("(");
|
|
||||||
let input = input(self);
|
|
||||||
let (_, end) = self.consume(")");
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_parens(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_parens(input: Expression, start: usize, end: usize) -> Expression {
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Parenthesized(Box::new(ast::Parenthesized::new(input))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn raw_block(
|
|
||||||
&mut self,
|
|
||||||
input: &dyn Fn(&mut ExpressionBuilder) -> Expression,
|
|
||||||
) -> Spanned<ast::Block> {
|
|
||||||
let (start, _) = self.consume("{ ");
|
|
||||||
let input = input(self);
|
|
||||||
let (_, end) = self.consume(" }");
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_raw_block(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_raw_block(input: Expression, start: usize, end: usize) -> Spanned<ast::Block> {
|
|
||||||
Spanned::from_item(ast::Block::new(input), (start, end))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block(&mut self, input: &dyn Fn(&mut ExpressionBuilder) -> Expression) -> Expression {
|
|
||||||
let (start, _) = self.consume("{ ");
|
|
||||||
let input = input(self);
|
|
||||||
let (_, end) = self.consume(" }");
|
|
||||||
self.pos = end;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_block(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_block(input: Expression, start: usize, end: usize) -> Expression {
|
|
||||||
let block = ast::Block::new(input);
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Block(Box::new(block)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn binary(
|
|
||||||
&mut self,
|
|
||||||
input: (
|
|
||||||
&dyn Fn(&mut ExpressionBuilder) -> Expression,
|
|
||||||
&dyn Fn(&mut ExpressionBuilder) -> Spanned<ast::Operator>,
|
|
||||||
&dyn Fn(&mut ExpressionBuilder) -> Expression,
|
|
||||||
),
|
|
||||||
) -> Expression {
|
|
||||||
let start = self.pos;
|
|
||||||
|
|
||||||
let left = (input.0)(self);
|
|
||||||
self.consume(" ");
|
|
||||||
let operator = (input.1)(self);
|
|
||||||
self.consume(" ");
|
|
||||||
let right = (input.2)(self);
|
|
||||||
|
|
||||||
let end = self.pos;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_binary((left, operator, right), start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_binary(
|
|
||||||
input: (
|
|
||||||
impl Into<Expression>,
|
|
||||||
impl Into<Spanned<ast::Operator>>,
|
|
||||||
impl Into<Expression>,
|
|
||||||
),
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> Expression {
|
|
||||||
let binary = ast::Binary::new(input.0, input.1.into(), input.2);
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Binary(Box::new(binary)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(
|
|
||||||
&mut self,
|
|
||||||
input: (
|
|
||||||
&dyn Fn(&mut ExpressionBuilder) -> Expression,
|
|
||||||
Vec<impl Into<String>>,
|
|
||||||
),
|
|
||||||
) -> Expression {
|
|
||||||
let start = self.pos;
|
|
||||||
|
|
||||||
let head = (input.0)(self);
|
|
||||||
|
|
||||||
let mut tail = vec![];
|
|
||||||
|
|
||||||
for item in input.1 {
|
|
||||||
self.consume(".");
|
|
||||||
let item = item.into();
|
|
||||||
let (start, end) = self.consume(&item);
|
|
||||||
tail.push(Spanned::new(Span::from((start, end)), item));
|
|
||||||
}
|
|
||||||
|
|
||||||
let end = self.pos;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_path((head, tail), start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_path(
|
|
||||||
input: (impl Into<Expression>, Vec<Spanned<String>>),
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> Expression {
|
|
||||||
let path = ast::Path::new(input.0.into(), input.1);
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Path(Box::new(path)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(
|
|
||||||
&mut self,
|
|
||||||
input: (
|
|
||||||
&(dyn Fn(&mut ExpressionBuilder) -> Expression),
|
|
||||||
Vec<&dyn Fn(&mut ExpressionBuilder) -> Expression>,
|
|
||||||
),
|
|
||||||
) -> Expression {
|
|
||||||
let start = self.pos;
|
|
||||||
|
|
||||||
let name = (&input.0)(self);
|
|
||||||
|
|
||||||
let mut args = vec![];
|
|
||||||
|
|
||||||
for item in input.1 {
|
|
||||||
self.consume(" ");
|
|
||||||
args.push(item(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
let end = self.pos;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_call((name, args), start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_call(input: impl Into<ast::Call>, start: usize, end: usize) -> Expression {
|
|
||||||
let call = input.into();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr: RawExpression::Call(Box::new(call)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn var(&mut self, input: impl Into<String>) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
let (start, _) = self.consume("$");
|
|
||||||
let (_, end) = self.consume(&input);
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_var(input, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_var(input: impl Into<String>, start: usize, end: usize) -> Expression {
|
|
||||||
let input = input.into();
|
|
||||||
|
|
||||||
let expr = match &input[..] {
|
|
||||||
"it" => RawExpression::VariableReference(ast::Variable::It),
|
|
||||||
_ => RawExpression::VariableReference(ast::Variable::Other(input)),
|
|
||||||
};
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
expr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pipeline(
|
|
||||||
&mut self,
|
|
||||||
input: Vec<&dyn Fn(&mut ExpressionBuilder) -> Expression>,
|
|
||||||
) -> ast::Pipeline {
|
|
||||||
let start = self.pos;
|
|
||||||
|
|
||||||
let mut exprs = vec![];
|
|
||||||
let mut input = input.into_iter();
|
|
||||||
|
|
||||||
let next = input.next().unwrap();
|
|
||||||
exprs.push(next(self));
|
|
||||||
|
|
||||||
for item in input {
|
|
||||||
self.consume(" | ");
|
|
||||||
exprs.push(item(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
let end = self.pos;
|
|
||||||
|
|
||||||
ExpressionBuilder::spanned_pipeline(exprs, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_pipeline(input: Vec<Expression>, start: usize, end: usize) -> ast::Pipeline {
|
|
||||||
ast::Pipeline {
|
|
||||||
span: Span::from((start, end)),
|
|
||||||
commands: input,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sp(&mut self) {
|
|
||||||
self.consume(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ws(&mut self, input: &str) {
|
|
||||||
self.consume(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consume(&mut self, input: &str) -> (usize, usize) {
|
|
||||||
let start = self.pos;
|
|
||||||
self.pos += input.len();
|
|
||||||
(start, self.pos)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
use crate::parser::ast;
|
|
||||||
use crate::parser::lexer::{Span, Spanned};
|
|
||||||
use derive_new::new;
|
|
||||||
|
|
||||||
#[derive(new, Eq, PartialEq, Clone, Debug)]
|
|
||||||
pub struct Module {
|
|
||||||
span: Span,
|
|
||||||
items: Vec<Item>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Module {
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
let mut iter = self.items.iter();
|
|
||||||
|
|
||||||
let first = iter.next().unwrap();
|
|
||||||
let mut out = first.print();
|
|
||||||
|
|
||||||
for item in iter {
|
|
||||||
out.push_str(&format!("\n{}", item.print()));
|
|
||||||
}
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
|
||||||
pub enum RawItem {
|
|
||||||
Expression(ast::Pipeline),
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
Function(Function),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RawItem {
|
|
||||||
fn print(&self) -> String {
|
|
||||||
match self {
|
|
||||||
RawItem::Expression(p) => p.print(),
|
|
||||||
RawItem::Function(f) => f.print(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Item = Spanned<RawItem>;
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
|
||||||
pub enum Type {
|
|
||||||
Any,
|
|
||||||
Int,
|
|
||||||
Decimal,
|
|
||||||
Bytes,
|
|
||||||
Text,
|
|
||||||
Boolean,
|
|
||||||
Date,
|
|
||||||
Object,
|
|
||||||
List,
|
|
||||||
Block,
|
|
||||||
// Object(IndexMap<Spanned<String>, Spanned<Type>>),
|
|
||||||
// List(Box<Spanned<Type>>),
|
|
||||||
// Block {
|
|
||||||
// arguments: Spanned<Vec<Spanned<Type>>>,
|
|
||||||
// return_type: Box<Spanned<Type>>,
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
#[allow(unused)]
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Any => "any",
|
|
||||||
Int => "int",
|
|
||||||
Decimal => "decimal",
|
|
||||||
Bytes => "bytes",
|
|
||||||
Text => "text",
|
|
||||||
Boolean => "boolean",
|
|
||||||
Date => "date",
|
|
||||||
Object => "object",
|
|
||||||
List => "list",
|
|
||||||
Block => "block",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, new)]
|
|
||||||
pub struct FormalParameter {
|
|
||||||
name: ast::ParameterIdentifier,
|
|
||||||
ty: Spanned<Type>,
|
|
||||||
span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, new)]
|
|
||||||
pub struct Function {
|
|
||||||
name: Spanned<ast::Bare>,
|
|
||||||
params: Vec<FormalParameter>,
|
|
||||||
return_type: Option<Box<Spanned<Type>>>,
|
|
||||||
body: Spanned<ast::Block>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Function {
|
|
||||||
crate fn print(&self) -> String {
|
|
||||||
use pretty::{BoxDoc, Doc};
|
|
||||||
|
|
||||||
let doc: Doc<BoxDoc<()>> = Doc::text("function")
|
|
||||||
.append(Doc::space())
|
|
||||||
.append(Doc::text(self.name.item.to_string()))
|
|
||||||
// todo: signature
|
|
||||||
.append(Doc::space())
|
|
||||||
.append(Doc::text("{"))
|
|
||||||
.append(Doc::newline())
|
|
||||||
.append(Doc::text(self.body.print()).nest(1))
|
|
||||||
.append(Doc::newline())
|
|
||||||
.append(Doc::text("}"));
|
|
||||||
|
|
||||||
format!("{}", doc.pretty(80))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
use crate::parser::ast::module::{Item, Module};
|
|
||||||
use crate::parser::ast::{self, module};
|
|
||||||
use crate::parser::lexer::{Span, Spanned};
|
|
||||||
use derive_new::new;
|
|
||||||
|
|
||||||
#[derive(new)]
|
|
||||||
pub struct ModuleBuilder {
|
|
||||||
#[new(default)]
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
impl ModuleBuilder {
|
|
||||||
// crate fn function(&mut self, input: ) -> Function {}
|
|
||||||
|
|
||||||
crate fn spanned_function(
|
|
||||||
input: (
|
|
||||||
Spanned<ast::Bare>,
|
|
||||||
Vec<module::FormalParameter>,
|
|
||||||
Option<Spanned<module::Type>>,
|
|
||||||
Spanned<ast::Block>,
|
|
||||||
),
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> module::Function {
|
|
||||||
module::Function::new(input.0, input.1, input.2.map(Box::new), input.3)
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn spanned_formal_parameter(
|
|
||||||
input: (ast::ParameterIdentifier, Spanned<module::Type>),
|
|
||||||
start: usize,
|
|
||||||
end: usize,
|
|
||||||
) -> module::FormalParameter {
|
|
||||||
module::FormalParameter::new(input.0, input.1, Span::from((start, end)))
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn items(&mut self, input: Vec<&dyn Fn(&mut ModuleBuilder) -> Item>) -> Module {
|
|
||||||
let start = self.pos;
|
|
||||||
|
|
||||||
let mut items = vec![];
|
|
||||||
let mut input = input.into_iter();
|
|
||||||
|
|
||||||
let next = input.next().unwrap();
|
|
||||||
items.push(next(self));
|
|
||||||
|
|
||||||
for item in input {
|
|
||||||
self.consume(" | ");
|
|
||||||
items.push(item(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
let end = self.pos;
|
|
||||||
|
|
||||||
ModuleBuilder::spanned_items(items, start, end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn spanned_items(input: Vec<Item>, start: usize, end: usize) -> ast::Module {
|
|
||||||
ast::Module::new(Span::from((start, end)), input)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sp(&mut self) {
|
|
||||||
self.consume(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ws(&mut self, input: &str) {
|
|
||||||
self.consume(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn newline(&mut self) {
|
|
||||||
self.consume("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consume(&mut self, input: &str) -> (usize, usize) {
|
|
||||||
let start = self.pos;
|
|
||||||
self.pos += input.len();
|
|
||||||
(start, self.pos)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
crate fn concat<T>(item: T, rest: Vec<T>) -> Vec<T> {
|
|
||||||
let mut out = vec![item];
|
|
||||||
out.extend(rest);
|
|
||||||
out
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
use crate::prelude::*;
|
|
||||||
use rustyline::{completion, Context};
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
crate struct Completer {
|
|
||||||
commands: BTreeMap<String, Box<dyn Command>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl completion::Completer for Completer {
|
|
||||||
type Candidate = completion::Pair;
|
|
||||||
|
|
||||||
fn complete(
|
|
||||||
&self,
|
|
||||||
_line: &str,
|
|
||||||
_pos: usize,
|
|
||||||
_ctx: &Context<'_>,
|
|
||||||
) -> rustyline::Result<(usize, Vec<completion::Pair>)> {
|
|
||||||
let pairs: Vec<completion::Pair> = self
|
|
||||||
.commands
|
|
||||||
.keys()
|
|
||||||
.map(|k| completion::Pair {
|
|
||||||
display: k.clone(),
|
|
||||||
replacement: k.clone(),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok((0, pairs))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) {
|
|
||||||
let end = line.pos();
|
|
||||||
line.replace(start..end, elected)
|
|
||||||
}
|
|
||||||
}
|
|
1242
src/parser/lexer.rs
1242
src/parser/lexer.rs
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
use crate::parser::parse2::span::Span;
|
use crate::parser::parse::span::Span;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use language_reporting::{FileName, Location};
|
use language_reporting::{FileName, Location};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
use crate::parser::parse2::{
|
use crate::parser::parse::{
|
||||||
call_node::*, flag::*, operator::*, pipeline::*, span::*, token_tree::*, token_tree_builder::*,
|
call_node::*, flag::*, operator::*, pipeline::*, span::*, token_tree::*, token_tree_builder::*,
|
||||||
tokens::*, unit::*,
|
tokens::*, unit::*,
|
||||||
};
|
};
|
||||||
|
@ -552,8 +552,8 @@ fn is_id_continue(c: char) -> bool {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parser::parse2::token_tree_builder::TokenTreeBuilder as b;
|
use crate::parser::parse::token_tree_builder::TokenTreeBuilder as b;
|
||||||
use crate::parser::parse2::token_tree_builder::{CurriedToken, TokenTreeBuilder};
|
use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
macro_rules! assert_leaf {
|
macro_rules! assert_leaf {
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::parser::parse2::{call_node::*, flag::*, operator::*, pipeline::*, span::*, tokens::*};
|
use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, span::*, tokens::*};
|
||||||
use crate::Text;
|
use crate::Text;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use enum_utils::FromStr;
|
use enum_utils::FromStr;
|
|
@ -1,13 +1,13 @@
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::parser::parse2::flag::{Flag, FlagKind};
|
use crate::parser::parse::flag::{Flag, FlagKind};
|
||||||
use crate::parser::parse2::operator::Operator;
|
use crate::parser::parse::operator::Operator;
|
||||||
use crate::parser::parse2::pipeline::{Pipeline, PipelineElement};
|
use crate::parser::parse::pipeline::{Pipeline, PipelineElement};
|
||||||
use crate::parser::parse2::span::{Span, Spanned};
|
use crate::parser::parse::span::{Span, Spanned};
|
||||||
use crate::parser::parse2::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
use crate::parser::parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||||
use crate::parser::parse2::tokens::{RawToken, Token};
|
use crate::parser::parse::tokens::{RawToken, Token};
|
||||||
use crate::parser::parse2::unit::Unit;
|
use crate::parser::parse::unit::Unit;
|
||||||
use crate::parser::CallNode;
|
use crate::parser::CallNode;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::parser::parse2::span::*;
|
use crate::parser::parse::span::*;
|
||||||
use crate::parser::parse2::unit::*;
|
use crate::parser::parse::unit::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub enum RawToken {
|
pub enum RawToken {
|
|
@ -1,330 +0,0 @@
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
use crate::parser::ast::expression::*;
|
|
||||||
use crate::parser::ast::module::*;
|
|
||||||
use crate::parser::ast::parser_utils::*;
|
|
||||||
use crate::parser::ast::{ExpressionBuilder, ModuleBuilder};
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::parser::lexer::{SpannedToken, Spanned, Span, Token};
|
|
||||||
use byte_unit::Byte;
|
|
||||||
|
|
||||||
// nu's grammar is a little bit different from a lot of other languages, to better match
|
|
||||||
// the idioms and constraints of a shell environment. A lot of the constraints are
|
|
||||||
// the same as PowerShell, but mostly derived from the same first principles.
|
|
||||||
//
|
|
||||||
// - Other than at the beginning of a command, bare words are virtually always parsed as
|
|
||||||
// strings. This means that, in general, bare words cannot be used as keywords or
|
|
||||||
// variables.
|
|
||||||
// - Variable names begin with `$`, and so do keywords
|
|
||||||
// - Functions are invoked without `()` and without comma separation
|
|
||||||
// - In general, because of the lack of comma-separation, expressions must be grouped:
|
|
||||||
// - a single token
|
|
||||||
// - a path ($variable followed by any number of `"." member`)
|
|
||||||
// - parenthesized expression
|
|
||||||
// - This means that more elaborate expressions, like binary expressions, must usually
|
|
||||||
// be parenthesized
|
|
||||||
// - There is a special case for a command that takes a single expression, which can
|
|
||||||
// omit the parens
|
|
||||||
|
|
||||||
grammar<'input>;
|
|
||||||
|
|
||||||
// === MODULES === //
|
|
||||||
|
|
||||||
pub Module: Module = {
|
|
||||||
<l: @L> <first:Item> <items: ( ("newline")+ <Item> )*> <r: @R> => ModuleBuilder::spanned_items(concat(first, items), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
Item: Item = {
|
|
||||||
<l: @L> <pipeline:Pipeline> <r: @R> => Spanned::from_item(RawItem::Expression(pipeline), Span::from((l, r))),
|
|
||||||
<l: @L> <function:Function> <r: @R> => Spanned::from_item(RawItem::Function(function), Span::from((l, r))),
|
|
||||||
}
|
|
||||||
|
|
||||||
// === FUNCTIONS === //
|
|
||||||
|
|
||||||
Function: Function = {
|
|
||||||
<l: @L> "function" <bare: CommandName> "start-params"
|
|
||||||
<params: ParameterList>
|
|
||||||
"end-params" <ret: ("->" <Type>)?> <block: Block> <r: @R> => {
|
|
||||||
ModuleBuilder::spanned_function((bare, params, ret, block), l, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterList: Vec<FormalParameter> = {
|
|
||||||
<params: Comma<FormalParameter>> => params
|
|
||||||
}
|
|
||||||
|
|
||||||
FormalParameter: FormalParameter = {
|
|
||||||
<l: @L> <name: ParameterName> ":" <ty: Type> <r: @R> => ModuleBuilder::spanned_formal_parameter((name, ty), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterName: ParameterIdentifier = {
|
|
||||||
<l: @L> "-" <b: SpannedBare> <r: @R> => ParameterIdentifier::shorthand(b.map(|b| b.to_string()), (l, r)),
|
|
||||||
<l: @L> "--" <b: SpannedBare> <r: @R> => ParameterIdentifier::flag(b.map(|b| b.to_string()), (l, r)),
|
|
||||||
<l: @L> <var: ParameterVariable> <r: @R> => ParameterIdentifier::var(var, (l, r)),
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterVariable: Spanned<Variable> = {
|
|
||||||
<l: @L> "$" <v: "variable"> <r: @R> => Spanned::from_item(ast::Variable::from_string(v.as_slice()), (l, r)),
|
|
||||||
}
|
|
||||||
|
|
||||||
// === TYPES === //
|
|
||||||
|
|
||||||
Type: Spanned<Type> = {
|
|
||||||
<l: @L> <ty: RawType> <r: @R> => Spanned::from_item(ty, (l, r)),
|
|
||||||
}
|
|
||||||
|
|
||||||
RawType: Type = {
|
|
||||||
"any" => Type::Any,
|
|
||||||
"int" => Type::Int,
|
|
||||||
"decimal" => Type::Decimal,
|
|
||||||
"bytes" => Type::Bytes,
|
|
||||||
"text" => Type::Text,
|
|
||||||
"boolean" => Type::Boolean,
|
|
||||||
"date" => Type::Date,
|
|
||||||
|
|
||||||
// TODO: generics
|
|
||||||
"object" => Type::Object,
|
|
||||||
"list" => Type::List,
|
|
||||||
"block" => Type::Block,
|
|
||||||
}
|
|
||||||
|
|
||||||
// === EXPRESSIONS === //
|
|
||||||
|
|
||||||
pub ReplLine: Pipeline = {
|
|
||||||
<Pipeline> ("newline")*
|
|
||||||
}
|
|
||||||
|
|
||||||
Pipeline: Pipeline = {
|
|
||||||
<l: @L> <first:PipelineElement> <rest: ( "|" <PipelineElement> )*> <r: @R> => Pipeline::from_parts(first, rest, l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineElement: Expression = {
|
|
||||||
<l: @L> <bare: BareExpression> <r: @R> => ExpressionBuilder::spanned_call((bare, vec![]), l, r),
|
|
||||||
<SingleExpression> => <>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// A leaf expression is a single logical token that directly represents an expression
|
|
||||||
LeafExpression: Expression = {
|
|
||||||
<String>,
|
|
||||||
<l: @L> <int: Int> <r: @R> => ExpressionBuilder::spanned_int(int, l, r),
|
|
||||||
<UnitsNum>,
|
|
||||||
<Var>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub Call: Expression = {
|
|
||||||
<l: @L> <expr:Expression> <rest:SingleCallArgument> <r: @R> => ExpressionBuilder::spanned_call((expr, vec![rest]), l, r),
|
|
||||||
<l: @L> <expr:Expression> <first:CallArgument> <rest:( <CallArgument> )+> <r: @R> => ExpressionBuilder::spanned_call((expr, { let mut rest = rest; let mut v = vec![first]; v.append(&mut rest); v }), l, r),
|
|
||||||
<l: @L> <expr:BareExpression> <rest:SingleCallArgument> <r: @R> => ExpressionBuilder::spanned_call((expr, vec![rest]), l, r),
|
|
||||||
<l: @L> <expr:BareExpression> <first:CallArgument> <rest:( <CallArgument> )+> <r: @R> => ExpressionBuilder::spanned_call((expr, { let mut v = vec![first]; let mut rest = rest; v.append(&mut rest); v }), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
Binary: Expression = {
|
|
||||||
<l: @L> <left:ArgumentExpression> <op:SpannedOperator> <right:ArgumentExpression> <r: @R> => ExpressionBuilder::spanned_binary((left, op, right), l, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// In a block, a single bare word is interpreted as a call:
|
|
||||||
//
|
|
||||||
// foreach { ls }
|
|
||||||
Block: Spanned<Block> = {
|
|
||||||
<l: @L> "{" <expr: SingleExpression> "}" <r: @R> => ExpressionBuilder::spanned_raw_block(expr, l, r),
|
|
||||||
<l: @L> "{" <bare: BareExpression> "}" <r: @R> => {
|
|
||||||
let call = ExpressionBuilder::spanned_call(bare.clone(), bare.span.start, bare.span.end);
|
|
||||||
ExpressionBuilder::spanned_raw_block(call, l, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In a block, a single bare word is interpreted as a call:
|
|
||||||
//
|
|
||||||
// foreach { ls }
|
|
||||||
BlockExpression: Expression = {
|
|
||||||
<l: @L> "{" <expr: SingleExpression> "}" <r: @R> => ExpressionBuilder::spanned_block(expr, l, r),
|
|
||||||
<l: @L> "{" <bare: BareExpression> "}" <r: @R> => {
|
|
||||||
let call = ExpressionBuilder::spanned_call(bare.clone(), bare.span.start, bare.span.end);
|
|
||||||
ExpressionBuilder::spanned_block(call, l, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// An `Expression` is the most general kind of expression. It can go anywhere, even right next to another expression, and
|
|
||||||
// even as the first part of a call.
|
|
||||||
MemberHeadExpression: Expression = {
|
|
||||||
<LeafExpression> => <>,
|
|
||||||
<BlockExpression> => <>,
|
|
||||||
<l: @L> "(" <expr: Call> ")" <r: @R> => ExpressionBuilder::spanned_call(expr, l, r),
|
|
||||||
<l: @L> "(" <expr: BareExpression> ")" <r: @R> => ExpressionBuilder::spanned_call((expr, vec![]), l, r),
|
|
||||||
<l: @L> "(" <expr:Binary> ")" <r: @R> => ExpressionBuilder::spanned_parens(expr, l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression: Expression = {
|
|
||||||
<MemberHeadExpression> => <>,
|
|
||||||
<l: @L> <expr:MemberHeadExpression> <rest: ( "???." <Member> )+> <r: @R> => ExpressionBuilder::spanned_path((expr, rest), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
// An `ArgumentExpression` is an expression that appears in an argument list. It includes all of `Expression`, and
|
|
||||||
// bare words are interpreted as strings.
|
|
||||||
ArgumentExpression: Expression = {
|
|
||||||
<Expression>,
|
|
||||||
<BareExpression>,
|
|
||||||
}
|
|
||||||
|
|
||||||
CallArgument: Expression = {
|
|
||||||
<ArgumentExpression>,
|
|
||||||
<Flag>,
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleCallArgument: Expression = {
|
|
||||||
<CallArgument>,
|
|
||||||
<Binary>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// A `SingleExpression` is a special-case of `Expression` for situations where expressions do not appear side-by-side.
|
|
||||||
// Because expression lists in nu are not comma-separated, composite expressions (like binary expressions) must be
|
|
||||||
// parenthesized in lists. If only a single expression appears alone, the parentheses may be left out.
|
|
||||||
//
|
|
||||||
// `SingleExpression` does not include `Bare`, because expressions that include `SingleExpression` must decide how
|
|
||||||
// to interpret a single bare word (`foreach { ls }` vs `cd ls`).
|
|
||||||
SingleExpression: Expression = {
|
|
||||||
<Expression>,
|
|
||||||
<Call>,
|
|
||||||
<Binary>,
|
|
||||||
}
|
|
||||||
|
|
||||||
BareExpression: Expression = {
|
|
||||||
<l: @L> <bare: Bare> <r: @R> => ExpressionBuilder::spanned_bare(bare, l, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
SpannedOperator: Spanned<Operator> = {
|
|
||||||
<l: @L> <op: Operator> <r: @R> => Spanned::from_item(op, Span::from((l, r)))
|
|
||||||
}
|
|
||||||
|
|
||||||
Newlines: () = {
|
|
||||||
("newline")+
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionalNewlines: () = {
|
|
||||||
("newline")*
|
|
||||||
}
|
|
||||||
|
|
||||||
// === LOGICAL TOKENS === //
|
|
||||||
|
|
||||||
// A logical token may be composed of more than one raw token, but the tokens must be emitted
|
|
||||||
// from the stream in exactly one sequence. This allows us to use parser infrastructure to
|
|
||||||
// compose tokens without the risk that these logical tokens will introduce ambiguities.
|
|
||||||
|
|
||||||
Bare: Bare = {
|
|
||||||
<head: "bare"> => Bare::from_string(head.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
// A member is a special token that represents bare words or string literals immediate
|
|
||||||
// following a dot.
|
|
||||||
Member: Spanned<String> = {
|
|
||||||
<"member"> => <>.to_spanned_string(),
|
|
||||||
<"dqmember"> => <>.to_spanned_string(),
|
|
||||||
<"sqmember"> => <>.to_spanned_string(),
|
|
||||||
<"function"> => <>.to_spanned_string(),
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandName: Spanned<Bare> = {
|
|
||||||
<l: @L> <name: "command-name"> <r: @R> => Spanned::from_item(Bare::from_string(name.as_slice()), (l, r)),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Operator: Operator = {
|
|
||||||
"==" => Operator::Equal,
|
|
||||||
"!=" => Operator::NotEqual,
|
|
||||||
"<" => Operator::LessThan,
|
|
||||||
">" => Operator::GreaterThan,
|
|
||||||
"<=" => Operator::LessThanOrEqual,
|
|
||||||
">=" => Operator::GreaterThanOrEqual
|
|
||||||
}
|
|
||||||
|
|
||||||
Int: i64 = {
|
|
||||||
<n: "num"> => i64::from_str(<>.as_slice()).unwrap(),
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitsNum: Expression = {
|
|
||||||
<l: @L> <num: Int> <unit: "unit"> <r: @R> => ExpressionBuilder::spanned_unit((num, Unit::from_str(unit.as_slice()).unwrap()), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
String: Expression = {
|
|
||||||
<l: @L> <s: "sqstring"> <r: @R> => ExpressionBuilder::spanned_string(&s.as_slice()[1..(s.as_slice().len() - 1)], l, r),
|
|
||||||
<l: @L> <s: "dqstring"> <r: @R> => ExpressionBuilder::spanned_string(&s.as_slice()[1..(s.as_slice().len() - 1)], l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
Flag: Expression = {
|
|
||||||
<l: @L> "-" <b: Bare> <r: @R> => ExpressionBuilder::spanned_shorthand(b.to_string(), l, r),
|
|
||||||
<l: @L> "--" <b: Bare> <r: @R> => ExpressionBuilder::spanned_flag(b.to_string(), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
Var: Expression = {
|
|
||||||
<l: @L> "$" <v: "variable"> <r: @R> => ExpressionBuilder::spanned_var(v.as_slice(), l, r),
|
|
||||||
}
|
|
||||||
|
|
||||||
SpannedBare: Spanned<Bare> = {
|
|
||||||
<l: @L> <bare: Bare> <r: @R> => Spanned::from_item(bare, (l, r)),
|
|
||||||
}
|
|
||||||
|
|
||||||
// === MACROS === //
|
|
||||||
|
|
||||||
Comma<T>: Vec<T> = { // (1)
|
|
||||||
<v:(<T> OptionalNewlines "," OptionalNewlines)*> <e:T?> => match e { // (2)
|
|
||||||
None => v,
|
|
||||||
Some(e) => {
|
|
||||||
let mut v = v;
|
|
||||||
v.push(e);
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern {
|
|
||||||
type Location = usize;
|
|
||||||
type Error = ShellError;
|
|
||||||
|
|
||||||
enum SpannedToken<'input> {
|
|
||||||
"any" => SpannedToken { token: Token::TyAny, .. },
|
|
||||||
"int" => SpannedToken { token: Token::TyInt, .. },
|
|
||||||
"decimal" => SpannedToken { token: Token::TyDecimal, .. },
|
|
||||||
"bytes" => SpannedToken { token: Token::TyBytes, .. },
|
|
||||||
"text" => SpannedToken { token: Token::TyText, .. },
|
|
||||||
"boolean" => SpannedToken { token: Token::TyBoolean, .. },
|
|
||||||
"date" => SpannedToken { token: Token::TyDate, .. },
|
|
||||||
"object" => SpannedToken { token: Token::TyObject, .. },
|
|
||||||
"list" => SpannedToken { token: Token::TyList, .. },
|
|
||||||
"block" => SpannedToken { token: Token::TyBlock, .. },
|
|
||||||
|
|
||||||
"->" => SpannedToken { token: Token::ReturnArrow, .. },
|
|
||||||
"," => SpannedToken { token: Token::Comma, .. },
|
|
||||||
":" => SpannedToken { token: Token::Colon, .. },
|
|
||||||
"|" => SpannedToken { token: Token::Pipe, .. },
|
|
||||||
"(" => SpannedToken { token: Token::OpenParen, .. },
|
|
||||||
")" => SpannedToken { token: Token::CloseParen, .. },
|
|
||||||
"{" => SpannedToken { token: Token::OpenBrace, .. },
|
|
||||||
"}" => SpannedToken { token: Token::CloseBrace, .. },
|
|
||||||
"==" => SpannedToken { token: Token::OpEq, .. },
|
|
||||||
"!=" => SpannedToken { token: Token::OpNeq, .. },
|
|
||||||
"<" => SpannedToken { token: Token::OpLt, .. },
|
|
||||||
"<=" => SpannedToken { token: Token::OpLte, .. },
|
|
||||||
">" => SpannedToken { token: Token::OpGt, .. },
|
|
||||||
">=" => SpannedToken { token: Token::OpGte, .. },
|
|
||||||
"-" => SpannedToken { token: Token::Dash, .. },
|
|
||||||
"--" => SpannedToken { token: Token::DashDash, .. },
|
|
||||||
"$" => SpannedToken { token: Token::Dollar, .. },
|
|
||||||
"???." => SpannedToken { token: Token::PathDot, .. },
|
|
||||||
"command-name" => SpannedToken { token: Token::CommandName, .. },
|
|
||||||
"start-params" => SpannedToken { token: Token::StartParamList, .. },
|
|
||||||
"end-params" => SpannedToken { token: Token::EndParamList, .. },
|
|
||||||
"num" => SpannedToken { token: Token::Num, .. },
|
|
||||||
"member" => SpannedToken { token: Token::Member, .. },
|
|
||||||
"sqmember" => SpannedToken { token: Token::SQMember, .. },
|
|
||||||
"dqmember" => SpannedToken { token: Token::SQMember, .. },
|
|
||||||
"variable" => SpannedToken { token: Token::Variable, .. },
|
|
||||||
"bare" => SpannedToken { token: Token::Bare, .. },
|
|
||||||
"dqstring" => SpannedToken { token: Token::DQString, .. },
|
|
||||||
"sqstring" => SpannedToken { token: Token::SQString, .. },
|
|
||||||
"unit" => SpannedToken { token: Token::Unit, .. },
|
|
||||||
"newline" => SpannedToken { token: Token::Newline, .. },
|
|
||||||
"function" => SpannedToken { token: Token::KeywordFunction, .. },
|
|
||||||
}
|
|
||||||
}
|
|
17838
src/parser/parser.rs
17838
src/parser/parser.rs
File diff suppressed because it is too large
Load diff
|
@ -1,80 +0,0 @@
|
||||||
#[allow(unused)]
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
use crate::parser::lexer::Span;
|
|
||||||
use derive_new::new;
|
|
||||||
use language_reporting::{FileName, Location, ReportingSpan};
|
|
||||||
|
|
||||||
#[derive(new, Debug, Clone)]
|
|
||||||
pub struct Files {
|
|
||||||
snippet: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl language_reporting::ReportingFiles for Files {
|
|
||||||
type Span = Span;
|
|
||||||
type FileId = usize;
|
|
||||||
|
|
||||||
fn byte_span(
|
|
||||||
&self,
|
|
||||||
_file: Self::FileId,
|
|
||||||
from_index: usize,
|
|
||||||
to_index: usize,
|
|
||||||
) -> Option<Self::Span> {
|
|
||||||
Some(Span::from((from_index, to_index)))
|
|
||||||
}
|
|
||||||
fn file_id(&self, _span: Self::Span) -> Self::FileId {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn file_name(&self, _file: Self::FileId) -> FileName {
|
|
||||||
FileName::Verbatim(format!("<eval>"))
|
|
||||||
}
|
|
||||||
fn byte_index(&self, _file: Self::FileId, _line: usize, _column: usize) -> Option<usize> {
|
|
||||||
unimplemented!("byte_index")
|
|
||||||
}
|
|
||||||
fn location(&self, _file: Self::FileId, byte_index: usize) -> Option<Location> {
|
|
||||||
let source = &self.snippet;
|
|
||||||
let mut seen_lines = 0;
|
|
||||||
let mut seen_bytes = 0;
|
|
||||||
|
|
||||||
for (pos, _) in source.match_indices('\n') {
|
|
||||||
if pos > byte_index {
|
|
||||||
return Some(language_reporting::Location::new(
|
|
||||||
seen_lines,
|
|
||||||
byte_index - seen_bytes,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
seen_lines += 1;
|
|
||||||
seen_bytes = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if seen_lines == 0 {
|
|
||||||
Some(language_reporting::Location::new(0, byte_index))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn line_span(&self, _file: Self::FileId, lineno: usize) -> Option<Self::Span> {
|
|
||||||
let source = &self.snippet;
|
|
||||||
let mut seen_lines = 0;
|
|
||||||
let mut seen_bytes = 0;
|
|
||||||
|
|
||||||
for (pos, _) in source.match_indices('\n') {
|
|
||||||
if seen_lines == lineno {
|
|
||||||
return Some(Span::from((seen_bytes, pos)));
|
|
||||||
} else {
|
|
||||||
seen_lines += 1;
|
|
||||||
seen_bytes = pos + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if seen_lines == 0 {
|
|
||||||
Some(Span::from((0, self.snippet.len() - 1)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn source(&self, span: Self::Span) -> Option<String> {
|
|
||||||
Some(self.snippet[span.start()..span.end()].to_string())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::parser::nom_input;
|
use crate::parser::nom_input;
|
||||||
use crate::parser::parse2::span::Spanned;
|
use crate::parser::parse::span::Spanned;
|
||||||
use crate::parser::parse2::token_tree::TokenNode;
|
use crate::parser::parse::token_tree::TokenNode;
|
||||||
use crate::parser::parse2::tokens::RawToken;
|
use crate::parser::parse::tokens::RawToken;
|
||||||
use crate::parser::{Pipeline, PipelineElement};
|
use crate::parser::{Pipeline, PipelineElement};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::shell::completer::NuCompleter;
|
use crate::shell::completer::NuCompleter;
|
||||||
|
|
Loading…
Reference in a new issue