feat(parser): parse double quoted strings
This commit is contained in:
parent
c1881bb7b2
commit
78593f1667
48 changed files with 594 additions and 68 deletions
|
@ -73,11 +73,11 @@ fn build_tree_pipeline<'a>(
|
||||||
ParseEvent::StartNode(NodeKind::Command) => {
|
ParseEvent::StartNode(NodeKind::Command) => {
|
||||||
children.push(build_tree_command(parser, source, pos)?)
|
children.push(build_tree_command(parser, source, pos)?)
|
||||||
}
|
}
|
||||||
ParseEvent::EndNode => break,
|
|
||||||
ParseEvent::NewLeaf(NodeKind::Pipe, _) => {
|
ParseEvent::NewLeaf(NodeKind::Pipe, _) => {
|
||||||
*pos += 1;
|
*pos += 1;
|
||||||
children.last_mut().unwrap().1 = Redirect::Stdout;
|
children.last_mut().unwrap().1 = Redirect::Stdout;
|
||||||
}
|
}
|
||||||
|
ParseEvent::EndNode => break,
|
||||||
ParseEvent::NewLeaf(_, len) => *pos += len,
|
ParseEvent::NewLeaf(_, len) => *pos += len,
|
||||||
ParseEvent::Error(err, _) => return Err(err),
|
ParseEvent::Error(err, _) => return Err(err),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -116,9 +116,38 @@ fn build_tree_word<'a>(
|
||||||
) -> Result<Word<'a>, ParseError> {
|
) -> Result<Word<'a>, ParseError> {
|
||||||
let mut children = vec![];
|
let mut children = vec![];
|
||||||
|
|
||||||
|
while let Some(ev) = parser.next() {
|
||||||
|
match ev {
|
||||||
|
ParseEvent::NewLeaf(NodeKind::PlainText, len) => {
|
||||||
|
children.push(WordPart::Text(&source[*pos..*pos + len]));
|
||||||
|
*pos += len
|
||||||
|
}
|
||||||
|
ParseEvent::NewLeaf(NodeKind::EscapedChar, len) => {
|
||||||
|
children.push(WordPart::Text(&source[*pos + 1..*pos + len]));
|
||||||
|
*pos += len
|
||||||
|
}
|
||||||
|
ParseEvent::StartNode(NodeKind::DQuotedString) => {
|
||||||
|
build_tree_string(parser, source, pos, &mut children)?
|
||||||
|
}
|
||||||
|
ParseEvent::EndNode => break,
|
||||||
|
ParseEvent::NewLeaf(_, len) => *pos += len,
|
||||||
|
ParseEvent::Error(err, _) => return Err(err),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Word(children))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_tree_string<'a>(
|
||||||
|
parser: &mut Parser,
|
||||||
|
source: &'a str,
|
||||||
|
pos: &mut usize,
|
||||||
|
children: &mut Vec<WordPart<'a>>,
|
||||||
|
) -> Result<(), ParseError> {
|
||||||
for ev in parser {
|
for ev in parser {
|
||||||
match ev {
|
match ev {
|
||||||
ParseEvent::NewLeaf(NodeKind::PlainWord, len) => {
|
ParseEvent::NewLeaf(NodeKind::PlainText, len) => {
|
||||||
children.push(WordPart::Text(&source[*pos..*pos + len]));
|
children.push(WordPart::Text(&source[*pos..*pos + len]));
|
||||||
*pos += len
|
*pos += len
|
||||||
}
|
}
|
||||||
|
@ -127,10 +156,11 @@ fn build_tree_word<'a>(
|
||||||
*pos += len
|
*pos += len
|
||||||
}
|
}
|
||||||
ParseEvent::EndNode => break,
|
ParseEvent::EndNode => break,
|
||||||
|
ParseEvent::NewLeaf(_, len) => *pos += len,
|
||||||
ParseEvent::Error(err, _) => return Err(err),
|
ParseEvent::Error(err, _) => return Err(err),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Word(children))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,10 @@ pub enum TokenKind {
|
||||||
Semicolon,
|
Semicolon,
|
||||||
/// A pipe.
|
/// A pipe.
|
||||||
Pipe,
|
Pipe,
|
||||||
/// A plain, unquoted word.
|
/// Double quotes.
|
||||||
PlainWord,
|
DoubleQuote,
|
||||||
|
/// Plain text. Either outside or inside of quotes.
|
||||||
|
PlainText,
|
||||||
/// A backslash followed by another character.
|
/// A backslash followed by another character.
|
||||||
EscapedChar,
|
EscapedChar,
|
||||||
/// A line comment, from # to newline.
|
/// A line comment, from # to newline.
|
||||||
|
@ -101,6 +103,7 @@ impl Lexer<'_> {
|
||||||
let kind = match c {
|
let kind = match c {
|
||||||
';' => TokenKind::Semicolon,
|
';' => TokenKind::Semicolon,
|
||||||
'|' => TokenKind::Pipe,
|
'|' => TokenKind::Pipe,
|
||||||
|
'"' => TokenKind::DoubleQuote,
|
||||||
|
|
||||||
c if is_whitespace(c) => {
|
c if is_whitespace(c) => {
|
||||||
self.eat_while(is_whitespace);
|
self.eat_while(is_whitespace);
|
||||||
|
@ -123,8 +126,37 @@ impl Lexer<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
self.eat_while(|c| ![' ', '\t', '\n', ';', '|', '\\'].contains(&c));
|
self.eat_while(|c| ![' ', '\t', '\n', ';', '|', '\\', '"'].contains(&c));
|
||||||
TokenKind::PlainWord
|
TokenKind::PlainText
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let len = self.token_len();
|
||||||
|
|
||||||
|
Token { kind, len }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the next token in the string sublanguage.
|
||||||
|
pub fn next_string_token(&mut self) -> Token {
|
||||||
|
match self.next_char() {
|
||||||
|
None => Token {
|
||||||
|
kind: TokenKind::Eof,
|
||||||
|
len: 0,
|
||||||
|
},
|
||||||
|
Some(c) => {
|
||||||
|
let kind = match c {
|
||||||
|
'"' => TokenKind::DoubleQuote,
|
||||||
|
|
||||||
|
'\\' => {
|
||||||
|
self.next_char();
|
||||||
|
TokenKind::EscapedChar
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
self.eat_while(|c| !['"', '\\'].contains(&c));
|
||||||
|
TokenKind::PlainText
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//! _terminator ::= SEMICOLON | NEWLINES | EOF
|
//! _terminator ::= SEMICOLON | NEWLINES | EOF
|
||||||
//! pipeline ::= command (PIPE NEWLINES? command)*
|
//! pipeline ::= command (PIPE NEWLINES? command)*
|
||||||
//! command ::= word+
|
//! command ::= word+
|
||||||
//! word ::= (PLAIN_WORD)+
|
//! word ::= (PLAIN_TEXT|DQUOTES PLAIN_TEXT DQUOTES)+
|
||||||
//!
|
//!
|
||||||
//! extras ::= COMMENT | WHITESPACE | BACKSLASH_N
|
//! extras ::= COMMENT | WHITESPACE | BACKSLASH_N
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
@ -20,7 +20,8 @@ pub enum NodeKind {
|
||||||
Newlines,
|
Newlines,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
Pipe,
|
Pipe,
|
||||||
PlainWord,
|
DoubleQuote,
|
||||||
|
PlainText,
|
||||||
EscapedChar,
|
EscapedChar,
|
||||||
Comment,
|
Comment,
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ pub enum NodeKind {
|
||||||
Pipeline,
|
Pipeline,
|
||||||
Command,
|
Command,
|
||||||
Word,
|
Word,
|
||||||
|
DQuotedString,
|
||||||
|
|
||||||
/// Read a pipe but didn't start word yet.
|
/// Read a pipe but didn't start word yet.
|
||||||
PipelineCont,
|
PipelineCont,
|
||||||
|
@ -118,23 +120,35 @@ impl Iterator for Parser<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! leaf {
|
macro_rules! leaf {
|
||||||
($type:expr) => {{
|
($type:expr $(, $mode:ident)?) => {{
|
||||||
use NodeKind::*;
|
use NodeKind::*;
|
||||||
let len = self.lookahead.len;
|
let len = self.lookahead.len;
|
||||||
self.lookahead = self.lex.next_command_token();
|
self.lookahead = next_token!($($mode)?);
|
||||||
Some(ParseEvent::NewLeaf($type, len))
|
Some(ParseEvent::NewLeaf($type, len))
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($type:expr) => {{
|
($type:expr $(, $mode:ident)?) => {{
|
||||||
use ParseError::*;
|
use ParseError::*;
|
||||||
let len = self.lookahead.len;
|
let len = self.lookahead.len;
|
||||||
self.lookahead = self.lex.next_command_token();
|
self.lookahead = next_token!($($mode)?);
|
||||||
Some(ParseEvent::Error($type, len))
|
Some(ParseEvent::Error($type, len))
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! next_token {
|
||||||
|
() => {
|
||||||
|
self.lex.next_command_token()
|
||||||
|
};
|
||||||
|
(Command) => {
|
||||||
|
self.lex.next_command_token()
|
||||||
|
};
|
||||||
|
(String) => {
|
||||||
|
self.lex.next_string_token()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
use TokenKind::*;
|
use TokenKind::*;
|
||||||
|
|
||||||
if let Some(ev) = self.buffer.take() {
|
if let Some(ev) = self.buffer.take() {
|
||||||
|
@ -149,7 +163,7 @@ impl Iterator for Parser<'_> {
|
||||||
Newlines => leaf!(Newlines),
|
Newlines => leaf!(Newlines),
|
||||||
Semicolon => leaf!(Semicolon),
|
Semicolon => leaf!(Semicolon),
|
||||||
Comment => leaf!(Comment),
|
Comment => leaf!(Comment),
|
||||||
PlainWord | EscapedChar => call!(Pipeline),
|
PlainText | DoubleQuote | EscapedChar => call!(Pipeline),
|
||||||
Pipe => error!(UnexpectedPipe),
|
Pipe => error!(UnexpectedPipe),
|
||||||
Eof => chain!(None, ret!()), // return silently
|
Eof => chain!(None, ret!()), // return silently
|
||||||
},
|
},
|
||||||
|
@ -157,14 +171,14 @@ impl Iterator for Parser<'_> {
|
||||||
Whitespace => leaf!(Whitespace),
|
Whitespace => leaf!(Whitespace),
|
||||||
Comment => leaf!(Comment),
|
Comment => leaf!(Comment),
|
||||||
Pipe => chain!(leaf!(Pipe), call!(PipelineCont)),
|
Pipe => chain!(leaf!(Pipe), call!(PipelineCont)),
|
||||||
PlainWord | EscapedChar => call!(Command),
|
PlainText | DoubleQuote | EscapedChar => call!(Command),
|
||||||
Newlines | Semicolon | Eof => ret!(),
|
Newlines | Semicolon | Eof => ret!(),
|
||||||
},
|
},
|
||||||
NodeKind::PipelineCont => match self.lookahead.kind {
|
NodeKind::PipelineCont => match self.lookahead.kind {
|
||||||
Whitespace => leaf!(Whitespace),
|
Whitespace => leaf!(Whitespace),
|
||||||
Newlines => leaf!(Newlines),
|
Newlines => leaf!(Newlines),
|
||||||
Comment => leaf!(Comment),
|
Comment => leaf!(Comment),
|
||||||
PlainWord | EscapedChar => tailcall!(Command),
|
PlainText | DoubleQuote | EscapedChar => tailcall!(Command),
|
||||||
Semicolon => chain_buf!(chain!(error!(UnexpectedSemicolon), ret!()), ret!()),
|
Semicolon => chain_buf!(chain!(error!(UnexpectedSemicolon), ret!()), ret!()),
|
||||||
Pipe => chain!(error!(UnexpectedPipe), ret!()),
|
Pipe => chain!(error!(UnexpectedPipe), ret!()),
|
||||||
Eof => chain!(error!(UnexpectedEof), ret!()),
|
Eof => chain!(error!(UnexpectedEof), ret!()),
|
||||||
|
@ -172,15 +186,23 @@ impl Iterator for Parser<'_> {
|
||||||
NodeKind::Command => match self.lookahead.kind {
|
NodeKind::Command => match self.lookahead.kind {
|
||||||
Whitespace => leaf!(Whitespace),
|
Whitespace => leaf!(Whitespace),
|
||||||
Comment => leaf!(Comment),
|
Comment => leaf!(Comment),
|
||||||
PlainWord | EscapedChar => call!(Word),
|
PlainText | DoubleQuote | EscapedChar => call!(Word),
|
||||||
Newlines | Semicolon | Eof => ret!(),
|
Newlines | Semicolon | Eof => ret!(),
|
||||||
Pipe => ret!(),
|
Pipe => ret!(),
|
||||||
},
|
},
|
||||||
NodeKind::Word => match self.lookahead.kind {
|
NodeKind::Word => match self.lookahead.kind {
|
||||||
PlainWord => leaf!(PlainWord),
|
PlainText => leaf!(PlainText),
|
||||||
EscapedChar => leaf!(EscapedChar),
|
EscapedChar => leaf!(EscapedChar),
|
||||||
|
DoubleQuote => chain_buf!(call!(DQuotedString), leaf!(DoubleQuote, String)),
|
||||||
Comment | Whitespace | Newlines | Semicolon | Pipe | Eof => ret!(),
|
Comment | Whitespace | Newlines | Semicolon | Pipe | Eof => ret!(),
|
||||||
},
|
},
|
||||||
|
NodeKind::DQuotedString => match self.lookahead.kind {
|
||||||
|
PlainText => leaf!(PlainText, String),
|
||||||
|
EscapedChar => leaf!(EscapedChar, String),
|
||||||
|
DoubleQuote => chain_buf!(leaf!(DoubleQuote, Command), ret!()),
|
||||||
|
Eof => chain_buf!(error!(UnexpectedEof, Command), ret!()),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,3 +143,30 @@ fn reject_double_pipe() {
|
||||||
|
|
||||||
assert_snapshot!(actual);
|
assert_snapshot!(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_quote_string() {
|
||||||
|
let source = r#""hello world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaped_char_in_double_quotes() {
|
||||||
|
let source = r#""hello \" world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unterminated_double_quotes() {
|
||||||
|
let source = r#""hello world"#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
|
@ -143,3 +143,30 @@ fn reject_double_pipe() {
|
||||||
|
|
||||||
assert_snapshot!(actual);
|
assert_snapshot!(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_quote_string() {
|
||||||
|
let source = r#""hello world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaped_char_in_double_quotes() {
|
||||||
|
let source = r#""hello \" world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unterminated_double_quotes() {
|
||||||
|
let source = r#""hello world"#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
|
@ -81,3 +81,30 @@ fn comment() {
|
||||||
|
|
||||||
assert_snapshot!(actual);
|
assert_snapshot!(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_quotes_in_command() {
|
||||||
|
let source = r#"""#;
|
||||||
|
|
||||||
|
let actual = Lexer::new(source).next_command_token();
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_quotes_in_string() {
|
||||||
|
let source = r#"""#;
|
||||||
|
|
||||||
|
let actual = Lexer::new(source).next_string_token();
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaped_quotes_in_string() {
|
||||||
|
let source = r#"\""#;
|
||||||
|
|
||||||
|
let actual = Lexer::new(source).next_string_token();
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
|
@ -143,3 +143,30 @@ fn reject_double_pipe() {
|
||||||
|
|
||||||
assert_snapshot!(actual);
|
assert_snapshot!(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_quote_string() {
|
||||||
|
let source = r#""hello world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn escaped_char_in_double_quotes() {
|
||||||
|
let source = r#""hello \" world""#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unterminated_double_quotes() {
|
||||||
|
let source = r#""hello world"#;
|
||||||
|
|
||||||
|
let actual = parse(source);
|
||||||
|
|
||||||
|
assert_snapshot!(actual);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/ast.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Code(
|
||||||
|
[
|
||||||
|
Pipeline(
|
||||||
|
Pipeline(
|
||||||
|
[
|
||||||
|
Command(
|
||||||
|
[
|
||||||
|
Word(
|
||||||
|
[
|
||||||
|
Text(
|
||||||
|
"hello world",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/ast.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Ok(
|
||||||
|
Code(
|
||||||
|
[
|
||||||
|
Pipeline(
|
||||||
|
Pipeline(
|
||||||
|
[
|
||||||
|
Command(
|
||||||
|
[
|
||||||
|
Word(
|
||||||
|
[
|
||||||
|
Text(
|
||||||
|
"hello ",
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"\"",
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
" world",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/ast.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Err(
|
||||||
|
UnexpectedEof,
|
||||||
|
)
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -49,7 +49,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -62,7 +62,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/cst.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Tree {
|
||||||
|
kind: Program,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Pipeline,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Command,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Word,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: DQuotedString,
|
||||||
|
children: [
|
||||||
|
Leaf {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: PlainText,
|
||||||
|
len: 11,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/cst.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Tree {
|
||||||
|
kind: Program,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Pipeline,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Command,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Word,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: DQuotedString,
|
||||||
|
children: [
|
||||||
|
Leaf {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: PlainText,
|
||||||
|
len: 6,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: EscapedChar,
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: PlainText,
|
||||||
|
len: 6,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -41,7 +41,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -54,7 +54,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -41,7 +41,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -49,7 +49,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -46,7 +46,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -54,7 +54,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 5,
|
len: 5,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -42,7 +42,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 4,
|
len: 4,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -28,7 +28,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/cst.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Tree {
|
||||||
|
kind: Program,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Pipeline,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Command,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: Word,
|
||||||
|
children: [
|
||||||
|
Tree {
|
||||||
|
kind: DQuotedString,
|
||||||
|
children: [
|
||||||
|
Leaf {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
kind: PlainText,
|
||||||
|
len: 11,
|
||||||
|
},
|
||||||
|
Error {
|
||||||
|
kind: UnexpectedEof,
|
||||||
|
len: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 4,
|
len: 4,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ Tree {
|
||||||
kind: Word,
|
kind: Word,
|
||||||
children: [
|
children: [
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 5,
|
len: 5,
|
||||||
},
|
},
|
||||||
Leaf {
|
Leaf {
|
||||||
|
@ -23,7 +23,7 @@ Tree {
|
||||||
len: 2,
|
len: 2,
|
||||||
},
|
},
|
||||||
Leaf {
|
Leaf {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 5,
|
len: 5,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/lexer.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Token {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/lexer.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Token {
|
||||||
|
kind: DoubleQuote,
|
||||||
|
len: 1,
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/lexer.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
Token {
|
||||||
|
kind: EscapedChar,
|
||||||
|
len: 2,
|
||||||
|
}
|
|
@ -3,6 +3,6 @@ source: crates/oyster_parser/tests/it/lexer.rs
|
||||||
expression: actual
|
expression: actual
|
||||||
---
|
---
|
||||||
Token {
|
Token {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 6,
|
len: 6,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,6 @@ source: crates/oyster_parser/tests/it/lexer.rs
|
||||||
expression: actual
|
expression: actual
|
||||||
---
|
---
|
||||||
Token {
|
Token {
|
||||||
kind: PlainWord,
|
kind: PlainText,
|
||||||
len: 13,
|
len: 13,
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -45,7 +45,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -57,7 +57,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/parser.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
[
|
||||||
|
StartNode(
|
||||||
|
Pipeline,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Command,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Word,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
DQuotedString,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
DoubleQuote,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
PlainText,
|
||||||
|
11,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
DoubleQuote,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
]
|
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/parser.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
[
|
||||||
|
StartNode(
|
||||||
|
Pipeline,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Command,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Word,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
DQuotedString,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
DoubleQuote,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
PlainText,
|
||||||
|
6,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
EscapedChar,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
PlainText,
|
||||||
|
6,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
DoubleQuote,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
]
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -37,7 +37,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -49,7 +49,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -37,7 +37,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -45,7 +45,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -41,7 +41,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -49,7 +49,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
3,
|
3,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
5,
|
5,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -37,7 +37,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
@ -25,7 +25,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
6,
|
6,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
source: crates/oyster_parser/tests/it/parser.rs
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
[
|
||||||
|
StartNode(
|
||||||
|
Pipeline,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Command,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
Word,
|
||||||
|
),
|
||||||
|
StartNode(
|
||||||
|
DQuotedString,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
DoubleQuote,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
NewLeaf(
|
||||||
|
PlainText,
|
||||||
|
11,
|
||||||
|
),
|
||||||
|
Error(
|
||||||
|
UnexpectedEof,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
EndNode,
|
||||||
|
]
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
|
@ -13,7 +13,7 @@ expression: actual
|
||||||
Word,
|
Word,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
5,
|
5,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
|
@ -21,7 +21,7 @@ expression: actual
|
||||||
2,
|
2,
|
||||||
),
|
),
|
||||||
NewLeaf(
|
NewLeaf(
|
||||||
PlainWord,
|
PlainText,
|
||||||
4,
|
4,
|
||||||
),
|
),
|
||||||
EndNode,
|
EndNode,
|
||||||
|
|
Loading…
Reference in a new issue