Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contributing/grammar.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ flag_long → "--" flag_name;
short_flag → "-" SHORT_FLAGS ;
spread → "..." expression ;

command_name → string | call_name | IDENTIFIER ;
command_name → string | IDENTIFIER_ALLOW_DASH ;
flag_name → IDENTIFIER_ALLOW_DASH ;
call_name
→ IDENTIFIER_ALLOW_DASH IDENTIFIER_ALLOW_DASH+ ;
Expand Down
71 changes: 66 additions & 5 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,23 @@ pub enum AstNode {
long: NodeId,
short: Option<NodeId>,
ty: Option<NodeId>,
// it can only exists if `ty` is not None
custom_completion: Option<NodeId>,
default: Option<NodeId>,
},
PosParam {
name: NodeId,
ty: Option<NodeId>,
// it can only exists if `ty` is not None
custom_completion: Option<NodeId>,
default: Option<NodeId>,
is_optional: bool,
},
RestParam {
name: NodeId,
ty: Option<NodeId>,
// it can only exists if `ty` is not None
custom_completion: Option<NodeId>,
},
InOutTypes(InOutTypesId),
/// Input/output type pair for a command
Expand Down Expand Up @@ -1000,6 +1011,13 @@ impl Parser {
)
}

pub fn command_name(&mut self) -> NodeId {
match self.tokens.peek_token() {
Token::DoubleQuotedString | Token::SingleQuotedString => self.string(),
_ => self.identifier_allow_dash(),
}
}

pub fn string(&mut self) -> NodeId {
match self.tokens.peek() {
(Token::DoubleQuotedString, span) => self.advance_node(AstNode::String, span),
Expand Down Expand Up @@ -1218,8 +1236,16 @@ impl Parser {
}

let is_flag_param = self.is_dashdash();
let is_rest_param = self.is_dotdotdot();
let mut is_pos_param_optional = false;

let (name, short_name) =
if is_flag_param && matches!(params_context, ParamsContext::Squares) {
if is_rest_param && matches!(params_context, ParamsContext::Squares) {
// reset parameter
self.tokens.advance();
(self.name(), None)
} else if is_flag_param && matches!(params_context, ParamsContext::Squares) {
// flag_parameter.
let result = self.flag_long();
if self.is_lparen() {
self.tokens.advance();
Expand All @@ -1230,16 +1256,30 @@ impl Parser {
(result, None)
}
} else {
(self.name(), None)
// positional parameter
let result = (self.name(), None);
if self.is_question_mark() {
self.tokens.advance();
is_pos_param_optional = true;
}
result
};

let ty = if self.is_colon() {
let (ty, custom_completion) = if self.is_colon() {
// We have a type
self.colon();

Some(self.typename())
let type_name = self.typename();
// We have custom completer
let custom_completion = if self.is_at() {
self.tokens.advance();
Some(self.command_name())
} else {
None
};
(Some(type_name), custom_completion)
} else {
None
(None, None)
};

let default_val = if self.is_equals() {
Expand All @@ -1262,17 +1302,30 @@ impl Parser {
long: name,
short: short_name,
ty,
custom_completion,
default: default_val,
},
name_span.start,
param_span_end,
)
} else if is_rest_param {
self.create_node(
AstNode::RestParam {
name,
ty,
custom_completion,
},
name_span.start,
param_span_end,
)
} else {
self.create_node(
AstNode::PosParam {
name,
ty,
custom_completion,
default: default_val,
is_optional: is_pos_param_optional,
},
name_span.start,
param_span_end,
Expand Down Expand Up @@ -1868,6 +1921,10 @@ impl Parser {
self.tokens.peek_token() == Token::Equals
}

pub fn is_at(&mut self) -> bool {
self.tokens.peek_token() == Token::At
}

pub fn is_comma(&mut self) -> bool {
self.tokens.peek_token() == Token::Comma
}
Expand Down Expand Up @@ -1956,6 +2013,10 @@ impl Parser {
self.tokens.peek_token() == Token::DotDot
}

pub fn is_dotdotdot(&mut self) -> bool {
self.tokens.peek_token() == Token::DotDotDot
}

pub fn is_coloncolon(&mut self) -> bool {
self.tokens.peek_token() == Token::ColonColon
}
Expand Down
6 changes: 5 additions & 1 deletion src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,18 @@ impl<'a> Resolver<'a> {
AstNode::PosParam {
name,
ty,
custom_completion: _,
default: _,
is_optional: _,
}
| AstNode::FlagParam {
long: name,
short: _,
ty,
custom_completion: _,
default: _,
} => {
}
| AstNode::RestParam { name, ty, .. } => {
self.define_variable(name, false);
if let Some(ty) = ty {
self.resolve_node(ty);
Expand Down
6 changes: 3 additions & 3 deletions src/snapshots/new_nu_parser__test__node_output@calls.nu.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ input_file: tests/calls.nu
9: Name (38 to 39) "a"
10: Name (41 to 47) "string"
11: Type { name: NodeId(10), args: None, optional: false } (41 to 47)
12: PosParam { name: NodeId(9), ty: Some(NodeId(11)), default: None } (38 to 47)
12: PosParam { name: NodeId(9), ty: Some(NodeId(11)), custom_completion: None, default: None, is_optional: false } (38 to 47)
13: Name (49 to 50) "b"
14: Name (52 to 58) "string"
15: Type { name: NodeId(14), args: None, optional: false } (52 to 58)
16: PosParam { name: NodeId(13), ty: Some(NodeId(15)), default: None } (49 to 58)
16: PosParam { name: NodeId(13), ty: Some(NodeId(15)), custom_completion: None, default: None, is_optional: false } (49 to 58)
17: Name (60 to 61) "c"
18: Name (63 to 66) "int"
19: Type { name: NodeId(18), args: None, optional: false } (63 to 66)
20: PosParam { name: NodeId(17), ty: Some(NodeId(19)), default: None } (60 to 66)
20: PosParam { name: NodeId(17), ty: Some(NodeId(19)), custom_completion: None, default: None, is_optional: false } (60 to 66)
21: Params(ParamsId(0)) (37 to 67)
22: Variable (72 to 74) "$a"
23: Variable (76 to 78) "$b"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ input_file: tests/calls_invalid.nu
1: Name (10 to 11) "a"
2: Name (13 to 16) "int"
3: Type { name: NodeId(2), args: None, optional: false } (13 to 16)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), default: None } (10 to 16)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), custom_completion: None, default: None, is_optional: false } (10 to 16)
5: Params(ParamsId(0)) (8 to 18)
6: Block(BlockId(0)) (19 to 21)
7: Def { name: NodeId(0), type_params: None, params: NodeId(5), in_out_types: None, block: NodeId(6), env: false, wrapped: false } (0 to 21)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ input_file: tests/closure.nu
---
==== COMPILER ====
0: Name (3 to 4) "a"
1: PosParam { name: NodeId(0), ty: None, default: None } (3 to 4)
1: PosParam { name: NodeId(0), ty: None, custom_completion: None, default: None, is_optional: false } (3 to 4)
2: Name (6 to 7) "b"
3: PosParam { name: NodeId(2), ty: None, default: None } (6 to 7)
3: PosParam { name: NodeId(2), ty: None, custom_completion: None, default: None, is_optional: false } (6 to 7)
4: Params(ParamsId(0)) (2 to 8)
5: Variable (9 to 11) "$a"
6: Plus (12 to 13)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ input_file: tests/closure3.nu
1: Name (16 to 17) "a"
2: Name (19 to 22) "int"
3: Type { name: NodeId(2), args: None, optional: false } (19 to 22)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), default: None } (16 to 22)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), custom_completion: None, default: None, is_optional: false } (16 to 22)
5: Name (24 to 25) "b"
6: Name (27 to 30) "int"
7: Type { name: NodeId(6), args: None, optional: false } (27 to 30)
8: PosParam { name: NodeId(5), ty: Some(NodeId(7)), default: None } (24 to 30)
8: PosParam { name: NodeId(5), ty: Some(NodeId(7)), custom_completion: None, default: None, is_optional: false } (24 to 30)
9: Params(ParamsId(0)) (15 to 31)
10: Variable (32 to 34) "$a"
11: Plus (35 to 36)
Expand Down
88 changes: 75 additions & 13 deletions src/snapshots/new_nu_parser__test__node_output@def.nu.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ input_file: tests/def.nu
==== COMPILER ====
0: Name (4 to 7) "foo"
1: Name (9 to 10) "w"
2: PosParam { name: NodeId(1), ty: None, default: None } (9 to 10)
2: PosParam { name: NodeId(1), ty: None, custom_completion: None, default: None, is_optional: false } (9 to 10)
3: Name (11 to 12) "x"
4: Name (14 to 17) "int"
5: Type { name: NodeId(4), args: None, optional: false } (14 to 17)
6: PosParam { name: NodeId(3), ty: Some(NodeId(5)), default: None } (11 to 17)
6: PosParam { name: NodeId(3), ty: Some(NodeId(5)), custom_completion: None, default: None, is_optional: false } (11 to 17)
7: Name (19 to 20) "y"
8: Name (22 to 26) "list"
9: Name (27 to 31) "list"
Expand All @@ -20,18 +20,18 @@ input_file: tests/def.nu
13: Type { name: NodeId(9), args: Some(NodeId(12)), optional: false } (27 to 31)
14: TypeArgs(TypeArgsId(1)) (26 to 37)
15: Type { name: NodeId(8), args: Some(NodeId(14)), optional: false } (22 to 26)
16: PosParam { name: NodeId(7), ty: Some(NodeId(15)), default: None } (19 to 26)
16: PosParam { name: NodeId(7), ty: Some(NodeId(15)), custom_completion: None, default: None, is_optional: false } (19 to 26)
17: Name (39 to 40) "z"
18: Name (42 to 48) "record"
19: Name (49 to 50) "a"
20: PosParam { name: NodeId(19), ty: None, default: None } (49 to 50)
20: PosParam { name: NodeId(19), ty: None, custom_completion: None, default: None, is_optional: false } (49 to 50)
21: Name (52 to 53) "b"
22: Name (55 to 58) "int"
23: Type { name: NodeId(22), args: None, optional: false } (55 to 58)
24: PosParam { name: NodeId(21), ty: Some(NodeId(23)), default: None } (52 to 58)
24: PosParam { name: NodeId(21), ty: Some(NodeId(23)), custom_completion: None, default: None, is_optional: false } (52 to 58)
25: Params(ParamsId(0)) (48 to 59)
26: RecordType { fields: NodeId(25), optional: false } (42 to 60)
27: PosParam { name: NodeId(17), ty: Some(NodeId(26)), default: None } (39 to 60)
27: PosParam { name: NodeId(17), ty: Some(NodeId(26)), custom_completion: None, default: None, is_optional: false } (39 to 60)
28: Params(ParamsId(1)) (8 to 61)
29: Variable (66 to 68) "$w"
30: Variable (69 to 71) "$x"
Expand All @@ -46,18 +46,18 @@ input_file: tests/def.nu
39: Name (125 to 128) "int"
40: Type { name: NodeId(39), args: None, optional: false } (125 to 128)
41: Int (131 to 132) "3"
42: FlagParam { long: NodeId(38), short: None, ty: Some(NodeId(40)), default: Some(NodeId(41)) } (118 to 132)
42: FlagParam { long: NodeId(38), short: None, ty: Some(NodeId(40)), custom_completion: None, default: Some(NodeId(41)) } (118 to 132)
43: Name (136 to 139) "baz"
44: FlagLong(NodeId(43)) (134 to 139)
45: Name (141 to 142) "b"
46: FlagShort(NodeId(45)) (140 to 142)
47: FlagParam { long: NodeId(44), short: Some(NodeId(46)), ty: None, default: None } (134 to 139)
47: FlagParam { long: NodeId(44), short: Some(NodeId(46)), ty: None, custom_completion: None, default: None } (134 to 139)
48: Name (145 to 146) "x"
49: PosParam { name: NodeId(48), ty: None, default: None } (145 to 146)
49: PosParam { name: NodeId(48), ty: None, custom_completion: None, default: None, is_optional: false } (145 to 146)
50: Name (148 to 149) "y"
51: Name (151 to 154) "int"
52: Type { name: NodeId(51), args: None, optional: false } (151 to 154)
53: PosParam { name: NodeId(50), ty: Some(NodeId(52)), default: None } (148 to 154)
53: PosParam { name: NodeId(50), ty: Some(NodeId(52)), custom_completion: None, default: None, is_optional: false } (148 to 154)
54: Params(ParamsId(2)) (117 to 155)
55: Variable (159 to 163) "$bar"
56: Variable (165 to 169) "$baz"
Expand All @@ -66,14 +66,76 @@ input_file: tests/def.nu
59: List(ListId(1)) (158 to 177)
60: Block(BlockId(1)) (156 to 180)
61: Def { name: NodeId(36), type_params: None, params: NodeId(54), in_out_types: None, block: NodeId(60), env: false, wrapped: false } (99 to 180)
62: Block(BlockId(2)) (0 to 181)
62: Name (213 to 223) "completion"
63: Params(ParamsId(3)) (224 to 226)
64: Int (230 to 231) "1"
65: Int (233 to 234) "2"
66: Int (236 to 237) "3"
67: List(ListId(2)) (229 to 237)
68: Block(BlockId(2)) (227 to 240)
69: Def { name: NodeId(62), type_params: None, params: NodeId(63), in_out_types: None, block: NodeId(68), env: false, wrapped: false } (209 to 240)
70: Name (245 to 264) "foo-with-completion"
71: Name (268 to 271) "bar"
72: FlagLong(NodeId(71)) (266 to 271)
73: Name (273 to 276) "int"
74: Type { name: NodeId(73), args: None, optional: false } (273 to 276)
75: Name (277 to 287) "completion"
76: FlagParam { long: NodeId(72), short: None, ty: Some(NodeId(74)), custom_completion: Some(NodeId(75)), default: None } (266 to 276)
77: Name (289 to 292) "baz"
78: Name (294 to 297) "int"
79: Type { name: NodeId(78), args: None, optional: false } (294 to 297)
80: Name (298 to 308) "completion"
81: PosParam { name: NodeId(77), ty: Some(NodeId(79)), custom_completion: Some(NodeId(80)), default: None, is_optional: false } (289 to 297)
82: Params(ParamsId(4)) (265 to 309)
83: Variable (313 to 317) "$bar"
84: Variable (319 to 323) "$baz"
85: List(ListId(3)) (312 to 323)
86: Block(BlockId(3)) (310 to 326)
87: Def { name: NodeId(70), type_params: None, params: NodeId(82), in_out_types: None, block: NodeId(86), env: false, wrapped: false } (241 to 326)
88: Name (332 to 344) "foo-optional"
89: Name (346 to 347) "x"
90: Name (349 to 352) "int"
91: Type { name: NodeId(90), args: None, optional: false } (349 to 352)
92: PosParam { name: NodeId(89), ty: Some(NodeId(91)), custom_completion: None, default: None, is_optional: false } (346 to 352)
93: Name (354 to 355) "y"
94: Name (358 to 361) "int"
95: Type { name: NodeId(94), args: None, optional: false } (358 to 361)
96: PosParam { name: NodeId(93), ty: Some(NodeId(95)), custom_completion: None, default: None, is_optional: true } (354 to 361)
97: Params(ParamsId(5)) (345 to 362)
98: Variable (366 to 368) "$x"
99: Variable (370 to 372) "$y"
100: List(ListId(4)) (365 to 372)
101: Block(BlockId(4)) (363 to 375)
102: Def { name: NodeId(88), type_params: None, params: NodeId(97), in_out_types: None, block: NodeId(101), env: false, wrapped: false } (328 to 375)
103: Name (380 to 388) "foo-rest"
104: Name (390 to 391) "x"
105: Name (393 to 396) "int"
106: Type { name: NodeId(105), args: None, optional: false } (393 to 396)
107: PosParam { name: NodeId(104), ty: Some(NodeId(106)), custom_completion: None, default: None, is_optional: false } (390 to 396)
108: Name (401 to 402) "y"
109: RestParam { name: NodeId(108), ty: None, custom_completion: None } (401 to 402)
110: Params(ParamsId(6)) (389 to 403)
111: Variable (407 to 409) "$x"
112: Variable (411 to 413) "$y"
113: List(ListId(5)) (406 to 413)
114: Block(BlockId(5)) (404 to 416)
115: Def { name: NodeId(103), type_params: None, params: NodeId(110), in_out_types: None, block: NodeId(114), env: false, wrapped: false } (376 to 416)
116: Block(BlockId(6)) (0 to 417)
==== SCOPE ====
0: Frame Scope, node_id: NodeId(62)
decls: [ foo-with-flag: NodeId(36), foo: NodeId(0) ]
0: Frame Scope, node_id: NodeId(116)
decls: [ completion: NodeId(62), foo-optional: NodeId(88), foo-rest: NodeId(103), foo-with-completion: NodeId(70), foo-with-flag: NodeId(36), foo: NodeId(0) ]
1: Frame Scope, node_id: NodeId(34)
variables: [ w: NodeId(1), x: NodeId(3), y: NodeId(7), z: NodeId(17) ]
2: Frame Scope, node_id: NodeId(60)
variables: [ --bar: NodeId(38), --baz: NodeId(44), x: NodeId(48), y: NodeId(50) ]
3: Frame Scope, node_id: NodeId(68) (empty)
4: Frame Scope, node_id: NodeId(86)
variables: [ --bar: NodeId(72), baz: NodeId(77) ]
5: Frame Scope, node_id: NodeId(101)
variables: [ x: NodeId(89), y: NodeId(93) ]
6: Frame Scope, node_id: NodeId(114)
variables: [ x: NodeId(104), y: NodeId(108) ]
==== SCOPE ERRORS ====
Error (NodeId 55): variable `bar` not found
Error (NodeId 56): variable `baz` not found
Error (NodeId 83): variable `bar` not found
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ input_file: tests/extern.nu
1: Name (13 to 17) "text"
2: Name (19 to 25) "string"
3: Type { name: NodeId(2), args: None, optional: false } (19 to 25)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), default: None } (13 to 25)
4: PosParam { name: NodeId(1), ty: Some(NodeId(3)), custom_completion: None, default: None, is_optional: false } (13 to 25)
5: Params(ParamsId(0)) (12 to 26)
6: Extern { name: NodeId(0), params: NodeId(5) } (0 to 26)
7: Block(BlockId(0)) (0 to 27)
Expand Down
Loading
Loading