about summary refs log tree commit diff
path: root/utils/parse-syllable.raku
blob: 16deb04c9467ea7073177a7fbe7fa2568a93d852 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Parser for word syllables.
# Copyright (C) 2021 Ngô Ngọc Đức Huy
#
# This file is part of Hàësdáïga utils.
#
# Hàësdáïga utils is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hàësdáïga utils is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hàësdáïga utils.  If not, see <https://www.gnu.org/licenses/>.
use JSON::Tiny;

grammar Syllable {
	token TOP { <onset> <nucleus> <coda> }

	token onset { <consonant>* }
	token nucleus { <first-vowel> <second-vowel>? }
	token coda { <consonant>* }

	token vowel { <[aeiouy]>}
	token rise-vowel { <[áéíóúý]>}
	token fall-vowel { <[àèìòùỳ]>}
	token first-vowel { [ <vowel> | <rise-vowel> | <fall-vowel> ] }
	token second-vowel { [ <vowel> | '~' ] }
	token consonant { <[bcdfghjlmnprstvwz']> }
}

class Parser {
	method nucleus ($/) {
		make ($<first-vowel>.made, $<second-vowel> ??
			$<second-vowel>.made !! Nil).flat
	}
	method first-vowel ($/) {
		make $<rise-vowel> ?? $<rise-vowel>.made !! (
			$<fall-vowel> ?? $<fall-vowel>.made !! $<vowel>.made);
	}
	method rise-vowel ($/) {
		given $/ {
			when 'á' { make ('a', 'rising')}
			when 'é' { make ('e', 'rising')}
			when 'í' { make ('i', 'rising')}
			when 'ó' { make ('o', 'rising')}
			when 'ú' { make ('u', 'rising')}
			when 'ý' { make ('y', 'rising')}
		}
	}
	method fall-vowel ($/) {
		given $/ {
			when 'à' { make ('a', 'falling')}
			when 'è' { make ('e', 'falling')}
			when 'ì' { make ('i', 'falling')}
			when 'ò' { make ('o', 'falling')}
			when 'ù' { make ('u', 'falling')}
			when 'ỳ' { make ('y', 'falling')}
		}
	}
	method vowel ($/) {
		make ($/.words.join, 'level')
	}
	method second-vowel ($/) { make $/.words.join }
	method coda ($/) {make $<consonant> ?? $<consonant>.join !! Nil}
}

sub extras ($char) {
	my %parsing;
	%parsing{"type"} = "punctuation";
	%parsing{"name"} = do given $char {
		when ',' { 'comma' }
		when ':' { 'colon' }
		when '!' { 'exclam' }
		when '(' { 'parenleft' }
		when ')' { 'parenright' }
		when '.' { 'period' }
		when '?' { 'question' }
	};
	return %parsing
}

sub parse-one ($word) {
	if $word<. , ? ! ( ) :> {
		return extras($word);
	}
	if $word eqv '-' {
		my %parsing;
		%parsing{"type"} = "space";
		return %parsing
	}
	my $C1 = Syllable.parse($word)<onset><consonant>.join;
	my $C2 = Syllable.parse(
		$word, actions => Parser)<coda>.made;
	my ($V1, $T, $V2) = Syllable.parse(
		$word, actions => Parser)<nucleus>.made;
	if $V2 eqv '~' { $V2 = 'long' }
	if $C1 eqv "'" { $C1 = 'glottal'}

	my %parsing;
	%parsing{"type"} = "syllable";
	%parsing{"C1"} = $C1;
	%parsing{"C2"} = $C2;
	%parsing{"V1"} = $V1;
	%parsing{"V2"} = $V2;
	%parsing{"T" } = $T ;
	return %parsing
}

sub MAIN ($phrase) {
	my @list;
	for $phrase.words -> $word {
		@list.push(parse-one($word))
	}
	say to-json @list;
}