mirror of
https://github.com/nushell/nushell
synced 2025-01-15 14:44:14 +00:00
Add table parsing
This commit is contained in:
parent
04a6a4f860
commit
bf1a23afcf
2 changed files with 73 additions and 10 deletions
12
src/lex.rs
12
src/lex.rs
|
@ -43,6 +43,7 @@ pub enum LexMode {
|
||||||
Normal,
|
Normal,
|
||||||
CommaIsSpace,
|
CommaIsSpace,
|
||||||
NewlineIsSpace,
|
NewlineIsSpace,
|
||||||
|
CommaAndNewlineIsSpace,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A baseline token is terminated if it's not nested inside of a paired
|
// A baseline token is terminated if it's not nested inside of a paired
|
||||||
|
@ -56,7 +57,8 @@ fn is_item_terminator(block_level: &[BlockKind], c: u8, lex_mode: LexMode) -> bo
|
||||||
|| c == b'|'
|
|| c == b'|'
|
||||||
|| c == b';'
|
|| c == b';'
|
||||||
|| c == b'#'
|
|| c == b'#'
|
||||||
|| (c == b',' && lex_mode == LexMode::CommaIsSpace))
|
|| (c == b',' && lex_mode == LexMode::CommaIsSpace)
|
||||||
|
|| (c == b',' && lex_mode == LexMode::CommaAndNewlineIsSpace))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lex_item(
|
pub fn lex_item(
|
||||||
|
@ -237,7 +239,7 @@ pub fn lex(
|
||||||
|
|
||||||
let idx = curr_offset;
|
let idx = curr_offset;
|
||||||
curr_offset += 1;
|
curr_offset += 1;
|
||||||
if lex_mode != LexMode::NewlineIsSpace {
|
if lex_mode != LexMode::NewlineIsSpace && lex_mode != LexMode::CommaAndNewlineIsSpace {
|
||||||
output.push(Token::new(TokenContents::Eol, Span::new(idx, idx + 1)));
|
output.push(Token::new(TokenContents::Eol, Span::new(idx, idx + 1)));
|
||||||
}
|
}
|
||||||
} else if c == b'#' {
|
} else if c == b'#' {
|
||||||
|
@ -263,7 +265,11 @@ pub fn lex(
|
||||||
Span::new(start, curr_offset),
|
Span::new(start, curr_offset),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if c == b' ' || c == b'\t' || (c == b',' && lex_mode == LexMode::CommaIsSpace) {
|
} else if c == b' '
|
||||||
|
|| c == b'\t'
|
||||||
|
|| (c == b',' && lex_mode == LexMode::CommaIsSpace)
|
||||||
|
|| (c == b',' && lex_mode == LexMode::CommaAndNewlineIsSpace)
|
||||||
|
{
|
||||||
// If the next character is non-newline whitespace, skip it.
|
// If the next character is non-newline whitespace, skip it.
|
||||||
curr_offset += 1;
|
curr_offset += 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -104,6 +104,8 @@ pub enum Expr {
|
||||||
Subexpression(Box<Block>),
|
Subexpression(Box<Block>),
|
||||||
Block(Box<Block>),
|
Block(Box<Block>),
|
||||||
List(Vec<Expression>),
|
List(Vec<Expression>),
|
||||||
|
Table(Vec<Expression>, Vec<Vec<Expression>>),
|
||||||
|
String(String), // FIXME: improve this in the future?
|
||||||
Garbage,
|
Garbage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,6 +565,25 @@ impl ParserWorkingSet {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_string(&mut self, span: Span) -> (Expression, Option<ParseError>) {
|
||||||
|
let bytes = self.get_span_contents(span);
|
||||||
|
|
||||||
|
if let Ok(token) = String::from_utf8(bytes.into()) {
|
||||||
|
(
|
||||||
|
Expression {
|
||||||
|
expr: Expr::String(token),
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Mismatch("string".into(), span)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_table_expression(&mut self, span: Span) -> (Expression, Option<ParseError>) {
|
pub fn parse_table_expression(&mut self, span: Span) -> (Expression, Option<ParseError>) {
|
||||||
let bytes = self.get_span_contents(span);
|
let bytes = self.get_span_contents(span);
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
@ -591,14 +612,12 @@ impl ParserWorkingSet {
|
||||||
|
|
||||||
let source = &self.file_contents[..end];
|
let source = &self.file_contents[..end];
|
||||||
|
|
||||||
let (output, err) = lex(&source, start, crate::LexMode::CommaIsSpace);
|
let (output, err) = lex(&source, start, crate::LexMode::CommaAndNewlineIsSpace);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
println!("{:?}", output.block);
|
|
||||||
|
|
||||||
match output.block.len() {
|
match output.block.len() {
|
||||||
0 => (
|
0 => (
|
||||||
Expression {
|
Expression {
|
||||||
|
@ -628,10 +647,42 @@ impl ParserWorkingSet {
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => (
|
_ => {
|
||||||
garbage(span),
|
let mut table_headers = vec![];
|
||||||
Some(ParseError::Mismatch("table".into(), span)),
|
|
||||||
),
|
let (headers, err) =
|
||||||
|
self.parse_arg(output.block[0].commands[0].parts[0], SyntaxShape::Table);
|
||||||
|
error = error.or(err);
|
||||||
|
|
||||||
|
if let Expression {
|
||||||
|
expr: Expr::List(headers),
|
||||||
|
..
|
||||||
|
} = headers
|
||||||
|
{
|
||||||
|
table_headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rows = vec![];
|
||||||
|
for part in &output.block[1].commands[0].parts {
|
||||||
|
let (values, err) = self.parse_arg(*part, SyntaxShape::Table);
|
||||||
|
error = error.or(err);
|
||||||
|
if let Expression {
|
||||||
|
expr: Expr::List(values),
|
||||||
|
..
|
||||||
|
} = values
|
||||||
|
{
|
||||||
|
rows.push(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Table(table_headers, rows),
|
||||||
|
span,
|
||||||
|
},
|
||||||
|
error,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,6 +695,11 @@ impl ParserWorkingSet {
|
||||||
|
|
||||||
if bytes.starts_with(b"{") {
|
if bytes.starts_with(b"{") {
|
||||||
start += 1;
|
start += 1;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Mismatch("block".into(), span)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if bytes.ends_with(b"}") {
|
if bytes.ends_with(b"}") {
|
||||||
end -= 1;
|
end -= 1;
|
||||||
|
@ -734,6 +790,7 @@ impl ParserWorkingSet {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SyntaxShape::String => self.parse_string(span),
|
||||||
SyntaxShape::Block => self.parse_block_expression(span),
|
SyntaxShape::Block => self.parse_block_expression(span),
|
||||||
SyntaxShape::Any => {
|
SyntaxShape::Any => {
|
||||||
let shapes = vec![
|
let shapes = vec![
|
||||||
|
|
Loading…
Reference in a new issue