From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/pest/tests/calculator.rs | 201 +++++++++++++++++ vendor/pest/tests/json.rs | 465 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 666 insertions(+) create mode 100644 vendor/pest/tests/calculator.rs create mode 100644 vendor/pest/tests/json.rs (limited to 'vendor/pest/tests') diff --git a/vendor/pest/tests/calculator.rs b/vendor/pest/tests/calculator.rs new file mode 100644 index 000000000..b78ee0d27 --- /dev/null +++ b/vendor/pest/tests/calculator.rs @@ -0,0 +1,201 @@ +// pest. The Elegant Parser +// Copyright (c) 2018 DragoČ™ Tiselice +// +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +#[macro_use] +extern crate pest; + +use pest::error::Error; +use pest::iterators::{Pair, Pairs}; +use pest::prec_climber::{Assoc, Operator, PrecClimber}; +use pest::{state, ParseResult, Parser, ParserState}; + +#[allow(dead_code, non_camel_case_types)] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +enum Rule { + expression, + primary, + number, + plus, + minus, + times, + divide, + modulus, + power, +} + +struct CalculatorParser; + +impl Parser for CalculatorParser { + fn parse(rule: Rule, input: &str) -> Result, Error> { + fn expression(state: Box>) -> ParseResult>> { + state.rule(Rule::expression, |s| { + s.sequence(|s| { + primary(s).and_then(|s| { + s.repeat(|s| { + s.sequence(|s| { + plus(s) + .or_else(|s| minus(s)) + .or_else(|s| times(s)) + .or_else(|s| divide(s)) + .or_else(|s| modulus(s)) + .or_else(|s| power(s)) + .and_then(|s| primary(s)) + }) + }) + }) + }) + }) + } + + fn primary(state: Box>) -> ParseResult>> { + state + .sequence(|s| { + s.match_string("(") + .and_then(|s| expression(s)) + .and_then(|s| s.match_string(")")) + }) + .or_else(|s| number(s)) + } + + fn number(state: Box>) -> ParseResult>> { + state.rule(Rule::number, |s| { + s.sequence(|s| { + s.optional(|s| s.match_string("-")).and_then(|s| { + s.match_string("0").or_else(|s| { + s.sequence(|s| { + s.match_range('1'..'9') + .and_then(|s| s.repeat(|s| s.match_range('0'..'9'))) + }) + }) + }) + }) + }) + } + + fn plus(state: Box>) -> ParseResult>> { + state.rule(Rule::plus, |s| s.match_string("+")) + } + + fn minus(state: Box>) -> ParseResult>> { + state.rule(Rule::minus, |s| s.match_string("-")) + } + + fn times(state: Box>) -> ParseResult>> { + state.rule(Rule::times, |s| s.match_string("*")) + } + + fn divide(state: Box>) -> ParseResult>> { + state.rule(Rule::divide, |s| s.match_string("/")) + } + + fn modulus(state: Box>) -> ParseResult>> { + state.rule(Rule::modulus, |s| s.match_string("%")) + } + + fn power(state: Box>) -> ParseResult>> { + state.rule(Rule::power, |s| s.match_string("^")) + } + + state(input, |state| match rule { + Rule::expression => expression(state), + _ => unreachable!(), + }) + } +} + +fn consume<'i>(pair: Pair<'i, Rule>, climber: &PrecClimber) -> i32 { + let primary = |pair| consume(pair, climber); + let infix = |lhs: i32, op: Pair, rhs: i32| match op.as_rule() { + Rule::plus => lhs + rhs, + Rule::minus => lhs - rhs, + Rule::times => lhs * rhs, + Rule::divide => lhs / rhs, + Rule::modulus => lhs % rhs, + Rule::power => lhs.pow(rhs as u32), + _ => unreachable!(), + }; + + match pair.as_rule() { + Rule::expression => climber.climb(pair.into_inner(), primary, infix), + Rule::number => pair.as_str().parse().unwrap(), + _ => unreachable!(), + } +} + +#[test] +fn number() { + parses_to! { + parser: CalculatorParser, + input: "-12", + rule: Rule::expression, + tokens: [ + expression(0, 3, [ + number(0, 3) + ]) + ] + }; +} + +#[test] +fn parens() { + parses_to! { + parser: CalculatorParser, + input: "((-12))", + rule: Rule::expression, + tokens: [ + expression(0, 7, [ + expression(1, 6, [ + expression(2, 5, [ + number(2, 5) + ]) + ]) + ]) + ] + }; +} + +#[test] +fn expression() { + parses_to! { + parser: CalculatorParser, + input: "-12+3*(4-9)^7^2", + rule: Rule::expression, + tokens: [ + expression(0, 15, [ + number(0, 3), + plus(3, 4), + number(4, 5), + times(5, 6), + expression(7, 10, [ + number(7, 8), + minus(8, 9), + number(9, 10) + ]), + power(11, 12), + number(12, 13), + power(13, 14), + number(14, 15) + ]) + ] + }; +} + +#[test] +fn prec_climb() { + let climber = PrecClimber::new(vec![ + Operator::new(Rule::plus, Assoc::Left) | Operator::new(Rule::minus, Assoc::Left), + Operator::new(Rule::times, Assoc::Left) + | Operator::new(Rule::divide, Assoc::Left) + | Operator::new(Rule::modulus, Assoc::Left), + Operator::new(Rule::power, Assoc::Right), + ]); + + let pairs = CalculatorParser::parse(Rule::expression, "-12+3*(4-9)^3^2/9%7381"); + assert_eq!(-1_525, consume(pairs.unwrap().next().unwrap(), &climber)); +} diff --git a/vendor/pest/tests/json.rs b/vendor/pest/tests/json.rs new file mode 100644 index 000000000..84906258a --- /dev/null +++ b/vendor/pest/tests/json.rs @@ -0,0 +1,465 @@ +// pest. The Elegant Parser +// Copyright (c) 2018 DragoČ™ Tiselice +// +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +#[macro_use] +extern crate pest; + +use std::collections::HashMap; + +use pest::error::Error; +use pest::iterators::{Pair, Pairs}; +use pest::{state, ParseResult, Parser, ParserState, Span}; + +#[allow(dead_code, non_camel_case_types)] +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +enum Rule { + json, + object, + pair, + array, + value, + string, + escape, + unicode, + hex, + number, + int, + exp, + bool, + null, +} + +struct JsonParser; + +impl Parser for JsonParser { + fn parse(rule: Rule, input: &str) -> Result, Error> { + fn json(state: Box>) -> ParseResult>> { + value(state) + } + + fn object(state: Box>) -> ParseResult>> { + state.rule(Rule::object, |s| { + s.sequence(|s| { + s.match_string("{") + .and_then(|s| skip(s)) + .and_then(|s| pair(s)) + .and_then(|s| skip(s)) + .and_then(|s| { + s.repeat(|s| { + s.sequence(|s| { + s.match_string(",") + .and_then(|s| skip(s)) + .and_then(|s| pair(s)) + .and_then(|s| skip(s)) + }) + }) + }) + .and_then(|s| s.match_string("}")) + }) + .or_else(|s| { + s.sequence(|s| { + s.match_string("{") + .and_then(|s| skip(s)) + .and_then(|s| s.match_string("}")) + }) + }) + }) + } + + fn pair(state: Box>) -> ParseResult>> { + state.rule(Rule::pair, |s| { + s.sequence(|s| { + string(s) + .and_then(|s| skip(s)) + .and_then(|s| s.match_string(":")) + .and_then(|s| skip(s)) + .and_then(|s| value(s)) + }) + }) + } + + fn array(state: Box>) -> ParseResult>> { + state.rule(Rule::array, |s| { + s.sequence(|s| { + s.match_string("[") + .and_then(|s| skip(s)) + .and_then(|s| value(s)) + .and_then(|s| skip(s)) + .and_then(|s| { + s.repeat(|s| { + s.sequence(|s| { + s.match_string(",") + .and_then(|s| skip(s)) + .and_then(|s| value(s)) + .and_then(|s| skip(s)) + }) + }) + }) + .and_then(|s| s.match_string("]")) + }) + .or_else(|s| { + s.sequence(|s| { + s.match_string("[") + .and_then(|s| skip(s)) + .and_then(|s| s.match_string("]")) + }) + }) + }) + } + + fn value(state: Box>) -> ParseResult>> { + state.rule(Rule::value, |s| { + string(s) + .or_else(|s| number(s)) + .or_else(|s| object(s)) + .or_else(|s| array(s)) + .or_else(|s| bool(s)) + .or_else(|s| null(s)) + }) + } + + fn string(state: Box>) -> ParseResult>> { + state.rule(Rule::string, |s| { + s.match_string("\"") + .and_then(|s| { + s.repeat(|s| { + escape(s).or_else(|s| { + s.sequence(|s| { + s.lookahead(false, |s| { + s.match_string("\"").or_else(|s| s.match_string("\\")) + }) + .and_then(|s| s.skip(1)) + }) + }) + }) + }) + .and_then(|pos| pos.match_string("\"")) + }) + } + + fn escape(state: Box>) -> ParseResult>> { + state.sequence(|s| { + s.match_string("\\").and_then(|s| { + s.match_string("\"") + .or_else(|s| s.match_string("\\")) + .or_else(|s| s.match_string("/")) + .or_else(|s| s.match_string("b")) + .or_else(|s| s.match_string("f")) + .or_else(|s| s.match_string("n")) + .or_else(|s| s.match_string("r")) + .or_else(|s| s.match_string("t")) + .or_else(|s| unicode(s)) + }) + }) + } + + fn unicode(state: Box>) -> ParseResult>> { + state.sequence(|s| { + s.match_string("u") + .and_then(|s| hex(s)) + .and_then(|s| hex(s)) + .and_then(|s| hex(s)) + }) + } + + fn hex(state: Box>) -> ParseResult>> { + state + .match_range('0'..'9') + .or_else(|s| s.match_range('a'..'f')) + .or_else(|s| s.match_range('A'..'F')) + } + + fn number(state: Box>) -> ParseResult>> { + state.rule(Rule::number, |s| { + s.sequence(|s| { + s.optional(|s| s.match_string("-")) + .and_then(|s| int(s)) + .and_then(|s| { + s.optional(|s| { + s.sequence(|s| { + s.match_string(".") + .and_then(|s| s.match_range('0'..'9')) + .and_then(|s| s.repeat(|s| s.match_range('0'..'9'))) + .and_then(|s| s.optional(|s| exp(s))) + .or_else(|s| exp(s)) + }) + }) + }) + }) + }) + } + + fn int(state: Box>) -> ParseResult>> { + state.match_string("0").or_else(|s| { + s.sequence(|s| { + s.match_range('1'..'9') + .and_then(|s| s.repeat(|s| s.match_range('0'..'9'))) + }) + }) + } + + fn exp(state: Box>) -> ParseResult>> { + state.sequence(|s| { + s.match_string("E") + .or_else(|s| s.match_string("e")) + .and_then(|s| { + s.optional(|s| s.match_string("+").or_else(|s| s.match_string("-"))) + }) + .and_then(|s| int(s)) + }) + } + + fn bool(state: Box>) -> ParseResult>> { + state.rule(Rule::bool, |s| { + s.match_string("true").or_else(|s| s.match_string("false")) + }) + } + + fn null(state: Box>) -> ParseResult>> { + state.rule(Rule::null, |s| s.match_string("null")) + } + + fn skip(state: Box>) -> ParseResult>> { + state.repeat(|s| { + s.match_string(" ") + .or_else(|s| s.match_string("\t")) + .or_else(|s| s.match_string("\r")) + .or_else(|s| s.match_string("\n")) + }) + } + + state(input, |state| match rule { + Rule::json => json(state), + Rule::object => object(state), + Rule::pair => pair(state), + Rule::array => array(state), + Rule::value => value(state), + Rule::string => string(state), + Rule::escape => escape(state), + Rule::unicode => unicode(state), + Rule::hex => hex(state), + Rule::number => number(state), + Rule::int => int(state), + Rule::exp => exp(state), + Rule::bool => bool(state), + Rule::null => null(state), + }) + } +} + +#[derive(Debug, PartialEq)] +enum Json<'i> { + Null, + Bool(bool), + Number(f64), + String(Span<'i>), + Array(Vec>), + Object(HashMap, Json<'i>>), +} + +fn consume(pair: Pair) -> Json { + fn value(pair: Pair) -> Json { + let pair = pair.into_inner().next().unwrap(); + + match pair.as_rule() { + Rule::null => Json::Null, + Rule::bool => match pair.as_str() { + "false" => Json::Bool(false), + "true" => Json::Bool(true), + _ => unreachable!(), + }, + Rule::number => Json::Number(pair.as_str().parse().unwrap()), + Rule::string => Json::String(pair.as_span()), + Rule::array => Json::Array(pair.into_inner().map(value).collect()), + Rule::object => { + let pairs = pair.into_inner().map(|pos| { + let mut pair = pos.into_inner(); + + let key = pair.next().unwrap().as_span(); + let value = value(pair.next().unwrap()); + + (key, value) + }); + + Json::Object(pairs.collect()) + } + _ => unreachable!(), + } + } + + value(pair) +} + +#[test] +fn null() { + parses_to! { + parser: JsonParser, + input: "null", + rule: Rule::null, + tokens: [ + null(0, 4) + ] + }; +} + +#[test] +fn bool() { + parses_to! { + parser: JsonParser, + input: "false", + rule: Rule::bool, + tokens: [ + bool(0, 5) + ] + }; +} + +#[test] +fn number_zero() { + parses_to! { + parser: JsonParser, + input: "0", + rule: Rule::number, + tokens: [ + number(0, 1) + ] + }; +} + +#[test] +fn float() { + parses_to! { + parser: JsonParser, + input: "100.001", + rule: Rule::number, + tokens: [ + number(0, 7) + ] + }; +} + +#[test] +fn float_with_exp() { + parses_to! { + parser: JsonParser, + input: "100.001E+100", + rule: Rule::number, + tokens: [ + number(0, 12) + ] + }; +} + +#[test] +fn number_minus_zero() { + parses_to! { + parser: JsonParser, + input: "-0", + rule: Rule::number, + tokens: [ + number(0, 2) + ] + }; +} + +#[test] +fn string_with_escapes() { + parses_to! { + parser: JsonParser, + input: "\"asd\\u0000\\\"\"", + rule: Rule::string, + tokens: [ + string(0, 13) + ] + }; +} + +#[test] +fn array_empty() { + parses_to! { + parser: JsonParser, + input: "[ ]", + rule: Rule::array, + tokens: [ + array(0, 3) + ] + }; +} + +#[test] +fn array() { + parses_to! { + parser: JsonParser, + input: "[0.0e1, false, null, \"a\", [0]]", + rule: Rule::array, + tokens: [ + array(0, 30, [ + value(1, 6, [number(1, 6)]), + value(8, 13, [bool(8, 13)]), + value(15, 19, [null(15, 19)]), + value(21, 24, [string(21, 24)]), + value(26, 29, [ + array(26, 29, [ + value(27, 28, [number(27, 28)]) + ]) + ]) + ]) + ] + }; +} + +#[test] +fn object() { + parses_to! { + parser: JsonParser, + input: "{\"a\" : 3, \"b\" : [{}, 3]}", + rule: Rule::object, + tokens: [ + object(0, 24, [ + pair(1, 8, [ + string(1, 4), + value(7, 8, [number(7, 8)]) + ]), + pair(10, 23, [ + string(10, 13), + value(16, 23, [ + array(16, 23, [ + value(17, 19, [object(17, 19)]), + value(21, 22, [number(21, 22)]) + ]) + ]) + ]) + ]) + ] + }; +} + +#[test] +fn ast() { + let input = "{\"a\": [null, true, 3.4]}"; + + let ast = consume( + JsonParser::parse(Rule::json, input) + .unwrap() + .next() + .unwrap(), + ); + + match ast { + Json::Object(pairs) => { + let vals: Vec<&Json> = pairs.values().collect(); + + assert_eq!( + **vals.get(0).unwrap(), + Json::Array(vec![Json::Null, Json::Bool(true), Json::Number(3.4)]) + ); + } + _ => {} + } +} -- cgit v1.2.3