#language #regex #cli-tool #phone #validation #conlang

bin+lib phonet

用于验证构建语言音位学模式的 CLI 工具和库

12 个版本 (3 个稳定版)

1.0.2 2023 年 3 月 13 日
1.0.0 2023 年 2 月 28 日
0.9.6 2023 年 2 月 28 日
0.8.1 2023 年 2 月 7 日
0.8.0 2023 年 1 月 31 日

#1515 in 命令行工具

MIT 许可证

95KB
1.5K SLoC

Phonet

Phonet 是一个用于验证构建语言音位学模式的 CLI 工具和库。它兼容罗马化和音标转录。可以随机生成单词(参见 参数语法)。

VSCode 语法高亮扩展

用法

此项目可以作为 rust 库 crate 或二进制可执行文件使用。

二进制使用

在此下载最新版本

参数语法

Clap 生成

Usage: phonet.exe [OPTIONS] [TESTS]...

Arguments:
  [TESTS]...
          Custom tests (optional)

          This overrides all tests in the file

Options:
  -f, --file <FILE>
          Name and path of file to run and test

          If name ends with a period, the 'phonet' extension is implied

          Eg. `phonet -f myfile.phonet` or `phonet -f myfile.` (same result)

          If name ends with a slash, the '/phonet' file name is implied

          Eg. `phonet -f folder/phonet` or `phonet -f folder/` (same result)

          [default: phonet]

  -q, --quiet
          Don't display passes and notes, only fails

  -m, --minify
          Minify file and save

  -w, --with-tests
          Include tests in minified file

  -g, --generate [<GENERATE>]
          Generate random words

          Default count 1, specify with number

      --gmin <GENERATE_MIN_LEN>
          Set minimum length (inclusive) for generated words

          Use with the `--generate` or `-g` flag

          Note: This increases generation time exponentially

          [default: 3]

      --gmax <GENERATE_MAX_LEN>
          Set maximum length (inclusive) for generated words

          Use with the `--generate` or `-g` flag

          [default: 20]

  -n, --no-color
          Display output in default color

          Use for piping standard output to a file

  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version

示例

# Runs ./phonet
phonet

# Runs ./phonet, with tests: 'some', 'tests' (overrides the tests in file)
phonet some tests

# Runs ./myfile.phonet
phonet -f myfile.phonet
phonet -f myfile.phonet some tests

# 'phonet' extension implied
phonet -f myfile.

# 'phonet' filename implied
phonet -f src/phonet
phonet -f src/

# Runs ./phonet, only showing fails
phonet -q

# Runs ./phonet, and minifies to ./min.phonet without tests
phonet -m

# Runs ./myfile.phonet, only displaying fails, and minifies to ./myfile.min.phonet with tests
phonet -f myfile. -q -mw

# Runs ./phonet, and generates 1 random word
phonet -g

# Runs ./myfile.phonet, and generates 10 random words
phonet -g10 -f myfile.phonet

# Runs ./phonet, with no color, and writes output to ./phonet.txt
phonet -n > phonet.txt

# Runs ./myfile.phonet, only displaying fails, and generates 3 random words with length 6-8, writes output to ./phonet.txt (with no color)
phonet -f myfile. -qn -g 3 --gmin 6 --gmax 8 > ./phonet.txt

创建别名/路径

<path_to_file> 替换为下载的二进制文件的目录。

Bash

在用户目录下的 .bashrc 中添加别名

# ~/.bashrc
alias phonet="<path_to_file>/phonet.exe"

Powershell

添加到 $env:PATH

$env:Path = "$env:Path;<path_to_file>\phonet.exe"

库使用

phonet = "1.0.2" 添加到您的 Crates.toml 文件

简例

use phonet::Draft;

fn main() {
    let file = std::fs::read_to_string("phonet").unwrap();

    // Parse draft
    Draft::from(&file).unwrap()
        // Run tests
        .run()
        // Display results
        .display(Default::default(), true)
}

长例

use std::fs;

use phonet::{
    draft::{Message::Test, TestDraft},
    get_min_filename, DisplayLevel, Draft,
};

fn main() {
    let filename = "myfile.phonet";

    // Read file
    let file = fs::read_to_string(filename).expect("Could not read phonet file");

    // Parse file
    let mut draft = Draft::from(&file).expect("Failed to parse file");

    // Add a custom test
    draft.messages.push(Test(TestDraft {
        intent: true,
        word: "taso".to_string(),
    }));

    // Minify file
    fs::write(
        get_min_filename(filename),
        draft.minify(false).expect("Failed to minify"),
    )
    .expect("Could not write minified file");

    // Run tests and display only failed tests
    draft.run().display(DisplayLevel::OnlyFails, true);

    // Create a generator for random words
    // Each with a length between 5 and 8 (inclusive)
    // Generation is done lazily, similar to an iterator
    println!("Randomly generated words:");
    let mut words = draft
        .generator(5..=8)
        .expect("Failed to create word generator");

    // Generate 10 random words
    for _ in 0..10 {
        println!(" - {}", words.next());
    }
}

文件语法

一个 Phonet 文件用于定义程序的规则、类和测试。

该文件应命名为 phonet,或以 .phonet 结尾。

VSCode 语法高亮扩展

语句

语法是语句,每个语句由分号 ; 或换行符分隔。

使用 Ampersand & 表示多行语句。这只能用分号 ; 结束。注意,注释不能多行。

注释将以换行符或分号 ; 结尾

所有空白都将被忽略,除了在 测试 中分隔单词。

注意!这将在正则表达式中也替换空格!如果您需要空格,请使用 \s

每个语句必须以操作符开头

  • # Hashtag:整行注释。换行符(不是分号)结束注释
  • $ 美元符号:定义一个
  • + 加号! 感叹号:定义一个规则
  • * 星号:创建一个测试注释,并在测试失败时定义一个原因
  • ? 问号:创建一个测试
  • ~ 波浪号:定义文件的模式

类用作简写正则表达式,在运行时被替换到规则中。

注意:尖括号将不会直接解析为类名

  • 一个开括号和一个问号:(?
  • 一个开括号、问号和字母 'P':(?P
  • 一个反斜杠和字母 'k':\k

这是用于后视和命名组的语法

语法

  • $ 美元符号
  • 名称 - 只能是 [a-zA-Z0-9_] 中的字符
  • = 等于
  • 值 - 正则表达式,可能包含尖括号 <>⟨⟩ 中的其他(与规则相同)

名为 'any' 的,用 $_ = ... 定义,用于随机单词生成。

示例

# Some consonants
$C = [ptksmn]

# Some vowels
$V = [iueoa]

# Only sibilant consonants
$C_s = [sz]

# Every letter
$_ = ⟨C⟩ | <V>

规则

规则是用于测试单词是否有效的正则表达式。

规则用意图定义,可以是+(表示)或!(表示)。

  • 则必须遵循,单词才有效
  • 则必须遵循,单词才有效

要使用,使用类名,并用尖括号 <>⟨⟩ 包围

语法

  • + 加号! 感叹号 - 加号用于则,感叹号用于
  • 模式 - 正则表达式,可能包含尖括号 <>⟨⟩ 中的

示例(带有预定义

# Must be (C)V syllable structure
+ ^ (<C>? ⟨V⟩)+ $

# Must not have two vowels in a row
! <V>{2}

测试

测试将与所有规则进行比较,并在输出中显示结果。

测试将按照定义的顺序运行。

规则一样,测试必须有一个定义的意图,即+(表示)或!(表示)。

  • 测试在有效时将通过
  • 测试在有效时将失败

语法

  • ? 问号
  • + 加号! 感叹号 - 加号用于测试,感叹号用于测试
  • 测试 - 一个单词,或由空格分隔的多个单词

示例(包含预定义的规则

# This should match, to pass
?+ taso
# This test should NOT match, to pass
?! tax
# Each word is a test, all should match to pass
?+ taso sato tasa

备注

备注将被打印到终端输出,与测试并行。

它们用作任何后续规则的原因,如果测试失败,则作为解释。

语法

  • * 星号
  • : 冒号可选) - 定义一个 '安静' 备注
  • 要打印的文本,以及定义原因

示例

* Syllable structure
+ ^ (<C>? <V>)+ $

# This test will NOT match, however it SHOULD (due to the Plus), so it will FAIL, with the above note as the reason
?+ tasto

# This is a 'quiet' note, it will not display, but it will be used as the reason for the following rule
*: Must not have two vowels in a row
! <V>{2}

?+ taso

模式

Phonet 文件的模式可能是以下之一

  • 罗马化:使用 <> (不是 ⟨⟩
  • 宽式转录:使用 //
  • 窄式转录:使用 []

这可以作为一个文件中的可选指定,尽管它不会添加任何功能。

语法

  • ~ 波浪号
  • <.>/./[.] - 模式标识符,其中 . 是任何字符串或空白

示例

# Specify romanized mode (fish icon)
~<>
# Specify broad transcription, with a given name
~ / My Language /

示例

请参阅示例文件夹中的Phonet文件示例。

这些格式化提示不是必需的,但建议使用,以便使文件更容易阅读。

  1. 在文件最顶部指定模式
  2. 在文件顶部定义所有类
    • 首先定义一个'any',用于单词生成
  3. 使用备注分组相关规则和测试
    • 首先定义规则,然后是正测试,然后是负测试
  4. 在备注下缩进规则和测试
    • 规则应使用 1 个意图,测试使用 2 个

示例文件

示例(这来自example.phonet

~<> ;# Mode (optional) - This file uses romanized letters

# Class definitions
$_ = ⟨C⟩ | ⟨V⟩        ;# Any / all letters (required for generating words)
$C = [ptkmnswjl]      ;# Consonants
$V = [aeiou]          ;# Vowels

* Invalid letters     ;# Note - Prints to standard output, and used as reason if test fails
  + ^_+ $          ;# Check that every letter is in the 'any' class
    ?+ taso
    ?! tyxo

* Examples of failing tests
    ?+ tyxo           ;# This test will fail - with the reason 'Invalid Letters' (above)
    ?! taso           ;# This test will fail, as a false positive

* Syllable structure
  + ^ ⟨V⟩? ( ⟨C⟩ ⟨V⟩ )+ $  ;# Check that word is Consonant + Vowel, repeating at least once
    ?+ taso kili ano atoso
    ?! taaso an

* Some more tests
    ?+ silo tila
    ?! akka axe

# This is a 'quiet' note - It will not display, unless any following rules fail
*: No repeated letters
  ! (.)\1             ;# This is an unnamed back-reference
  ! (?<x> .) \k<x>    ;# (Alternative) This is a named back-reference (NOT a class)
    ?+ taso           ;# An example of multi-line statements on next line (comments cannot be on same line)
    ?! &
      taaso
      ttaso
    ;

# Comments cannot be multiline, even using '&'

* 2 tests *should* have failed!

Phonet Icon

依赖项

~4.5–6.5MB
~113K SLoC