ok/jj
1
0
Fork 0
forked from mirrors/jj

revset: move alias types to separate module

Alias expansion is purely substitution of parsed tree, which should belong to
the first parsing stage.
This commit is contained in:
Yuya Nishihara 2024-05-09 16:59:55 +09:00
parent 68db9c142c
commit e6aa8906f7
2 changed files with 103 additions and 100 deletions

View file

@ -42,9 +42,9 @@ use crate::object_id::{HexPrefix, PrefixResolution};
use crate::op_store::WorkspaceId;
use crate::repo::Repo;
use crate::revset_graph::RevsetGraphEdge;
use crate::revset_parser::{RevsetAliasId, RevsetParser, STRING_LITERAL_PARSER};
// TODO: introduce AST types and remove Rule from the re-exports
pub use crate::revset_parser::{RevsetParseError, RevsetParseErrorKind, Rule};
use crate::revset_parser::{RevsetParser, STRING_LITERAL_PARSER};
pub use crate::revset_parser::{RevsetAliasesMap, RevsetParseError, RevsetParseErrorKind, Rule};
use crate::store::Store;
use crate::str_util::StringPattern;
@ -525,102 +525,6 @@ impl ResolvedExpression {
}
}
#[derive(Clone, Debug, Default)]
pub struct RevsetAliasesMap {
symbol_aliases: HashMap<String, String>,
function_aliases: HashMap<String, (Vec<String>, String)>,
}
impl RevsetAliasesMap {
pub fn new() -> Self {
Self::default()
}
/// Adds new substitution rule `decl = defn`.
///
/// Returns error if `decl` is invalid. The `defn` part isn't checked. A bad
/// `defn` will be reported when the alias is substituted.
pub fn insert(
&mut self,
decl: impl AsRef<str>,
defn: impl Into<String>,
) -> Result<(), RevsetParseError> {
match RevsetAliasDeclaration::parse(decl.as_ref())? {
RevsetAliasDeclaration::Symbol(name) => {
self.symbol_aliases.insert(name, defn.into());
}
RevsetAliasDeclaration::Function(name, params) => {
self.function_aliases.insert(name, (params, defn.into()));
}
}
Ok(())
}
pub fn get_symbol(&self, name: &str) -> Option<&str> {
self.symbol_aliases.get(name).map(|defn| defn.as_ref())
}
pub fn get_function(&self, name: &str) -> Option<(&[String], &str)> {
self.function_aliases
.get(name)
.map(|(params, defn)| (params.as_ref(), defn.as_ref()))
}
}
/// Parsed declaration part of alias rule.
#[derive(Clone, Debug)]
enum RevsetAliasDeclaration {
Symbol(String),
Function(String, Vec<String>),
}
impl RevsetAliasDeclaration {
fn parse(source: &str) -> Result<Self, RevsetParseError> {
let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?;
let first = pairs.next().unwrap();
match first.as_rule() {
Rule::identifier => Ok(RevsetAliasDeclaration::Symbol(first.as_str().to_owned())),
Rule::function_name => {
let name = first.as_str().to_owned();
let params_pair = pairs.next().unwrap();
let params_span = params_pair.as_span();
let params = params_pair
.into_inner()
.map(|pair| match pair.as_rule() {
Rule::identifier => pair.as_str().to_owned(),
r => panic!("unexpected formal parameter rule {r:?}"),
})
.collect_vec();
if params.iter().all_unique() {
Ok(RevsetAliasDeclaration::Function(name, params))
} else {
Err(RevsetParseError::with_span(
RevsetParseErrorKind::RedefinedFunctionParameter,
params_span,
))
}
}
r => panic!("unexpected alias declaration rule {r:?}"),
}
}
}
/// Borrowed reference to identify alias expression.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum RevsetAliasId<'a> {
Symbol(&'a str),
Function(&'a str),
}
impl fmt::Display for RevsetAliasId<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RevsetAliasId::Symbol(name) => write!(f, "{name}"),
RevsetAliasId::Function(name) => write!(f, "{name}()"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ParseState<'a> {
function_map: &'a HashMap<&'static str, RevsetFunction>,

View file

@ -14,9 +14,11 @@
#![allow(missing_docs)]
use std::collections::HashSet;
use std::error;
use std::collections::{HashMap, HashSet};
use std::{error, fmt};
use itertools::Itertools as _;
use pest::Parser;
use pest_derive::Parser;
use thiserror::Error;
@ -236,3 +238,100 @@ fn rename_rules_in_pest_error(mut err: pest::error::Error<Rule>) -> pest::error:
.unwrap_or_else(|| format!("<{rule:?}>"))
})
}
#[derive(Clone, Debug, Default)]
pub struct RevsetAliasesMap {
symbol_aliases: HashMap<String, String>,
// TODO: remove pub(super)
pub(super) function_aliases: HashMap<String, (Vec<String>, String)>,
}
impl RevsetAliasesMap {
pub fn new() -> Self {
Self::default()
}
/// Adds new substitution rule `decl = defn`.
///
/// Returns error if `decl` is invalid. The `defn` part isn't checked. A bad
/// `defn` will be reported when the alias is substituted.
pub fn insert(
&mut self,
decl: impl AsRef<str>,
defn: impl Into<String>,
) -> Result<(), RevsetParseError> {
match RevsetAliasDeclaration::parse(decl.as_ref())? {
RevsetAliasDeclaration::Symbol(name) => {
self.symbol_aliases.insert(name, defn.into());
}
RevsetAliasDeclaration::Function(name, params) => {
self.function_aliases.insert(name, (params, defn.into()));
}
}
Ok(())
}
pub fn get_symbol(&self, name: &str) -> Option<&str> {
self.symbol_aliases.get(name).map(|defn| defn.as_ref())
}
pub fn get_function(&self, name: &str) -> Option<(&[String], &str)> {
self.function_aliases
.get(name)
.map(|(params, defn)| (params.as_ref(), defn.as_ref()))
}
}
/// Parsed declaration part of alias rule.
#[derive(Clone, Debug)]
enum RevsetAliasDeclaration {
Symbol(String),
Function(String, Vec<String>),
}
impl RevsetAliasDeclaration {
fn parse(source: &str) -> Result<Self, RevsetParseError> {
let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?;
let first = pairs.next().unwrap();
match first.as_rule() {
Rule::identifier => Ok(RevsetAliasDeclaration::Symbol(first.as_str().to_owned())),
Rule::function_name => {
let name = first.as_str().to_owned();
let params_pair = pairs.next().unwrap();
let params_span = params_pair.as_span();
let params = params_pair
.into_inner()
.map(|pair| match pair.as_rule() {
Rule::identifier => pair.as_str().to_owned(),
r => panic!("unexpected formal parameter rule {r:?}"),
})
.collect_vec();
if params.iter().all_unique() {
Ok(RevsetAliasDeclaration::Function(name, params))
} else {
Err(RevsetParseError::with_span(
RevsetParseErrorKind::RedefinedFunctionParameter,
params_span,
))
}
}
r => panic!("unexpected alias declaration rule {r:?}"),
}
}
}
/// Borrowed reference to identify alias expression.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum RevsetAliasId<'a> {
Symbol(&'a str),
Function(&'a str),
}
impl fmt::Display for RevsetAliasId<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RevsetAliasId::Symbol(name) => write!(f, "{name}"),
RevsetAliasId::Function(name) => write!(f, "{name}()"),
}
}
}