yash_syntax/parser.rs
1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2020 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Syntax parser for the shell language
18//!
19//! The shell language parsing system has two important components: the lexical
20//! analyzer and the syntax parser.
21//!
22//! The lexical analyzer, or simply [lexer](lex::Lexer), extracts tokens from
23//! the source code string. Tokenization for the shell language involves parsing
24//! expansions like parameter expansions and command substitutions, which makes
25//! the lexer much more complicated than those for normal programming languages.
26//! However, as long as you use the lexer indirectly via the parser, you don't
27//! have to care about such details.
28//!
29//! The syntax [parser](Parser) examines tokens produced by the lexer and
30//! constructs abstract syntax trees. The below code illustrates the basic usage
31//! of the parser.
32//!
33//! ```
34//! // First, prepare an input object that the lexer reads from.
35//! use yash_syntax::input::Memory;
36//! let input = Box::new(Memory::new("echo $?"));
37//!
38//! // Next, create a lexer.
39//! use yash_syntax::parser::lex::Lexer;
40//! let mut lexer = Lexer::new(input);
41//!
42//! // Then, create a new parser borrowing the lexer.
43//! use yash_syntax::parser::Parser;
44//! let mut parser = Parser::new(&mut lexer);
45//!
46//! // Lastly, call the parser's function to get an AST.
47//! use futures_executor::block_on;
48//! let list = block_on(parser.command_line()).unwrap().unwrap();
49//! assert_eq!(list.to_string(), "echo $?");
50//! ```
51//!
52//! If there is any error reading the input or analyzing the source code, the
53//! parser returns an [`Error`] object. In case of a syntax error, the `Error`
54//! object's [cause](ErrorCause) will be a value of [`SyntaxError`] that
55//! describes it.
56//!
57//! Most lexer and parser functions are asynchronous because underlying
58//! [input](crate::input::Input) is asynchronous. Only as many lines are read
59//! from the input as needed to parse a complete AST.
60//!
61//! Note that most AST types have the [`FromStr`](std::str::FromStr) trait
62//! implemented for them. If you don't need to include source location
63//! information in the resultant AST, calling the `parse` function on a string
64//! is a convenient way to parse a code fragment.
65//! See the [`syntax`](crate::syntax) module for an example of this.
66
67mod core;
68mod error;
69mod from_str;
70
71mod and_or;
72mod case;
73mod command;
74mod compound_command;
75mod for_loop;
76mod function;
77mod grouping;
78mod r#if;
79mod list;
80mod pipeline;
81mod redir;
82mod simple_command;
83mod while_loop;
84
85pub mod lex;
86
87pub use self::core::Config;
88pub use self::core::Parser;
89pub use self::core::Rec;
90pub use self::core::Result;
91pub use self::error::Error;
92pub use self::error::ErrorCause;
93pub use self::error::SyntaxError;