Skip to content

Commit

Permalink
Some tests for user-defined meta rules that accept some PEGs as argum…
Browse files Browse the repository at this point in the history
…ents. (#14)

* CI: enable benchmarks on pushes to all branches

* CI: update names and add a few comments.

* Add a test for meta rules.

* CI: enable impact analysis of codecov.

* Update the test for meta rules.

* Update documents about meta rules.
  • Loading branch information
TheVeryDarkness authored Jun 16, 2024
1 parent b597196 commit 53d8839
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 7 deletions.
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(())
}

0 comments on commit 53d8839

Please sign in to comment.