4个版本 (破坏性更新)

0.4.0 2024年5月15日
0.3.0 2024年5月15日
0.2.1 2021年2月8日
0.2.0 2021年2月7日
0.1.0 2021年1月10日

#72 in 编程语言

Download history 233/week @ 2024-05-11 63/week @ 2024-05-18 13/week @ 2024-05-25 6/week @ 2024-06-01 21/week @ 2024-06-08 9/week @ 2024-06-15 18/week @ 2024-06-22 46/week @ 2024-07-06 45/week @ 2024-07-13 55/week @ 2024-07-20 152/week @ 2024-07-27 39/week @ 2024-08-03 53/week @ 2024-08-10 27/week @ 2024-08-17

每月下载量:272

MIT许可证

170KB
4.5K SLoC

Analisar

Rust的Lua解析器

使用方法

解析器

此crate提供了3种不同的API用于解析Lua。第一种是一个相当标准的AST解析器,它不提供任何关于空白、标点符号或关键字位置的上下文信息。提供的AST旨在表示程序的意图,而不是其他任何东西。

这种解析器可以用于构建一个树遍历解释器。以下是一个输出示例

use analisar::Parser;

fn main() {
    let lua = "print('hello world')";
    let mut p = Parser::new(lua.as_bytes());
    println!("{:#?}", p.next());
}
cargo run
Some(
    Ok(
        Expression(
            FuncCall(
                FunctionCall {
                    prefix: Name(
                        Name {
                            name: "print",
                            attr: None,
                        },
                    ),
                    args: ExpList(
                        [
                            LiteralString(
                                LiteralString(
                                    "\'hello world\'",
                                ),
                            ),
                        ],
                    ),
                    method: false,
                },
            ),
        ),
    ),
)

TokenBufferParser

这是这两种解析器中的一种混合体。它提供了语句/表达式的树,以及给定语句表示的原始标记。

以下是一个此类解析器输出的示例

use analisar::TokenBufferParser;

fn main() {
    let lua = "
    -- print out hello world to stdout
    print(--[[ why!!! ]]'hello world' --[[seriously???]])";
    let mut p = TokenBufferParser::new(lua.as_bytes());
    println!("{:#?}", p.next());
}
cargo run
Some(
    Ok(
        (
            [
                Item {
                    token: Comment(
                        "-- print out hello world to stdout",
                    ),
                    span: Span {
                        start: 5,
                        end: 39,
                    },
                },
                Item {
                    token: Name(
                        "print",
                    ),
                    span: Span {
                        start: 44,
                        end: 49,
                    },
                },
                Item {
                    token: Punct(
                        OpenParen,
                    ),
                    span: Span {
                        start: 49,
                        end: 50,
                    },
                },
                Item {
                    token: Comment(
                        "--[[ why!!! ]]",
                    ),
                    span: Span {
                        start: 50,
                        end: 64,
                    },
                },
                Item {
                    token: LiteralString(
                        "\'hello world\'",
                    ),
                    span: Span {
                        start: 64,
                        end: 77,
                    },
                },
                Item {
                    token: Comment(
                        "--[[seriously???]]",
                    ),
                    span: Span {
                        start: 78,
                        end: 96,
                    },
                },
                Item {
                    token: Punct(
                        CloseParen,
                    ),
                    span: Span {
                        start: 96,
                        end: 97,
                    },
                },
            ],
            Expression(
                FuncCall(
                    FunctionCall {
                        prefix: Name(
                            Name {
                                name: "print",
                                attr: None,
                            },
                        ),
                        args: ExpList(
                            [
                                LiteralString(
                                    LiteralString(
                                        "\'hello world\'",
                                    ),
                                ),
                            ],
                        ),
                        method: false,
                    },
                ),
            ),
        ),
    ),
)

如您所见,Statement::Expression的输出与之前完全相同,但还有一个提供标记的Vec

aware::Parser

此crate提供的最后一个解析器是一个完全上下文感知的解析器。让我们看看这种解析器的输出是什么样的。

use analisar::aware::Parser;

fn main() {
    let lua = "print(('hello world')) -- print the string 'hello world' to stdout";
    let mut p = Parser::new(lua.as_bytes());
    println!("{:#?}", p.next());
}

cargo run
Some(
    Ok(
        StatementWithComments {
            statement: Expression(
                FuncCall(
                    FunctionCall {
                        prefix: Name(
                            Name {
                                name_span: Span {
                                    start: 0,
                                    end: 5,
                                },
                                name: "print",
                                attr: None,
                            },
                        ),
                        args: ExpList {
                            open_paren: Span {
                                start: 5,
                                end: 6,
                            },
                            exprs: [
                                Expr(
                                    Parened {
                                        open_span: Span {
                                            start: 6,
                                            end: 7,
                                        },
                                        expr: LiteralString(
                                            LiteralString {
                                                span: Span {
                                                    start: 7,
                                                    end: 20,
                                                },
                                                value: "\'hello world\'",
                                            },
                                        ),
                                        close_span: Span {
                                            start: 20,
                                            end: 21,
                                        },
                                    },
                                ),
                            ],
                            close_paren: Span {
                                start: 21,
                                end: 22,
                            },
                        },
                    },
                ),
            ),
            comments: [
                Item {
                    token: Comment(
                        "-- print the string \'hello world\' to stdout",
                    ),
                    span: Span {
                        start: 23,
                        end: 66,
                    },
                },
            ],
        },
    ),
)

请注意,这与前两种解析器有很大的不同。首先,函数调用的名称有一个相关的Span,它表示原始字符串中标记的字节偏移量,您会注意到每个条目中都有类似的跨度。它还提供了一种Parened表达式,用于表示表达式被放入括号中的情况。最后,我们看到还提供了适用于此语句的注释。通过这三个添加项,可以完全重建标记的原始顺序,这对于构建代码格式化器或文档生成器非常有用。

依赖关系

~540–740KB
~11K SLoC