wip: make assignment consistent
This commit is contained in:
parent
3d1145e759
commit
c16e20592f
|
@ -6,6 +6,7 @@ pub enum TokenContents {
|
||||||
Comment,
|
Comment,
|
||||||
Pipe,
|
Pipe,
|
||||||
PipePipe,
|
PipePipe,
|
||||||
|
AssignmentOperator,
|
||||||
ErrGreaterPipe,
|
ErrGreaterPipe,
|
||||||
OutErrGreaterPipe,
|
OutErrGreaterPipe,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
|
@ -297,6 +298,10 @@ pub fn lex_item(
|
||||||
|
|
||||||
let mut err = None;
|
let mut err = None;
|
||||||
let output = match &input[(span.start - span_offset)..(span.end - span_offset)] {
|
let output = match &input[(span.start - span_offset)..(span.end - span_offset)] {
|
||||||
|
b"=" | b"+=" | b"++=" | b"-=" | b"*=" | b"/=" => Token {
|
||||||
|
contents: TokenContents::AssignmentOperator,
|
||||||
|
span,
|
||||||
|
},
|
||||||
b"out>" | b"o>" => Token {
|
b"out>" | b"o>" => Token {
|
||||||
contents: TokenContents::OutGreaterThan,
|
contents: TokenContents::OutGreaterThan,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -167,10 +167,43 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
let mut last_token = TokenContents::Eol;
|
let mut last_token = TokenContents::Eol;
|
||||||
let mut file_redirection = None;
|
let mut file_redirection = None;
|
||||||
let mut curr_comment: Option<Vec<Span>> = None;
|
let mut curr_comment: Option<Vec<Span>> = None;
|
||||||
|
let mut is_assignment = false;
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
for (idx, token) in tokens.iter().enumerate() {
|
for (idx, token) in tokens.iter().enumerate() {
|
||||||
if let Some((source, append, span)) = file_redirection.take() {
|
if is_assignment {
|
||||||
|
match &token.contents {
|
||||||
|
// Consume until semicolon or terminating EOL. Assignments absorb pipelines and
|
||||||
|
// redirections.
|
||||||
|
TokenContents::Eol => {
|
||||||
|
// Handle `[Command] [Pipe] ([Comment] | [Eol])+ [Command]`
|
||||||
|
//
|
||||||
|
// `[Eol]` branch checks if previous token is `[Pipe]` to construct pipeline
|
||||||
|
// and so `[Comment] | [Eol]` should be ignore to make it work
|
||||||
|
let actual_token = last_non_comment_token(tokens, idx);
|
||||||
|
if actual_token != Some(TokenContents::Pipe) {
|
||||||
|
is_assignment = false;
|
||||||
|
pipeline.push(&mut command);
|
||||||
|
block.push(&mut pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if last_token == TokenContents::Eol {
|
||||||
|
// Clear out the comment as we're entering a new comment
|
||||||
|
curr_comment = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TokenContents::Semicolon => {
|
||||||
|
is_assignment = false;
|
||||||
|
pipeline.push(&mut command);
|
||||||
|
block.push(&mut pipeline);
|
||||||
|
}
|
||||||
|
TokenContents::Comment => {
|
||||||
|
command.comments.push(token.span);
|
||||||
|
curr_comment = None;
|
||||||
|
}
|
||||||
|
_ => command.push(token.span),
|
||||||
|
}
|
||||||
|
} else if let Some((source, append, span)) = file_redirection.take() {
|
||||||
match &token.contents {
|
match &token.contents {
|
||||||
TokenContents::PipePipe => {
|
TokenContents::PipePipe => {
|
||||||
error = error.or(Some(ParseError::ShellOrOr(token.span)));
|
error = error.or(Some(ParseError::ShellOrOr(token.span)));
|
||||||
|
@ -189,6 +222,11 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
command.push(token.span)
|
command.push(token.span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TokenContents::AssignmentOperator => {
|
||||||
|
error = error.or(Some(ParseError::Expected("redirection target", token.span)));
|
||||||
|
command.push(span);
|
||||||
|
command.push(token.span);
|
||||||
|
}
|
||||||
TokenContents::OutGreaterThan
|
TokenContents::OutGreaterThan
|
||||||
| TokenContents::OutGreaterGreaterThan
|
| TokenContents::OutGreaterGreaterThan
|
||||||
| TokenContents::ErrGreaterThan
|
| TokenContents::ErrGreaterThan
|
||||||
|
@ -251,6 +289,15 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
}
|
}
|
||||||
command.push(token.span);
|
command.push(token.span);
|
||||||
}
|
}
|
||||||
|
TokenContents::AssignmentOperator => {
|
||||||
|
// When in assignment mode, we'll just consume pipes or redirections as part of
|
||||||
|
// the command.
|
||||||
|
is_assignment = true;
|
||||||
|
if let Some(curr_comment) = curr_comment.take() {
|
||||||
|
command.comments = curr_comment;
|
||||||
|
}
|
||||||
|
command.push(token.span);
|
||||||
|
}
|
||||||
TokenContents::OutGreaterThan => {
|
TokenContents::OutGreaterThan => {
|
||||||
error = error.or(command.check_accepts_redirection(token.span));
|
error = error.or(command.check_accepts_redirection(token.span));
|
||||||
file_redirection = Some((RedirectionSource::Stdout, false, token.span));
|
file_redirection = Some((RedirectionSource::Stdout, false, token.span));
|
||||||
|
|
|
@ -1430,7 +1430,8 @@ fn parse_binary_with_base(
|
||||||
| TokenContents::ErrGreaterThan
|
| TokenContents::ErrGreaterThan
|
||||||
| TokenContents::ErrGreaterGreaterThan
|
| TokenContents::ErrGreaterGreaterThan
|
||||||
| TokenContents::OutErrGreaterThan
|
| TokenContents::OutErrGreaterThan
|
||||||
| TokenContents::OutErrGreaterGreaterThan => {
|
| TokenContents::OutErrGreaterGreaterThan
|
||||||
|
| TokenContents::AssignmentOperator => {
|
||||||
working_set.error(ParseError::Expected("binary", span));
|
working_set.error(ParseError::Expected("binary", span));
|
||||||
return garbage(working_set, span);
|
return garbage(working_set, span);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user