lua_parser/
lib.rs

1//!
2//! ```rust
3//! let source = " <lua source code> ";
4//!
5//! let block = match lua_parser::parse_str(&source) {
6//!     Ok(block) => block,
7//!     Err(err) => {
8//!         println!("{}", err);
9//!         return;
10//!     }
11//! };
12//!
13//! println!("AST:\n{:#?}", block);
14//! ```
15
16mod error;
17mod expression;
18mod statement;
19// mod parser;
20mod parser_expanded;
21use parser_expanded as parser;
22mod spannedstring;
23
24// re-exports
25pub use spannedstring::SpannedString;
26
27pub use lua_tokenizer::FloatType;
28pub use lua_tokenizer::IntOrFloat;
29pub use lua_tokenizer::IntType;
30pub use lua_tokenizer::Span;
31pub use lua_tokenizer::Token;
32
33pub use error::InvalidToken;
34pub use error::ParseError;
35pub use error::TokenizeError;
36
37pub use expression::ExprBinary;
38pub use expression::ExprBinaryData;
39pub use expression::ExprBool;
40pub use expression::ExprFunction;
41pub use expression::ExprFunctionCall;
42pub use expression::ExprIdent;
43pub use expression::ExprNil;
44pub use expression::ExprNumeric;
45pub use expression::ExprString;
46pub use expression::ExprTable;
47pub use expression::ExprTableIndex;
48pub use expression::ExprUnary;
49pub use expression::ExprUnaryData;
50pub use expression::ExprVariadic;
51pub use expression::Expression;
52pub use expression::FunctionCallArguments;
53pub use expression::ParameterList;
54pub use expression::TableField;
55pub use expression::TableFieldKeyValue;
56pub use expression::TableFieldNameValue;
57pub use expression::TableFieldValue;
58
59pub use statement::AttName;
60pub use statement::Attrib;
61pub use statement::Block;
62pub use statement::FunctionName;
63pub use statement::ReturnStatement;
64pub use statement::Statement;
65pub use statement::StmtAssignment;
66pub use statement::StmtBreak;
67pub use statement::StmtDo;
68pub use statement::StmtElseIf;
69pub use statement::StmtFor;
70pub use statement::StmtForGeneric;
71pub use statement::StmtFunctionCall;
72pub use statement::StmtFunctionDefinition;
73pub use statement::StmtFunctionDefinitionLocal;
74pub use statement::StmtGoto;
75pub use statement::StmtIf;
76pub use statement::StmtLabel;
77pub use statement::StmtLocalDeclaration;
78pub use statement::StmtNone;
79pub use statement::StmtRepeat;
80pub use statement::StmtWhile;
81
82pub use lua_tokenizer::Tokenizer;
83
84pub use parser::ChunkOrExpressionsContext as Context;
85pub use parser::ChunkOrExpressionsParser as Parser;
86
87/// for interpreter to handle both chunk and expression
88#[derive(Debug, Clone)]
89pub enum ChunkOrExpressions {
90    Chunk(Block),
91    Expressions(Vec<Expression>),
92}
93
94/// parse lua source code to AST
95pub fn parse_str(source: &str) -> Result<Block, ParseError> {
96    parse_bytes(source.as_bytes())
97}
98
99/// parse lua source code to AST
100pub fn parse_bytes(source: &[u8]) -> Result<Block, ParseError> {
101    let tokenizer = Tokenizer::from_bytes(source);
102    let parser = parser::ChunkOrExpressionsParser::new();
103    let mut context = parser::ChunkOrExpressionsContext::new();
104
105    for token in tokenizer.into_iter() {
106        let token = match token {
107            Ok(token) => token,
108            Err(e) => {
109                return Err(ParseError::TokenizeError(e));
110            }
111        };
112
113        match context.feed(&parser, token, &mut ()) {
114            Ok(_) => {}
115            Err(err) => {
116                let (expected_terms, expected_nonterms) = context.expected_token_str(&parser);
117                let error = InvalidToken {
118                    token: Some(err.term.into_term().unwrap()),
119                    expected: expected_terms.collect(),
120                    expected_nonterm: expected_nonterms.collect(),
121                };
122                return Err(ParseError::InvalidToken(error));
123                // parser::ChunkOrExpressionsParseError::ReduceAction(reduce_actions) => {
124                //     return Err(reduce_actions.into_iter().next().unwrap());
125                // }
126            }
127        }
128    }
129
130    let mut block = None;
131
132    let (expected_terms, expected_nonterms) = context.expected_token_str(&parser);
133    let res = context.accept(&parser, &mut ());
134    match res {
135        Ok(matched) => {
136            for matched in matched {
137                match matched {
138                    ChunkOrExpressions::Chunk(block_) => {
139                        if block.is_some() {
140                            return Err(ParseError::Ambiguous);
141                        }
142                        block = Some(block_);
143                    }
144                    _ => {}
145                }
146            }
147        }
148        Err(_) => {
149            let error = InvalidToken {
150                token: None,
151                expected: expected_terms.collect(),
152                expected_nonterm: expected_nonterms.collect(),
153            };
154            return Err(ParseError::InvalidToken(error));
155        }
156    }
157
158    if let Some(block) = block {
159        Ok(block)
160    } else {
161        Err(ParseError::Ambiguous)
162    }
163}