mirror of
https://github.com/nushell/nushell.git
synced 2024-11-29 20:03:54 +01:00
fix parser merge. start highlighter
This commit is contained in:
parent
6b0b8744c1
commit
3a8206d1fb
@ -7,6 +7,7 @@ mod parser;
|
|||||||
mod parser_state;
|
mod parser_state;
|
||||||
mod signature;
|
mod signature;
|
||||||
mod span;
|
mod span;
|
||||||
|
mod syntax_highlight;
|
||||||
|
|
||||||
pub use declaration::Declaration;
|
pub use declaration::Declaration;
|
||||||
pub use eval::Engine;
|
pub use eval::Engine;
|
||||||
|
13
src/main.rs
13
src/main.rs
@ -1,8 +1,11 @@
|
|||||||
use engine_q::{ParserWorkingSet, Signature, SyntaxShape};
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use engine_q::{ParserState, ParserWorkingSet, Signature, SyntaxShape};
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
if let Some(path) = std::env::args().nth(1) {
|
if let Some(path) = std::env::args().nth(1) {
|
||||||
let mut working_set = ParserWorkingSet::new(None);
|
let mut parser_state = Arc::new(ParserState::new());
|
||||||
|
let mut working_set = ParserWorkingSet::new(Some(parser_state.clone()));
|
||||||
|
|
||||||
// let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
// let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
// working_set.add_decl(sig.into());
|
// working_set.add_decl(sig.into());
|
||||||
@ -60,9 +63,13 @@ fn main() -> std::io::Result<()> {
|
|||||||
.required("block", SyntaxShape::Block, "body of the definition");
|
.required("block", SyntaxShape::Block, "body of the definition");
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
|
ParserState::merge_working_set(&mut parser_state, working_set);
|
||||||
|
|
||||||
// let file = std::fs::read(&path)?;
|
// let file = std::fs::read(&path)?;
|
||||||
// let (output, err) = working_set.parse_file(&path, file);
|
// let (output, err) = working_set.parse_file(&path, file);
|
||||||
let (output, err) = working_set.parse_source(path.as_bytes());
|
|
||||||
|
let mut working_set = ParserWorkingSet::new(Some(parser_state.clone()));
|
||||||
|
let (output, err) = working_set.parse_source(path.as_bytes(), false);
|
||||||
println!("{:#?}", output);
|
println!("{:#?}", output);
|
||||||
println!("error: {:?}", err);
|
println!("error: {:?}", err);
|
||||||
|
|
||||||
|
@ -272,7 +272,6 @@ pub struct VarDecl {
|
|||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Pipeline(Pipeline),
|
Pipeline(Pipeline),
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -812,7 +811,7 @@ impl ParserWorkingSet {
|
|||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (output, err) = self.parse_block(&output);
|
let (output, err) = self.parse_block(&output, true);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let block_id = self.add_block(output);
|
let block_id = self.add_block(output);
|
||||||
@ -1339,7 +1338,7 @@ impl ParserWorkingSet {
|
|||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (output, err) = self.parse_block(&output);
|
let (output, err) = self.parse_block(&output, true);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
println!("{:?} {:?}", output, error);
|
println!("{:?} {:?}", output, error);
|
||||||
@ -1765,9 +1764,15 @@ impl ParserWorkingSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_block(&mut self, lite_block: &LiteBlock) -> (Block, Option<ParseError>) {
|
pub fn parse_block(
|
||||||
|
&mut self,
|
||||||
|
lite_block: &LiteBlock,
|
||||||
|
scoped: bool,
|
||||||
|
) -> (Block, Option<ParseError>) {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
if scoped {
|
||||||
self.enter_scope();
|
self.enter_scope();
|
||||||
|
}
|
||||||
|
|
||||||
let mut block = Block::new();
|
let mut block = Block::new();
|
||||||
|
|
||||||
@ -1791,12 +1796,19 @@ impl ParserWorkingSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if scoped {
|
||||||
self.exit_scope();
|
self.exit_scope();
|
||||||
|
}
|
||||||
|
|
||||||
(block, error)
|
(block, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_file(&mut self, fname: &str, contents: Vec<u8>) -> (Block, Option<ParseError>) {
|
pub fn parse_file(
|
||||||
|
&mut self,
|
||||||
|
fname: &str,
|
||||||
|
contents: Vec<u8>,
|
||||||
|
scoped: bool,
|
||||||
|
) -> (Block, Option<ParseError>) {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
let (output, err) = lex(&contents, 0, &[], &[]);
|
let (output, err) = lex(&contents, 0, &[], &[]);
|
||||||
@ -1807,13 +1819,13 @@ impl ParserWorkingSet {
|
|||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (output, err) = self.parse_block(&output);
|
let (output, err) = self.parse_block(&output, scoped);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
(output, error)
|
(output, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_source(&mut self, source: &[u8]) -> (Block, Option<ParseError>) {
|
pub fn parse_source(&mut self, source: &[u8], scoped: bool) -> (Block, Option<ParseError>) {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
self.add_file("source".into(), source.into());
|
self.add_file("source".into(), source.into());
|
||||||
@ -1824,7 +1836,7 @@ impl ParserWorkingSet {
|
|||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (output, err) = self.parse_block(&output);
|
let (output, err) = self.parse_block(&output, scoped);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
(output, error)
|
(output, error)
|
||||||
@ -1841,7 +1853,7 @@ mod tests {
|
|||||||
pub fn parse_int() {
|
pub fn parse_int() {
|
||||||
let mut working_set = ParserWorkingSet::new(None);
|
let mut working_set = ParserWorkingSet::new(None);
|
||||||
|
|
||||||
let (block, err) = working_set.parse_source(b"3");
|
let (block, err) = working_set.parse_source(b"3", true);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
@ -1861,7 +1873,7 @@ mod tests {
|
|||||||
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
let (block, err) = working_set.parse_source(b"foo");
|
let (block, err) = working_set.parse_source(b"foo", true);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
@ -1884,7 +1896,7 @@ mod tests {
|
|||||||
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
let (_, err) = working_set.parse_source(b"foo --jazz");
|
let (_, err) = working_set.parse_source(b"foo --jazz", true);
|
||||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1895,7 +1907,7 @@ mod tests {
|
|||||||
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
|
|
||||||
let (_, err) = working_set.parse_source(b"foo -j");
|
let (_, err) = working_set.parse_source(b"foo -j", true);
|
||||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1907,7 +1919,7 @@ mod tests {
|
|||||||
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
||||||
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
|
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
let (_, err) = working_set.parse_source(b"foo -mj");
|
let (_, err) = working_set.parse_source(b"foo -mj", true);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
err,
|
err,
|
||||||
Some(ParseError::ShortFlagBatchCantTakeArg(..))
|
Some(ParseError::ShortFlagBatchCantTakeArg(..))
|
||||||
@ -1920,7 +1932,7 @@ mod tests {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
let (_, err) = working_set.parse_source(b"foo -mj");
|
let (_, err) = working_set.parse_source(b"foo -mj", true);
|
||||||
assert!(matches!(err, Some(ParseError::UnknownFlag(..))));
|
assert!(matches!(err, Some(ParseError::UnknownFlag(..))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1930,7 +1942,7 @@ mod tests {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
let (_, err) = working_set.parse_source(b"foo -j 100");
|
let (_, err) = working_set.parse_source(b"foo -j 100", true);
|
||||||
assert!(matches!(err, Some(ParseError::ExtraPositional(..))));
|
assert!(matches!(err, Some(ParseError::ExtraPositional(..))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1940,7 +1952,7 @@ mod tests {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
|
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
let (_, err) = working_set.parse_source(b"foo");
|
let (_, err) = working_set.parse_source(b"foo", true);
|
||||||
assert!(matches!(err, Some(ParseError::MissingPositional(..))));
|
assert!(matches!(err, Some(ParseError::MissingPositional(..))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1951,7 +1963,7 @@ mod tests {
|
|||||||
let sig =
|
let sig =
|
||||||
Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
|
Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
|
||||||
working_set.add_decl(sig.into());
|
working_set.add_decl(sig.into());
|
||||||
let (_, err) = working_set.parse_source(b"foo");
|
let (_, err) = working_set.parse_source(b"foo", true);
|
||||||
assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..))));
|
assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ pub struct ParserState {
|
|||||||
vars: Vec<Type>,
|
vars: Vec<Type>,
|
||||||
decls: Vec<Declaration>,
|
decls: Vec<Declaration>,
|
||||||
blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
|
scope: Vec<ScopeFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
@ -49,6 +50,7 @@ impl ParserState {
|
|||||||
vars: vec![],
|
vars: vec![],
|
||||||
decls: vec![],
|
decls: vec![],
|
||||||
blocks: vec![],
|
blocks: vec![],
|
||||||
|
scope: vec![ScopeFrame::new()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +66,15 @@ impl ParserState {
|
|||||||
this.vars.extend(working_set.vars);
|
this.vars.extend(working_set.vars);
|
||||||
this.blocks.extend(working_set.blocks);
|
this.blocks.extend(working_set.blocks);
|
||||||
|
|
||||||
//FIXME: add scope frame merging
|
if let Some(last) = this.scope.last_mut() {
|
||||||
|
let first = working_set.scope.remove(0);
|
||||||
|
for item in first.decls.into_iter() {
|
||||||
|
last.decls.insert(item.0, item.1);
|
||||||
|
}
|
||||||
|
for item in first.vars.into_iter() {
|
||||||
|
last.vars.insert(item.0, item.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("Internal error: merging working set should always succeed");
|
panic!("Internal error: merging working set should always succeed");
|
||||||
}
|
}
|
||||||
@ -235,6 +245,14 @@ impl ParserWorkingSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(permanent_state) = &self.permanent_state {
|
||||||
|
for scope in permanent_state.scope.iter().rev() {
|
||||||
|
if let Some(decl_id) = scope.decls.get(name) {
|
||||||
|
return Some(*decl_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +272,14 @@ impl ParserWorkingSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(permanent_state) = &self.permanent_state {
|
||||||
|
for scope in permanent_state.scope.iter().rev() {
|
||||||
|
if let Some(var_id) = scope.vars.get(name) {
|
||||||
|
return Some(*var_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/syntax_highlight.rs
Normal file
24
src/syntax_highlight.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::{Block, Expr, Expression, ParserState, ParserWorkingSet, Statement};
|
||||||
|
|
||||||
|
fn syntax_highlight(parser_state: Arc<ParserState>, input: &[u8]) {
|
||||||
|
let mut working_set = ParserWorkingSet::new(Some(parser_state));
|
||||||
|
|
||||||
|
let (block, _) = working_set.parse_source(input, false);
|
||||||
|
|
||||||
|
// for stmt in &block.stmts {
|
||||||
|
// match stmt {
|
||||||
|
// Statement::Expression(expr) => {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// No merge at the end because this parse is speculative
|
||||||
|
}
|
||||||
|
|
||||||
|
fn highlight_expression(expression: &Expression) {
|
||||||
|
// match &expression.expr {
|
||||||
|
// Expr::BinaryOp()
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user