4 个版本 (破坏性更新)
使用旧的 Rust 2015
0.4.0 | 2018 年 1 月 29 日 |
---|---|
0.3.0 | 2018 年 1 月 28 日 |
0.2.0 | 2017 年 4 月 22 日 |
0.1.0 | 2017 年 4 月 17 日 |
#9 in #indentation
56KB
1K SLoC
缩进标记器
一个小巧简单的缩进标记器
一个类似的项目是 indentation_flattener. 在这个例子中,我们通过添加 PUSH_INDENT 和 POP_INDENT 来平坦化输入。这对 PEG 语法来说看起来更好。
使用方法
添加到 cargo.toml
[source, toml]
[dependencies]
indent_tokenizer = "0.2.0"
见下面的示例
修改
0.2.0:: 删除了通用类型(如 String、u32 或 usize)+ 使用具体类型(新类型)
缩进格式
制表符在缩进分组中无效。
让我们通过示例来了解。
简单有效输入
.....
...
....
....
....
....
....
....
....
....
缩进组可以包含任意数量的空格
有效缩进不同空格
..... level0
.... level1 <--
.... level2
.... level1 <--
.... level1 <--
.... level0
.... level0
.... level1 <--
不同级别的相同缩进不是一个好主意,但在创建新级别时是允许的。
在这个例子中,最后一个级别1的缩进比前面的更多
无效缩进
.....
...
....
....
.... <-- incorrect indentation
.... <-- correct previous ident level
....
....
....
....
为了回到一个级别,缩进必须与该级别上之前的缩进匹配。
如前一个示例所示,增加级别是自由缩进。
起始行指示符
|.....
|.....
|......
|......
你可以用 |
开始行,但这不是必需的。
缩进指示符是可选的
.....
|.....
......
......
......
注意 |
在缩进级别之前一个位置。
当需要以空格开始时,这很有用。
我想用空格开始一行
.....
| ..... <- This line starts with an space
| ...... <- Starting with 2 spaces
|..... <- starts with no spaces
..... <- starting with no spaces
... <- starting with no spaces
我的行以 |
开始
.....
||..... This line starts with a `|`
|...... This one starts with `.`
如果一行没有内容或只有空格,则该行是空的。
空行
.....
.....
.....
.....
..... next line is empty
..... next line is empty
.....
..... next line is empty
如果我想要表示空行怎么办?
表示空行
.....
.....
.....
.....
..... I want new line after this line
|
..... and three new lines, please
|
|
|
如果我想要表示行尾的空格怎么办?
行尾的空格不会被删除,因此,你不需要为此做任何事情。
但是,可以有趣地表示它,因为一些编辑器可以运行尾随空格,或者只是因为它可以可视化。
表示行尾空格
.....
.....
.....
.....
This line keeps 2 spaces and end |
and you know it
Next line is properly indented and only has spaces
| |
实际上,你可以在所有行的末尾写 |
。它将被删除。
以下字符串是等价的。
行尾的 |
是可选的
.....|
.....|
.....|
.....|
.....
.....
.....
.....
但我可能需要在行尾有一个管道 |
行尾的管道
.....
.....
.....
.....
This line ends with a pipe||
陷阱
|.....
..... <- Invalid, remember, indentation mark | is previus to real indentation
|.....
..... <- This is OK, but not elegant
| .... <- I want to start with an space
|..... <- This is redundant, but more clear
标记
- 级别的每次变化都表示标记的结束。
- 空行用于在相同级别上分隔标记
- 标记包含行和标记列表
令牌
This is the first token
This is another token, because it's on a different level
And another token
This is also a different token
A token can contain
multiple lines
This is another token
with three
lines
Empty lines can be used to
separate tokens
This is a token,
that continues
here. Next empty line define
a token division
And this is a different one
with a couple of lines
缩进令牌化API
版本0.2删除了通用类型,如String、usize、u32等...
相反,它为每个上下文创建了一个特定的类型。
具体类型:[source, rust]
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct LineNum(u32);
#[derive(Debug, PartialEq, Clone, Eq)]
pub struct SLine(String);
- LineNum表示行号
- SLine表示行字符串
内部,系统使用更多的新类型,如NSpaces表示空格数
要调用的函数:[source, rust]
pub fn tokenize(input: &str) -> Result<Vec<Token>, Error>
令牌类型:[source, rust]
#[derive(Debug, PartialEq)]
pub struct Token {
pub lines: Vec<SLine>,
pub tokens: Vec<Token>,
}
错误类型:[source, rust]
#[derive(Debug, PartialEq)]
pub struct Error {
pub line: LineNum,
pub desc: String,
}
就这些
查看lib.rs以了解API,查看tests.rs以查看示例
示例
您可以查看tests.rs,其中包含几个测试。
.复杂示例 [source, rust]
let tokens = tokenize("
0
|| 01a
01b
01c
02a
02b
|020a
||020b
| 021a
|021b
1a
1b
11a
||11b
11c
12a ||
|12b ||
2a
21a
21b
|
|
")
结果将是
[source, rust]
vec![Token {
lines: vec![SLine::from("0")],
tokens: vec![Token {
lines: vec![SLine::from("| 01a"),
SLine::from("01b"),
SLine::from("01c")],
tokens: vec![],
},
Token {
lines: vec![SLine::from("02a"), SLine::from("02b")],
tokens: vec![Token {
lines: vec![SLine::from("020a"),
SLine::from("|020b")],
tokens: vec![],
},
Token {
lines: vec![SLine::from(" 021a"),
SLine::from("021b")],
tokens: vec![],
}],
}],
},
Token {
lines: vec![SLine::from("1a"), SLine::from("1b")],
tokens: vec![Token {
lines: vec![SLine::from("11a"),
SLine::from("|11b"),
SLine::from("11c")],
tokens: vec![],
},
Token {
lines: vec![SLine::from("12a |"), SLine::from("12b |")],
tokens: vec![],
}],
},
Token {
lines: vec![SLine::from("2a")],
tokens: vec![Token {
lines: vec![SLine::from("21a"),
SLine::from("21b"),
SLine::from(""),
SLine::from("")],
tokens: vec![],
}],
}];