mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
dsl_util: extract helper that parses string literal with \-escapes
The top-level assertion is removed since it's now obvious that the pair represents a Rule::string_literal.
This commit is contained in:
parent
46b4c68325
commit
274183fa66
3 changed files with 60 additions and 24 deletions
|
@ -16,6 +16,7 @@ use std::collections::HashMap;
|
|||
use std::{error, fmt, mem};
|
||||
|
||||
use itertools::Itertools as _;
|
||||
use jj_lib::dsl_util::StringLiteralParser;
|
||||
use once_cell::sync::Lazy;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
use pest::pratt_parser::{Assoc, Op, PrattParser};
|
||||
|
@ -27,6 +28,11 @@ use thiserror::Error;
|
|||
#[grammar = "template.pest"]
|
||||
struct TemplateParser;
|
||||
|
||||
const STRING_LITERAL_PARSER: StringLiteralParser<Rule> = StringLiteralParser {
|
||||
content_rule: Rule::string_content,
|
||||
escape_rule: Rule::string_escape,
|
||||
};
|
||||
|
||||
impl Rule {
|
||||
fn to_symbol(self) -> Option<&'static str> {
|
||||
match self {
|
||||
|
@ -314,29 +320,6 @@ fn parse_identifier_name(pair: Pair<Rule>) -> TemplateParseResult<&str> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_string_literal(pair: Pair<Rule>) -> String {
|
||||
assert_eq!(pair.as_rule(), Rule::string_literal);
|
||||
let mut result = String::new();
|
||||
for part in pair.into_inner() {
|
||||
match part.as_rule() {
|
||||
Rule::string_content => {
|
||||
result.push_str(part.as_str());
|
||||
}
|
||||
Rule::string_escape => match &part.as_str()[1..] {
|
||||
"\"" => result.push('"'),
|
||||
"\\" => result.push('\\'),
|
||||
"t" => result.push('\t'),
|
||||
"r" => result.push('\r'),
|
||||
"n" => result.push('\n'),
|
||||
"0" => result.push('\0'),
|
||||
char => panic!("invalid escape: \\{char:?}"),
|
||||
},
|
||||
_ => panic!("unexpected part of string: {part:?}"),
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn parse_formal_parameters(params_pair: Pair<Rule>) -> TemplateParseResult<Vec<&str>> {
|
||||
assert_eq!(params_pair.as_rule(), Rule::formal_parameters);
|
||||
let params_span = params_pair.as_span();
|
||||
|
@ -397,7 +380,7 @@ fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
|
|||
let span = expr.as_span();
|
||||
let primary = match expr.as_rule() {
|
||||
Rule::string_literal => {
|
||||
let text = parse_string_literal(expr);
|
||||
let text = STRING_LITERAL_PARSER.parse(expr.into_inner());
|
||||
ExpressionNode::new(ExpressionKind::String(text), span)
|
||||
}
|
||||
Rule::integer_literal => {
|
||||
|
|
52
lib/src/dsl_util.rs
Normal file
52
lib/src/dsl_util.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2020-2024 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Domain-specific language helpers.
|
||||
|
||||
use pest::iterators::Pairs;
|
||||
use pest::RuleType;
|
||||
|
||||
/// Helper to parse string literal.
|
||||
#[derive(Debug)]
|
||||
pub struct StringLiteralParser<R> {
|
||||
/// String content part.
|
||||
pub content_rule: R,
|
||||
/// Escape sequence part including backslash character.
|
||||
pub escape_rule: R,
|
||||
}
|
||||
|
||||
impl<R: RuleType> StringLiteralParser<R> {
|
||||
/// Parses the given string literal `pairs` into string.
|
||||
pub fn parse(&self, pairs: Pairs<R>) -> String {
|
||||
let mut result = String::new();
|
||||
for part in pairs {
|
||||
if part.as_rule() == self.content_rule {
|
||||
result.push_str(part.as_str());
|
||||
} else if part.as_rule() == self.escape_rule {
|
||||
match &part.as_str()[1..] {
|
||||
"\"" => result.push('"'),
|
||||
"\\" => result.push('\\'),
|
||||
"t" => result.push('\t'),
|
||||
"r" => result.push('\r'),
|
||||
"n" => result.push('\n'),
|
||||
"0" => result.push('\0'),
|
||||
char => panic!("invalid escape: \\{char:?}"),
|
||||
}
|
||||
} else {
|
||||
panic!("unexpected part of string: {part:?}");
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ pub mod dag_walk;
|
|||
pub mod default_index;
|
||||
pub mod default_submodule_store;
|
||||
pub mod diff;
|
||||
pub mod dsl_util;
|
||||
pub mod extensions_map;
|
||||
pub mod file_util;
|
||||
pub mod files;
|
||||
|
|
Loading…
Reference in a new issue