Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some tests for user-defined meta rules that accept some PEGs as arguments. #14

Merged
merged 6 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
on:
push:
branches:
- main
- add-ci # Temporarily used for CI tests.
- "*" # Run benchmarks on all branches.

name: Benchmark

Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ name: Build, Lint and Test

jobs:
check:
name: Rust project
name: Checking
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@v1
with:
toolchain: 1.74
components: rustfmt, clippy
- name: cargo fmt
run: cargo fmt --all -- --check
- name: cargo clippy
# Add `-Dwarnings` when it's time.
run: cargo clippy --workspace --all-targets # -- -Dwarnings
- name: cargo test
run: cargo test --workspace
Expand All @@ -27,23 +28,25 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Rust toolchain
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@v1
with:
toolchain: 1.74
components: llvm-tools-preview, rustfmt
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
- name: Generate Code Coverage
run: cargo llvm-cov --workspace --lcov --output-path lcov.info
- name: Upload Results to Codecov
uses: codecov/codecov-action@v3
with:
file: lcov.info
flags: unittests
name: pest3-ci-coverage
# Failing to upload results will cause a CI error.
# So remember to use a token.
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
3 changes: 3 additions & 0 deletions codedov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
comment:
layout: "diff,flags,tree,betaprofiling"
show_critical_paths: true
45 changes: 45 additions & 0 deletions derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,49 @@
//! Derive macros implemented with [pest3_generator].
//!
//! ## Code Generation
//!
//! ### Meta Rules
//!
//! Rules can have several arguments.
//!
//! Definitions of these rules can use these arguments,
//! and these rules will be mapped to a struct in Rust using generics.
//!
//! ```rust
//! use pest3_derive::Parser;
//! use pest3::typed::TypedNode;
//!
//! #[derive(Parser)]
//! #[grammar_inline = r#"
//! pair(a, b) = a - " "* - ":" - " "* - b
//! string = "\"" - ('a'..'z' | 'A'..'Z' | '0'..'9')* - "\""
//! main = pair(string, string)
//! "#]
//! struct Parser;
//!
//! fn main() -> anyhow::Result<()> {
//! use rules::*;
//! pair::<string, string>::check(r#""a": "b""#)?;
//! Ok(())
//! }
//! ```
//!
//! Once called with some exact parameters,
//! these arguments are replaced directly as a whole.
//!
//! In the example above,
//! `pair(string, string)` has the same structure with
//! `string - " "* - ":" - " "* - string`.
//!
//! But there are some restrictions on meta rules:
//!
//! - All arguments must be used.
//! I think there is no reason in pest for one to define an argument
//! that won't be used, at least for now.
//!
//! And later we may support constant arguments
//! just like the built-in rule `pest::stack::peek`.

#![warn(rust_2018_idioms, rust_2021_compatibility, missing_docs)]

use proc_macro::TokenStream;
Expand Down
42 changes: 42 additions & 0 deletions derive/tests/meta_rules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use anyhow::Result;
use pest3::typed::TypedParser;
use pest3_derive::Parser;
use serde_json::{json, Value};
use std::iter::once;

#[derive(Parser)]
#[grammar_inline = r#"
separated(i, sep) = i - (sep - i)*
cell = ('a'..'z' | 'A'..'Z' | '0'..'9' | ".")+
main = separated(separated(cell, " "* - "," - " "*), "\n")
"#]
struct Parser;

fn to_json(input: &str) -> Result<Value> {
let file = Parser::try_parse::<rules::main>(input)?;
let (first, following) = file.separated().i();
let lines = once(first).chain(following);
let lines = lines.map(|line| {
let (first, following) = line.i();
let cells = once(first).chain(following);
let cells = cells.map(|cell| Value::String(cell.span.as_str().to_owned()));
Value::Array(cells.collect())
});
let res = Value::Array(lines.collect());
Ok(res)
}

#[test]
fn main() -> Result<()> {
assert_eq!(to_json("123,456")?, json!([["123", "456"]]));
assert_eq!(
to_json("123,456\n789,abc")?,
json!([["123", "456"], ["789", "abc"]])
);
assert!(to_json("").is_err());
assert!(to_json("123,").is_err());
assert!(to_json("123,456,").is_err());
assert!(to_json("123\n").is_err());
assert!(to_json("123,\n456").is_err());
Ok(())
}