Parse for expr and stmt variants + identifier, constant

This commit is contained in:
Jeong YunWon 2023-05-31 19:43:42 +09:00
parent ae3a477c97
commit 0b40db0735
4 changed files with 1358 additions and 2 deletions

1243
parser/src/gen/parse.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -59,6 +59,9 @@ where
fn parse(source: &str, source_path: &str) -> Result<Self, ParseError> {
Self::parse_starts_at(source, source_path, TextSize::default())
}
fn parse_without_path(source: &str) -> Result<Self, ParseError> {
Self::parse(source, "<unknown>")
}
fn parse_starts_at(
source: &str,
source_path: &str,
@ -197,6 +200,52 @@ impl Parse for ast::Expr {
}
}
impl Parse for ast::Identifier {
fn lex_starts_at(
source: &str,
offset: TextSize,
) -> SoftKeywordTransformer<Lexer<std::str::Chars>> {
ast::Expr::lex_starts_at(source, offset)
}
fn parse_tokens(
lxr: impl IntoIterator<Item = LexResult>,
source_path: &str,
) -> Result<Self, ParseError> {
let expr = ast::Expr::parse_tokens(lxr, source_path)?;
match expr {
ast::Expr::Name(name) => Ok(name.id),
expr => Err(ParseError {
error: ParseErrorType::InvalidToken,
offset: expr.range().start(),
source_path: source_path.to_owned(),
}),
}
}
}
impl Parse for ast::Constant {
fn lex_starts_at(
source: &str,
offset: TextSize,
) -> SoftKeywordTransformer<Lexer<std::str::Chars>> {
ast::Expr::lex_starts_at(source, offset)
}
fn parse_tokens(
lxr: impl IntoIterator<Item = LexResult>,
source_path: &str,
) -> Result<Self, ParseError> {
let expr = ast::Expr::parse_tokens(lxr, source_path)?;
match expr {
ast::Expr::Constant(c) => Ok(c.value),
expr => Err(ParseError {
error: ParseErrorType::InvalidToken,
offset: expr.range().start(),
source_path: source_path.to_owned(),
}),
}
}
}
/// Parse a full Python program usually consisting of multiple lines.
///
/// This is a convenience function that can be used to parse a full Python program without having to
@ -505,6 +554,8 @@ pub(super) fn optional_range(start: TextSize, end: TextSize) -> OptionalRange<Te
OptionalRange::<TextRange>::new(start, end)
}
include!("gen/parse.rs");
#[cfg(test)]
mod tests {
use super::*;
@ -1033,4 +1084,21 @@ def args_to_tuple(*args: *Ts) -> Tuple[*Ts]: ...
.unwrap();
insta::assert_debug_snapshot!(parse_ast);
}
#[test]
fn test_parse_constant() {
use num_traits::ToPrimitive;
let c = ast::Constant::parse_without_path("'string'").unwrap();
assert_eq!(c.str().unwrap(), "string");
let c = ast::Constant::parse_without_path("10").unwrap();
assert_eq!(c.int().unwrap().to_i32().unwrap(), 10);
}
#[test]
fn test_parse_identifier() {
let i = ast::Identifier::parse_without_path("test").unwrap();
assert_eq!(i.as_str(), "test");
}
}