yaparc 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -11
- data/lib/yaparc.rb +253 -89
- data/tests/abc20bnf.txt +264 -0
- data/tests/test_abc.rb +113 -0
- data/tests/test_calc.rb +10 -5
- data/tests/test_owl.rb +68 -0
- data/tests/test_parser.rb +89 -25
- data/tests/test_sql.rb +10 -10
- data/tests/test_uri.rb +752 -0
- metadata +9 -2
data/tests/abc20bnf.txt
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
; ABC notation 2.0 - BNF specification.
|
2
|
+
; This is a specification of the draft ABC 2.0 standard in BNF.
|
3
|
+
; This BNF specification is not finished yet - it needs to be elaborated in some places.
|
4
|
+
; It uses ABNF as defined in http://www.ietf.org/rfc/rfc2234.txt.
|
5
|
+
; This file written by Henrik Norbeck.
|
6
|
+
; --------------------------------------------------------------------------------
|
7
|
+
abc-file ::= *(abc-tune / comment / xcommand / file-field / text-line / tex)
|
8
|
+
file-field ::= field-area / field-book / field-composer / field-discography / field-file / field-group / field-history / field-length / field-meter / field-notes / field-origin / field-parts / field-tempo / field-rhythm / field-source / field-userdef-print / field-userdef-play / field-words / field-transcription / field-key / unused-field ; Default values for the whole file - all fields except number, title and voice
|
9
|
+
text-line ::= [non-comment-char tex-text] eol ; Free text between tunes. This is a catch-all rule - check for fields first!
|
10
|
+
|
11
|
+
; --------------------------------------------------------------------------------
|
12
|
+
abc-tune ::= abc-header abc-music eol
|
13
|
+
abc-header ::= [field-number] title-fields *other-field field-key ; note that field-number is optional.
|
14
|
+
field-number ::= %x58.3A *WSP 1*DIGIT header-eol ; X:
|
15
|
+
title-fields ::= *(comment / xcommand / tex) 1*(field-title *(comment / xcommand / tex))
|
16
|
+
field-title ::= %x54.3A *WSP tex-text header-eol ; T:
|
17
|
+
other-field ::= field-area / field-book / field-composer / field-discography / field-file / field-group / field-history / field-length / field-meter / field-notes / field-origin / field-parts / field-tempo / field-rhythm / field-source / field-userdef-print / field-userdef-play / field-voice / field-words / field-transcription / field-macro / unused-field / comment / xcommand / tex
|
18
|
+
field-area ::= %x41.3A *WSP tex-text header-eol ; A:
|
19
|
+
field-book ::= %x42.3A *WSP tex-text header-eol ; B:
|
20
|
+
field-composer ::= %x43.3A *WSP tex-text header-eol ; C:
|
21
|
+
field-discography ::= %x44.3A *WSP tex-text header-eol ; D:
|
22
|
+
field-file ::= %x46.3A *WSP tex-text header-eol ; F:
|
23
|
+
field-group ::= %x47.3A *WSP tex-text header-eol ; G:
|
24
|
+
field-history ::= %x48.3A *WSP 1*(tex-text header-eol) ; H: field contents may extend over many lines, which is deprecated (maybe not allowed any longer?)
|
25
|
+
field-length ::= %x4C.3A *WSP note-length-strict header-eol ; L: default note length
|
26
|
+
field-meter ::= %x4D.3A *WSP time-signature header-eol ; M:
|
27
|
+
field-notes ::= %x4E.3A *WSP tex-text header-eol ; N:
|
28
|
+
field-origin ::= %x4F.3A *WSP tex-text header-eol ; O:
|
29
|
+
field-parts ::= %x50.3A *WSP parts-play-order header-eol ; P: in header defines in which order parts should be played
|
30
|
+
field-tempo ::= %x51.3A *WSP tempo header-eol ; Q:
|
31
|
+
field-rhythm ::= %x52.3A *WSP tex-text header-eol ; R:
|
32
|
+
field-source ::= %x53.3A *WSP tex-text header-eol ; S:
|
33
|
+
field-userdef-print ::= %x55.3A *WSP userdef header-eol ; U:
|
34
|
+
field-userdef-play ::= %x75.3A *WSP userdef header-eol ; u:
|
35
|
+
field-voice ::= %x56.3A *WSP voice header-eol ; V: options should be better defined
|
36
|
+
field-words ::= %x57.3A *WSP tex-text header-eol ; W: unformatted words, printed after the tune
|
37
|
+
field-transcription ::= %x5A.3A *WSP tex-text header-eol ; Z:
|
38
|
+
field-macro ::= %x6D.3A *WSP 1*(WSP / VCHAR) header-eol ; m: BarFly-style macros - do be defined better
|
39
|
+
field-key ::= %x4B.3A *WSP key header-eol ; K:
|
40
|
+
unused-field ::= (%x45 / %x49 / %4A / %59 / %61-6c / %6e-%74 / %76 / %78-7A) %3A *(WSP / VCHAR) eol ; E: I: J: Y: a:-l: n:-t: v: x: y: z: ignore - but for backward and forward compatibility
|
41
|
+
|
42
|
+
; --------------------------------------------------------------------------------
|
43
|
+
time-signature ::= %x43 / %x43.7C / "none" / meter-num / 1*DIGIT ; C, C|, none or numeric
|
44
|
+
meter-num ::= (1*DIGIT *("+" 1*DIGIT) "/" 1*DIGIT) [1*SP meter-num]
|
45
|
+
; e.g. 2/4 , 6/8 , 2+2+3/16 , 11/8 , 2/4 3/4 , 2+2+3/8 2+2+3+2+2+2/8
|
46
|
+
tempo ::= (note-length-strict "=" 1*DIGIT) / (%x43 [note-length] "=" 1*DIGIT) / 1*DIGIT ; 1*DIGIT is deprecated, kept for compatibility
|
47
|
+
note-length-strict ::= 1*DIGIT "/" 1*DIGIT
|
48
|
+
key ::= (key-def [1*WSP clef]) / clef / "HP" / "Hp"
|
49
|
+
key-def ::= basenote ["#" / "b"] [mode] *(1*WSP global-accidental)
|
50
|
+
mode ::= minor / major / lydian / ionian / mixolydian / dorian / aeolian / phrygian / locrian
|
51
|
+
minor ::= "m" ["in" ["o" ["r"]]] ; m, min, mino, minor - all modes are case insensitive
|
52
|
+
major ::= "maj" ["o" ["r"]]
|
53
|
+
lydian ::= "lyd" ["i" ["a" ["n"]]] ; major with sharp 4th
|
54
|
+
ionian ::= "ion" ["i" ["a" ["n"]]] ; =major
|
55
|
+
mixolydian ::= "mix" ["o" ["l" ["y" ["d" ["i" ["a" ["n"]]]]]]] ; major with flat 7th
|
56
|
+
dorian ::= "dor" ["i" ["a" ["n"]]] ; minor with sharp 6th
|
57
|
+
aeolian ::= "aeo" ["l" ["i" ["a" ["n"]]]] ; =minor
|
58
|
+
phrygian ::= "phr" ["y" ["g" ["i" ["a" ["n"]]]]] ; minor with flat 2nd
|
59
|
+
locrian ::= "loc" ["r" ["i" ["a" ["n"]]]] ; minor with flat 2nd and 5th
|
60
|
+
global-accidental ::= accidental basenote ; e.g. ^f =c _b
|
61
|
+
parts-play-order ::= 1*( ALPHA / ( "(" parts-play-order ")" ) *DIGIT) / "." ; dots are ignored - for legibility only
|
62
|
+
|
63
|
+
; --------------------------------------------------------------------------------
|
64
|
+
voice ::= 1*(ALPHA / DIGIT) *(1*WSP (clef / voice-name / voice-subname / voice-transpose / "merge" / "up" / "down")) ; maybe "stems=up" / "stems=down" / "stems=normal" instead?
|
65
|
+
voice-name ::= ("name=" / "nm=") %x22 *non-quote %x22 ; \n in name = linefeed
|
66
|
+
voice-subname ::= ("subname=" / "snm=") %x22 *non-quote %x22 ; \n in name = linefeed
|
67
|
+
voice-transpose ::= "transpose=" ["-"] 1*DIGIT
|
68
|
+
|
69
|
+
; --------------------------------------------------------------------------------
|
70
|
+
clef ::= ( ("clef=" (clef-note / clef-name)) / clef-name) clef-line ["+8" / "-8"] [1*WSP clef-middle]
|
71
|
+
clef-note ::= "G" / "C" / "F" / "P"
|
72
|
+
clef-name ::= "treble" / "alto" / "tenor" / "baritone" / "bass" / "mezzo" / "soprano" / "perc" / "none" ; Maybe also Doh1-4, Fa1-4
|
73
|
+
clef-line ::= "1" / "2" / "3" / "4" / "5"
|
74
|
+
cleff-middle ::= "middle=" basenote [octave]
|
75
|
+
|
76
|
+
; --------------------------------------------------------------------------------
|
77
|
+
userdef ::= userdef-symbol *WSP "=" *WSP (long-gracing / chord-or-text)
|
78
|
+
header-eol ::= *WSP (comment / eol) ; there may be comments at the end of header lines
|
79
|
+
|
80
|
+
; --------------------------------------------------------------------------------
|
81
|
+
abc-music ::= *(abc-line / comment / xcommand / tune-field / tex)
|
82
|
+
abc-line ::= barline / ([barline] 1*element *(barline 1*element) [barline]) abc-eol
|
83
|
+
barline ::= ( *":" *"[" 1*"|" *"]" ( *":" / nth-repeat-num ) ) / invisible-barline / dashed-barline ; e.g. :| | |:: |2 :||:
|
84
|
+
invisible-barline ::= "[|]" | "[]"
|
85
|
+
dashed-barline ::= ":"
|
86
|
+
element ::= stem / WSP / chord-or-text / gracing / grace-notes / broken-rhythm / tuplet / slur-begin / slur-end / rollback / multi-measure-rest / measure-repeat / nth-repeat / end-nth-repeat / inline-field / unused-char
|
87
|
+
|
88
|
+
; --------------------------------------------------------------------------------
|
89
|
+
stem ::= note / ( "[" 2*note "]" ) ; stem
|
90
|
+
note ::= pitch [note-length] [tie] ; note
|
91
|
+
pitch ::= [accidental] basenote [octave]
|
92
|
+
rest ::= (normal-rest / invisible-rest / inaudible-rest) [note-length]
|
93
|
+
normal-rest ::= %x7A ; z = normal rest
|
94
|
+
invisible-rest ::= %x78 ; x = invisible rest
|
95
|
+
inaudible-rest ::= %x79 ; y = inaudible and invisible rest, for spacing
|
96
|
+
accidental ::= "^" / "^^" / "_" / "__" / "="
|
97
|
+
basenote ::= %x43 / %x44 / %x45 / %x46 / %x47 / %x41 / %x42 / %x63 / %x64 / %x65 / %x66 / %x67 / %x61 / %x62 ; CDEFGABcdefgab
|
98
|
+
octave ::= 1*"'" / 1*","
|
99
|
+
note-length ::= (*DIGIT ["/" *DIGIT]) / 1*"/"
|
100
|
+
tie ::= "-" ; tie
|
101
|
+
|
102
|
+
; --------------------------------------------------------------------------------
|
103
|
+
broken-rhythm ::= stem *b-elem (1*"<" / 1*">") *b-elem stem
|
104
|
+
b-elem ::= WSP / chord-or-text / gracing / grace-notes / slur-begin / slur-end
|
105
|
+
tuplet ::= "("1*DIGIT [":" [1*DIGIT] ":" [1*DIGIT]] 2*(*t-elem stem)
|
106
|
+
t-elem ::= WSP / chord-or-text / gracing / grace-notes / broken-rhythm / slur-begin / slur-end
|
107
|
+
|
108
|
+
; --------------------------------------------------------------------------------
|
109
|
+
gracing ::= "." / userdef-symbol / long-gracing ; gracings
|
110
|
+
userdef-symbol ::= "~" / %x48-59 / %x68-77 ; user definable symbols ~ H-Y, h-w
|
111
|
+
grace-notes ::= "{" acciaccatura 1*( grace-note-stem ) "}" ; grace notes can have length
|
112
|
+
grace-note-stem ::= grace-note / ( "[" 2*grace-note "]" )
|
113
|
+
grace-note ::= pitch [note-length] ; as note, but without tie
|
114
|
+
acciaccatura ::= "/"
|
115
|
+
|
116
|
+
; --------------------------------------------------------------------------------
|
117
|
+
chord-or-text ::= %x22 (chord / text-expression) *(chord-newline (chord / text-expression)) %x22 ; ".."
|
118
|
+
chord ::= basenote [chord-accidental] [chord-type] ["/" basenote [chord-accidental]] *non-quote
|
119
|
+
chord-accidental ::= "#" / "b" / "="
|
120
|
+
chord-type ::= 1*( ALPHA / DIGIT / "+" / "-" ) ; e.g. m, 7, m7, +, mb5, sus, sus4, maj7, mmaj7, 7sus4, dim
|
121
|
+
text-expression ::= [ "^" / "<" / ">" / "_" / "@" ] 1*non-quote ; above, left, right, below, anywhere
|
122
|
+
non-quote ::= SP / %x21 / %x23-7E ; all characters except quote
|
123
|
+
chord-newline ::= "\n" / ";"
|
124
|
+
|
125
|
+
; --------------------------------------------------------------------------------
|
126
|
+
slur-begin ::= "("
|
127
|
+
slur-end ::= ")"
|
128
|
+
rollback ::= "&"
|
129
|
+
measure-repeat ::= "/" ["/"] ; repeat whole measure
|
130
|
+
multi-measure-rest ::= %5A *DIGIT ; e.g. Z4
|
131
|
+
nth-repeat ::= "[" ( nth-repeat-num / nth-repeat-text )
|
132
|
+
nth-repeat-num ::= 1*DIGIT *(("," / "-") 1*DIGIT)
|
133
|
+
nth-repeat-text ::= %x22 *non-quote %x22
|
134
|
+
end-nth-repeat ::= "]"
|
135
|
+
unused-char ::= "#" / "$" / "*" / "+" / ";" / "?" / "@" / "`" ; ignore for backward and forward compatibility, but maybe warn about them
|
136
|
+
|
137
|
+
; --------------------------------------------------------------------------------
|
138
|
+
inline-field ::= ifield-area / ifield-book / ifield-composer / ifield-discography / ifield-group / ifield-history / ifield-length / ifield-meter / ifield-notes / ifield-origin / ifield-part / ifield-tempo / ifield-rhythm / ifield-source / ifield-title / ifield-voice / ifield-words / ifield-lyrics / ifield-transcription / ifield-key
|
139
|
+
ifield-area ::= %5B.%41.%3A tex-text-ifield %5D ; [A:..]
|
140
|
+
ifield-book ::= %5B.%42.%3A *WSP tex-text-ifield %5D ; [B:..]
|
141
|
+
ifield-composer ::= %5B.%43.%3A *WSP tex-text-ifield %5D ; [C:..]
|
142
|
+
ifield-discography ::= %5B.%44.%3A *WSP tex-text-ifield %5D ; [D:..]
|
143
|
+
ifield-group ::= %5B.%47.%3A *WSP tex-text-ifield %5D ; [G:..]
|
144
|
+
ifield-history ::= %5B.%48.%3A *WSP tex-text-ifield %5D ; [H:..]
|
145
|
+
ifield-length ::= %5B.4C.3A *WSP note-length-strict %5D ; e.g. [L:1/8]
|
146
|
+
ifield-meter ::= %5B.4D.3A *WSP meter %5D ; e.g. [M:C|] [M: 2+3/8]
|
147
|
+
ifield-notes ::= %5B.%4E.%3A *WSP tex-text-ifield %5D ; [N:..]
|
148
|
+
ifield-origin ::= %5B.%4F.%3A *WSP tex-text-ifield %5D ; [O:..]
|
149
|
+
ifield-part ::= %5B.%50.%3A *WSP (ALPHA / tex-text-ifield) %5D ; e.g. [P:A]
|
150
|
+
ifield-tempo ::= %5B.%51.%3A *WSP tempo %5D ; e.g. [Q:1/4=120]
|
151
|
+
ifield-rhythm ::= %5B.%52.%3A *WSP tex-text-ifield %5D ; e.g. [R:reel]
|
152
|
+
ifield-source ::= %5B.%53.%3A *WSP tex-text-ifield %5D ; [S:..]
|
153
|
+
ifield-title ::= %5B.%54.%3A *WSP tex-text-ifield %5D ; e.g. [T:second version]
|
154
|
+
ifield-voice ::= %5B.%56.%3A *WSP voice %5D ; [V:..] options should be better defined
|
155
|
+
ifield-words ::= %5B.%57.%3A *WSP tex-text-ifield %5D ; [W:..]
|
156
|
+
ifield-lyrics ::= %5B.%77.%3A *WSP tex-text-ifield %5D ; [w:..]
|
157
|
+
ifield-transcription ::= %5B.%5A.%3A *WSP tex-text-ifield %5D ; [Z:..]
|
158
|
+
ifield-key ::= %5B.4B.3A *WSP key %5D ; e.g. [K:Ador] [K: Bphr ^d]
|
159
|
+
unused-ifield ::= %5B (%x45 / %x49 / %4A / %59 / %61-6c / %6e-%74 / %76 / %78-7A) %3A *(WSP / VCHAR) %5D ; E: I: J: Y: a:-l: n:-t: v: x: y: z: ignore - but for backward and forward compatibility
|
160
|
+
non-bracket-char ::= *(WSP / %21-%5C / %5E-7E) ; all except ]
|
161
|
+
|
162
|
+
; --------------------------------------------------------------------------------
|
163
|
+
abc-eol ::= comment / ([line-continuation / hard-line-break] *WSP eol)
|
164
|
+
line-continuation ::= "\"
|
165
|
+
hard-line-break ::= "!" ; kept for compatibility with abc2win
|
166
|
+
|
167
|
+
; --------------------------------------------------------------------------------
|
168
|
+
tune-field ::= field-area / field-book / field-composer / field-discography / field-group / field-history / field-length / field-meter / field-notes / field-origin / field-part / field-tempo / field-rhythm / field-source / field-title / field-voice / field-words / field-lyrics / field-transcription / field-key / unused-field
|
169
|
+
field-part ::= %x50.3A *WSP (ALPHA / tex-text) header-eol ; P:
|
170
|
+
field-lyrics ::= %x56.3A *WSP lyrics header-eol ; w: formatted lyrics printed under staff
|
171
|
+
|
172
|
+
; --------------------------------------------------------------------------------
|
173
|
+
long-gracing ::= gracing-grace / gracing-vol / gracing-style / gracing-finger / gracing-phrase / gracing-exec / gracing-other
|
174
|
+
gracing-grace ::= "!trill!" / "!mordent!" / "!lowermordent!" / "!pralltriller!" / "!uppermordent!" / "!turn!" / "!roll!" / "!turnx!" / "!invertedturn!" / "!invertedturnx!" / "!trill(!" / "!trill)!"
|
175
|
+
gracing-vol ::= "!accent!" / "!emphasis!" / "!crescendo(!" / "!crescendo)!" / "!diminuendo(!" / "!diminuendo)!" / "!p!" / "!pp!" / "!ppp!" / "!pppp!" / "!mp!" / "!mf!" / "!fp!" / "!f!" / "!ff!" / "!fff!" / "!ffff!" / "!sfz!" / "!cresc!" / "!decresc!" / "!dimin!"
|
176
|
+
gracing-style ::= "!+!" / "!open!" / "!snap!" / "!upbow!" / "!downbow!" / "!slide!" / "!arpeggio!"
|
177
|
+
gracing-len ::= "!fermata!" / "!invertedfermata!" / "!tenuto!"
|
178
|
+
gracing-finger ::= "!0!" / "!1!" / "!2!" / "!3!" / "!4!" / "!5!"
|
179
|
+
gracing-phrase ::= "!shortphrase!" / "!mediumphrase!" / "!longphrase!"
|
180
|
+
gracing-exec ::= "!segno!" / "!coda!" / "!D.S.!" / "!D.C.!" / "!fine!" / ("!repeatbar" *DIGIT "!")
|
181
|
+
gracing-other ::= "!wedge!" / "!thumb!" / "!breath!" / ("!" 1*(SP / %x22-x7E) "!") ; any text between !! is allowed
|
182
|
+
|
183
|
+
; --------------------------------------------------------------------------------
|
184
|
+
comment ::= "%" ([non-comment-char *(VCHAR / WSP)]) eol
|
185
|
+
non-comment-char ::= %x20-24 / %x26-%x7E / HTAB ; all characters except %
|
186
|
+
xcommand ::= "%%" xcom eol
|
187
|
+
xcom ::= xcom-staff / xcom-measurenb / xcom-text / xcom-layout / xcom-margins / xcom-midi / xcom-other ; more need to be defined
|
188
|
+
xcom-staff ::= xcom-staffbreak / xcom-multicol / xcom-staves / xcom-indent
|
189
|
+
xcom-staffbreak ::= "staffbreak" 1*WSP xcom-number xcom-unit
|
190
|
+
xcom-multicol ::= "multicol" 1*WSP ("start" / "new" / "end")
|
191
|
+
xcom-staves ::= "staves" 1*WSP stave-voice *( bar-staves stave-voice)
|
192
|
+
stave-voice ::= single-voice / bracketed-voice / braced-voice / paren-voice
|
193
|
+
bracketed-voice ::= "[" *WSP (single-voice / braced-voice / paren-voice) 1*(bar-staves (single-voice / braced-voice / paren-voice)) *WSP "]" ; staves joined by bracket
|
194
|
+
braced-voice ::= "{" *WSP (single-voice / paren-voice) 1*(bar-staves (single-voice / paren-voice)) *WSP "}" ; staves joined by brace
|
195
|
+
paren-voice ::= "(" single-voice 1*( 1*WSP single-voice) ")" ; on same staff
|
196
|
+
single-voice ::= 1*(ALPHA / DIGIT)
|
197
|
+
bar-staves ::= (*WSP "|" *WSP) / 1*WSP ; | to not bar
|
198
|
+
xcom-indent ::= "indent" 1*WSP xcom-number xcom-unit
|
199
|
+
xcom-measurenb ::= "measurenb" / "measurebox" / "measurefirst" / ("setbarnb" 1*WSP 1*DIGIT)
|
200
|
+
xcom-text ::= xcom-textline / xcom-textcenter / xcom-textblock
|
201
|
+
xcom-textline ::= "text" 1*WSP tex-text
|
202
|
+
xcom-textcenter ::= "center" 1*WSP tex-text
|
203
|
+
xcom-textblock ::= "begintext" [textblock-param] eol *(["%%"] tex-text) "%%endtext"
|
204
|
+
textblock-param ::= "obeylines" / ("fill" / "ragged") / ("align" / "justify") / "skip"
|
205
|
+
xcom-layout ::= xcom-sep / xcom-vskip / xcom-newpage
|
206
|
+
xcom-sep ::= "sep" [3(1*WSP xcom-number xcom-unit)] ; space-above, space-below, width
|
207
|
+
xcom-vskip ::= "vskip" 1*WSP xcom-number xcom-unit
|
208
|
+
xcom-newpage ::= "newpage" [1*WSP 1*DIGIT] ; optionally restart page numbering at n
|
209
|
+
xcom-margins ::= ("botmargin" / "topmargin" / "leftmargin" / "rightmargin") 1*WSP xcom-number xcom-unit
|
210
|
+
xcom-midi ::= "midi" 1*WSP (midi-channel / midi-program / midi-transpose)
|
211
|
+
midi-channel ::= "channel" 1*WSP midi-channel-number
|
212
|
+
midi-program ::= "program" 1*WSP [midi-channel-number 1*WSP] midi-program-number
|
213
|
+
midi-channel-number ::= %x31-39 / (%x31 %x30-36) ; channels 1-16
|
214
|
+
midi-program-number ::= %x31-39 / (%x31-39 %x30-39) / (%x31 %x30-31 %x30-39) / (%x31.32 %x30-38) ; programs 1-128
|
215
|
+
midi-transpose ::= "transpose" 1*WSP ["-"] 1*DIGIT
|
216
|
+
xcom-other ::= *(VCHAR / WSP)
|
217
|
+
xcom-number ::= 1*DIGIT ["." 1*DIGIT]
|
218
|
+
xcom-unit ::= ["cm" / "pt" / "in"]
|
219
|
+
|
220
|
+
; --------------------------------------------------------------------------------
|
221
|
+
lyrics ::= *(lyrics-char / lyrics-syllable-break / lyrics-next-bar / lyrics-hold / lyrics-skip-note / lyrics-nbsp / lyrics-dash / tex-escape)
|
222
|
+
lyrics-ifield ::= *(lyrics-char-ifield / lyrics-syllable-break / lyrics-next-bar / lyrics-hold / lyrics-skip-note / lyrics-nbsp / lyrics-dash / tex-escape)
|
223
|
+
lyrics-syllable-break ::= "-" ; break between syllables in a word
|
224
|
+
lyrics-next-bar ::= "|" ; advance to next bar
|
225
|
+
lyrics-hold ::= "_" ; hold syllable for one more note
|
226
|
+
lyrics-skip-note ::= "*" ; =blank syllable
|
227
|
+
lyrics-nbsp ::= "~" ; non-breaking space = words on same note
|
228
|
+
lyrics-dash ::= "\-" ; printed as a -
|
229
|
+
lyrics-char ::= WSP / DIGIT / ALPHA / %x21-29 / %x2B-2C / %x2E-2F / %x3A-40 / %x5B / %x5D / %x5E / %x60 / %x7B-7D ; all characters without special meaning
|
230
|
+
lyrics-char-ifield ::= WSP / DIGIT / ALPHA / %x21-29 / %x2B-2C / %x2E-2F / %x3A-40 / %x5B / %x5E / %x60 / %x7B-7D ; all characters without special meaning and except ]
|
231
|
+
|
232
|
+
; --------------------------------------------------------------------------------
|
233
|
+
tex-text ::= *(WSP / %21-%5B / %5D-7E / tex-escape) ; text that may contain TeX escapes
|
234
|
+
tex-text-ifield ::= *(WSP / %21-%5B / %5E-7E / tex-escape) ; as above, but except ]
|
235
|
+
tex-escape ::= "\" 1*(VCHAR) ; to be defined better
|
236
|
+
|
237
|
+
; --------------------------------------------------------------------------------
|
238
|
+
tex ::= "\" *(VCHAR / WSP) eol ; deprecated - kept only for backward compatibility with abc2mtex
|
239
|
+
eol ::= CRLF / LF / CR ; only one version should occur in the whole file - win / *nix / mac line breaks
|
240
|
+
|
241
|
+
; --------------------------------------------------------------------------------
|
242
|
+
; Core rules in ABNF:
|
243
|
+
; ALPHA ::= %x41-5A / %x61-7A ; A-Z / a-z
|
244
|
+
; CR ::= %x0D ; carriage return
|
245
|
+
; CRLF ::= %x0D.0A ; CR+LF
|
246
|
+
; DIGIT ::= %x30-39 ; 0-9
|
247
|
+
; DQUOTE ::= %x22 ; "
|
248
|
+
; HTAB ::= %x09 ; tab
|
249
|
+
; LF ::= %x0A ; linefeed
|
250
|
+
; SP ::= %x20 ; space
|
251
|
+
; VCHAR ::= %x21-7e ; printing chars
|
252
|
+
; WSP ::= SP / HTAB ; whitespace
|
253
|
+
; %xDD means a hexadecimal code for a character
|
254
|
+
; %xCC-DD means any character in that range
|
255
|
+
; %xCC.DD means two characters
|
256
|
+
; / means or
|
257
|
+
; * means 0 or more occurences of
|
258
|
+
; 1* means 1 or more occurences of
|
259
|
+
; 2* means 2 or more occurences of
|
260
|
+
; [ ] means optional
|
261
|
+
; ( ) used for grouping
|
262
|
+
; " " is a literal string (note that it is case insensitive)
|
263
|
+
; ; starts a comment to end of line
|
264
|
+
; read more about ABNF at http://www.ietf.org/rfc/rfc2234.txt.
|
data/tests/test_abc.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
|
2
|
+
require 'lib/yaparc.rb'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
### c.f. http://www.norbeck.nu/abc/bnf/abc20bnf.htm###
|
6
|
+
|
7
|
+
module ABC
|
8
|
+
|
9
|
+
# KEYWORDS = %w{NOT AND OR ALL IN select from where EXISTS}
|
10
|
+
|
11
|
+
# abc-file ::= *(abc-tune / comment / xcommand / file-field / text-line / tex)
|
12
|
+
class AbcFile
|
13
|
+
include Yaparc::Parsable
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@parser = lambda do
|
17
|
+
Yaparc::ManyParser.new(
|
18
|
+
Yaparc::AltParser.new(AbcTune.new,
|
19
|
+
Comment.new,
|
20
|
+
Xcommand.new,
|
21
|
+
FileField.new,
|
22
|
+
TextLine.new,
|
23
|
+
Tex.new))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# file-field ::= field-area / field-book / field-composer / field-discography / field-file / field-group / field-history / field-length / field-meter / field-notes / field-origin / field-parts / field-tempo / field-rhythm / field-source / field-userdef-print / field-userdef-play / field-words / field-transcription / field-key / unused-field ; Default values for the whole file - all fields except number, title and voice
|
29
|
+
class FileField
|
30
|
+
include Yaparc::Parsable
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@parser = lambda do
|
34
|
+
Yaparc::AltParser.new(
|
35
|
+
FieldArea.new,
|
36
|
+
FieldBook.new,
|
37
|
+
FieldComposer.new,
|
38
|
+
FieldDiscography.new,
|
39
|
+
FieldFile.new,
|
40
|
+
FieldGroup.new,
|
41
|
+
FieldHistory.new,
|
42
|
+
FieldLength.new,
|
43
|
+
FieldMeter.new,
|
44
|
+
FieldNotes.new,
|
45
|
+
FieldOrigin.new,
|
46
|
+
FieldParts.new,
|
47
|
+
FieldTempo.new,
|
48
|
+
FieldRhythm.new,
|
49
|
+
FieldSource.new,
|
50
|
+
FieldUserdefPrint.new,
|
51
|
+
FieldUserdefPlay.new,
|
52
|
+
FieldWords.new,
|
53
|
+
FieldTranscription.new,
|
54
|
+
FieldKey.new,
|
55
|
+
UnusedField.new)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# abc-tune ::= abc-header abc-music eol
|
61
|
+
class AbcTune
|
62
|
+
include Yaparc::Parsable
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
@parser = lambda do
|
66
|
+
Yaparc::SeqParser.new(AbcHeader.new,
|
67
|
+
AbcMusic.new,
|
68
|
+
Eol.new)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# abc-header ::= [field-number] title-fields *other-field field-key ; note that field-number is optional.
|
74
|
+
class AbcTune
|
75
|
+
include Yaparc::Parsable
|
76
|
+
|
77
|
+
def initialize
|
78
|
+
@parser = lambda do
|
79
|
+
Yaparc::SeqParser.new(
|
80
|
+
ZeroOneParser.new(FieldNumber.new)
|
81
|
+
TitleFields.new,
|
82
|
+
ManyParser.new(OtherField.new),
|
83
|
+
FieldKey.new)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# field-number ::= %x58.3A *WSP 1*DIGIT header-eol ; X:
|
89
|
+
class FieldNumber
|
90
|
+
include Yaparc::Parsable
|
91
|
+
|
92
|
+
def initialize
|
93
|
+
@parser = lambda do
|
94
|
+
Yaparc::SeqParser.new(
|
95
|
+
|
96
|
+
|
97
|
+
%x58.3A *WSP 1*DIGIT header-eol ; X:
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
### eol ::= CRLF / LF / CR ; only one version should occur in the whole file - win / *nix / mac line breaks
|
103
|
+
class Eol
|
104
|
+
include Yaparc::Parsable
|
105
|
+
|
106
|
+
def initialize
|
107
|
+
@parser = lambda do
|
108
|
+
Yaparc::AltParser.new(RegexParser.new(/\n/))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/tests/test_calc.rb
CHANGED
@@ -3,8 +3,10 @@ require 'test/unit'
|
|
3
3
|
|
4
4
|
module Calc
|
5
5
|
|
6
|
-
class Expr < Yaparc::AbstractParser
|
7
|
-
|
6
|
+
# class Expr < Yaparc::AbstractParser
|
7
|
+
class Expr
|
8
|
+
include Yaparc::Parsable
|
9
|
+
|
8
10
|
def initialize
|
9
11
|
@parser = lambda do
|
10
12
|
Yaparc::AltParser.new(
|
@@ -43,7 +45,9 @@ module Calc
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
|
-
class Term < Yaparc::AbstractParser
|
48
|
+
# class Term < Yaparc::AbstractParser
|
49
|
+
class Term
|
50
|
+
include Yaparc::Parsable
|
47
51
|
|
48
52
|
def initialize
|
49
53
|
@parser = lambda do
|
@@ -59,8 +63,9 @@ module Calc
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
class Factor < Yaparc::AbstractParser
|
63
|
-
|
66
|
+
# class Factor < Yaparc::AbstractParser
|
67
|
+
class Factor
|
68
|
+
include Yaparc::Parsable
|
64
69
|
|
65
70
|
def initialize
|
66
71
|
@parser = lambda do
|
data/tests/test_owl.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
ontology ::= 'Ontology(' [ ontologyID ] { directive } ')'
|
2
|
+
directive ::= 'Annotation(' ontologyPropertyID ontologyID ')'
|
3
|
+
| 'Annotation(' annotationPropertyID URIreference ')'
|
4
|
+
| 'Annotation(' annotationPropertyID dataLiteral ')'
|
5
|
+
| 'Annotation(' annotationPropertyID individual ')'
|
6
|
+
| axiom
|
7
|
+
| fact
|
8
|
+
datatypeID ::= URIreference
|
9
|
+
classID ::= URIreference
|
10
|
+
individualID ::= URIreference
|
11
|
+
ontologyID ::= URIreference
|
12
|
+
datavaluedPropertyID ::= URIreference
|
13
|
+
individualvaluedPropertyID ::= URIreference
|
14
|
+
annotationPropertyID ::= URIreference
|
15
|
+
ontologyPropertyID ::= URIreference
|
16
|
+
annotation ::= 'annotation(' annotationPropertyID URIreference ')'
|
17
|
+
| 'annotation(' annotationPropertyID dataLiteral ')'
|
18
|
+
| 'annotation(' annotationPropertyID individual ')'
|
19
|
+
|
20
|
+
fact ::= individual
|
21
|
+
individual ::= 'Individual(' [ individualID ] { annotation } { 'type(' type ')' } { value } ')'
|
22
|
+
value ::= 'value(' individualvaluedPropertyID individualID ')'
|
23
|
+
| 'value(' individualvaluedPropertyID individual ')'
|
24
|
+
| 'value(' datavaluedPropertyID dataLiteral ')'
|
25
|
+
type ::= description
|
26
|
+
|
27
|
+
axiom ::= 'Class(' classID ['Deprecated'] modality { annotation } { description } ')'
|
28
|
+
| 'EnumeratedClass(' classID ['Deprecated'] { annotation } { individualID } ')'
|
29
|
+
| 'DisjointClasses(' description description { description } ')'
|
30
|
+
| 'EquivalentClasses(' description { description } ')'
|
31
|
+
| 'SubClassOf(' description description ')'
|
32
|
+
| 'Datatype(' datatypeID ['Deprecated'] { annotation } )'
|
33
|
+
| 'DatatypeProperty(' datavaluedPropertyID ['Deprecated'] { annotation } { 'super(' datavaluedPropertyID ')'} ['Functional'] { 'domain(' description ')' } { 'range(' dataRange ')' } ')'
|
34
|
+
| 'ObjectProperty(' individualvaluedPropertyID ['Deprecated'] { annotation } { 'super(' individualvaluedPropertyID ')' } [ 'inverseOf(' individualvaluedPropertyID ')' ] [ 'Symmetric' ] [ 'Functional' | 'InverseFunctional' | 'Functional' 'InverseFunctional' | 'Transitive' ] { 'domain(' description ')' } { 'range(' description ')' } ')'
|
35
|
+
| 'AnnotationProperty(' annotationPropertyID { annotation } ')'
|
36
|
+
| 'OntologyProperty(' ontologyPropertyID { annotation } ')'
|
37
|
+
| 'EquivalentProperties(' datavaluedPropertyID datavaluedPropertyID { datavaluedPropertyID } ')'
|
38
|
+
| 'SubPropertyOf(' datavaluedPropertyID datavaluedPropertyID ')'
|
39
|
+
| 'EquivalentProperties(' individualvaluedPropertyID individualvaluedPropertyID { individualvaluedPropertyID } ')'
|
40
|
+
| 'SubPropertyOf(' individualvaluedPropertyID individualvaluedPropertyID ')'
|
41
|
+
|
42
|
+
modality ::= 'complete' | 'partial'
|
43
|
+
|
44
|
+
description ::= classID
|
45
|
+
| restriction
|
46
|
+
| 'unionOf(' { description } ')'
|
47
|
+
| 'intersectionOf(' { description } ')'
|
48
|
+
| 'complementOf(' description ')'
|
49
|
+
| 'oneOf(' { individualID } ')'
|
50
|
+
|
51
|
+
restriction ::= 'restriction(' datavaluedPropertyID dataRestrictionComponent { dataRestrictionComponent } ')'
|
52
|
+
| 'restriction(' individualvaluedPropertyID individualRestrictionComponent { individualRestrictionComponent } ')'
|
53
|
+
|
54
|
+
dataRestrictionComponent ::= 'allValuesFrom(' dataRange ')'
|
55
|
+
| 'someValuesFrom(' dataRange ')'
|
56
|
+
| 'value(' dataLiteral ')'
|
57
|
+
| cardinality
|
58
|
+
|
59
|
+
individualRestrictionComponent ::= 'allValuesFrom(' description ')'
|
60
|
+
| 'someValuesFrom(' description ')'
|
61
|
+
| 'value(' individualID ')'
|
62
|
+
| cardinality
|
63
|
+
cardinality ::= 'minCardinality(' non-negative-integer ')'
|
64
|
+
| 'maxCardinality(' non-negative-integer ')'
|
65
|
+
| 'cardinality(' non-negative-integer ')'
|
66
|
+
dataRange ::= datatypeID | 'rdfs:Literal'
|
67
|
+
| 'oneOf(' { dataLiteral } ')'
|
68
|
+
|
data/tests/test_parser.rb
CHANGED
@@ -5,12 +5,15 @@ require 'pp'
|
|
5
5
|
class YaparcTest < Test::Unit::TestCase
|
6
6
|
include ::Yaparc
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
def test_seq_alt_parse
|
9
|
+
parser = Yaparc::SeqParser.new(Yaparc::Symbol.new('scheme'),
|
10
|
+
Yaparc::Symbol.new(':'),
|
11
|
+
Yaparc::AltParser.new(Natural.new,
|
12
|
+
Identifier.new))
|
13
|
+
result = parser.parse("scheme:124")
|
14
|
+
assert_instance_of Result::OK, result
|
15
|
+
result = parser.parse("scheme:identifier")
|
16
|
+
assert_instance_of Result::OK, result
|
14
17
|
end
|
15
18
|
|
16
19
|
def test_succeed_parse
|
@@ -116,6 +119,17 @@ class YaparcTest < Test::Unit::TestCase
|
|
116
119
|
parser = AltParser.new(FailParser.new, FailParser.new)
|
117
120
|
result = parser.parse("abc")
|
118
121
|
assert_instance_of Result::Fail, result
|
122
|
+
|
123
|
+
parser = AltParser.new(Natural.new, Ident.new)
|
124
|
+
result = parser.parse("abc")
|
125
|
+
assert_instance_of Result::OK, result
|
126
|
+
result = parser.parse("124")
|
127
|
+
assert_instance_of Result::OK, result
|
128
|
+
result = parser.parse("ABC124")
|
129
|
+
assert_instance_of Result::Fail, result
|
130
|
+
result = parser.parse("abc124")
|
131
|
+
assert_instance_of Result::OK, result
|
132
|
+
assert_equal 'abc124', result.value
|
119
133
|
end
|
120
134
|
|
121
135
|
def test_apply_parse
|
@@ -172,6 +186,17 @@ class YaparcTest < Test::Unit::TestCase
|
|
172
186
|
Integer(match)
|
173
187
|
end
|
174
188
|
assert_equal 1234, result.value
|
189
|
+
|
190
|
+
parser = RegexParser.new(/([0-9]+):([a-z]+)/)
|
191
|
+
result = parser.parse_with_parameter("1234:ab") do |match1, match2|
|
192
|
+
assert_equal 'ab', match2
|
193
|
+
end
|
194
|
+
|
195
|
+
parser = RegexParser.new(/([0-9]+):([a-z]+)/) do |match1, match2|
|
196
|
+
[match2,match1]
|
197
|
+
end
|
198
|
+
result = parser.parse("1234:ab")
|
199
|
+
assert_equal ["ab", "1234"], result.value
|
175
200
|
end
|
176
201
|
|
177
202
|
def test_zero_one_parse
|
@@ -197,6 +222,18 @@ class YaparcTest < Test::Unit::TestCase
|
|
197
222
|
assert_equal "abcdef", result.input
|
198
223
|
end
|
199
224
|
|
225
|
+
def test_many_one_parse
|
226
|
+
is_digit = SatisfyParser.new(lambda {|i| i >= '0' and i <= '9'})
|
227
|
+
parser = ManyOneParser.new(is_digit,"")
|
228
|
+
result = parser.parse("123abc")
|
229
|
+
assert_equal "123", result.value
|
230
|
+
assert_equal "abc", result.input
|
231
|
+
|
232
|
+
result = parser.parse("abcdef")
|
233
|
+
assert_instance_of Result::Fail, result
|
234
|
+
assert_equal "abcdef", result.input
|
235
|
+
end
|
236
|
+
|
200
237
|
def test_ident
|
201
238
|
parser = Ident.new
|
202
239
|
result = parser.parse("abc def")
|
@@ -220,19 +257,19 @@ class YaparcTest < Test::Unit::TestCase
|
|
220
257
|
assert_equal "", result.input
|
221
258
|
end
|
222
259
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
260
|
+
# def test_space
|
261
|
+
# parser = Space.new
|
262
|
+
# result = parser.parse(" abc")
|
263
|
+
# assert_instance_of Result::OK, result
|
264
|
+
# assert_equal "abc", result.input
|
265
|
+
# end
|
229
266
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
267
|
+
# def test_whitespace
|
268
|
+
# parser = WhiteSpace.new
|
269
|
+
# result = parser.parse(" \n abc")
|
270
|
+
# assert_instance_of Result::OK, result
|
271
|
+
# assert_equal "abc", result.input
|
272
|
+
# end
|
236
273
|
|
237
274
|
# def test_token
|
238
275
|
# parser = Token.new
|
@@ -241,10 +278,10 @@ class YaparcTest < Test::Unit::TestCase
|
|
241
278
|
# assert_equal "abc", result.input
|
242
279
|
# end
|
243
280
|
|
244
|
-
def
|
245
|
-
parser =
|
246
|
-
tokenize.prefix =
|
247
|
-
tokenize.postfix =
|
281
|
+
def test_tokenize_with_block
|
282
|
+
parser = TokenizeParser.new(Ident.new) do |tokenize|
|
283
|
+
tokenize.prefix = SpaceParser.new
|
284
|
+
tokenize.postfix = SpaceParser.new
|
248
285
|
end
|
249
286
|
|
250
287
|
result = parser.parse(" abc")
|
@@ -256,9 +293,9 @@ class YaparcTest < Test::Unit::TestCase
|
|
256
293
|
assert_instance_of Result::Fail, result
|
257
294
|
assert_equal "\n abc", result.input
|
258
295
|
|
259
|
-
parser =
|
260
|
-
tokenize.prefix =
|
261
|
-
tokenize.postfix =
|
296
|
+
parser = TokenizeParser.new(Ident.new) do |tokenize|
|
297
|
+
tokenize.prefix = WhiteSpaceParser.new
|
298
|
+
tokenize.postfix = WhiteSpaceParser.new
|
262
299
|
end
|
263
300
|
|
264
301
|
result = parser.parse(" \n abc")
|
@@ -267,11 +304,31 @@ class YaparcTest < Test::Unit::TestCase
|
|
267
304
|
assert_equal "", result.input
|
268
305
|
end
|
269
306
|
|
307
|
+
def test_tokenize_without_block
|
308
|
+
parser = TokenizeParser.new(Ident.new, :prefix => WhiteSpaceParser.new, :postfix => WhiteSpaceParser.new)
|
309
|
+
|
310
|
+
result = parser.parse(" abc")
|
311
|
+
assert_instance_of Result::OK, result
|
312
|
+
assert_equal "abc", result.value
|
313
|
+
assert_equal "", result.input
|
314
|
+
|
315
|
+
parser = TokenizeParser.new(Ident.new, :prefix => SpaceParser.new, :postfix => SpaceParser.new)
|
316
|
+
result = parser.parse(" \n abc")
|
317
|
+
assert_instance_of Result::Fail, result
|
318
|
+
assert_equal "\n abc", result.input
|
319
|
+
end
|
320
|
+
|
270
321
|
def test_identifier
|
271
322
|
parser = Identifier.new
|
272
323
|
result = parser.parse(" abc ")
|
273
324
|
assert_equal "abc", result.value
|
274
325
|
assert_equal "", result.input
|
326
|
+
result = parser.parse(" _abc ")
|
327
|
+
assert_instance_of Result::OK, result
|
328
|
+
result = parser.parse(" 0_abc ")
|
329
|
+
assert_instance_of Result::Fail, result
|
330
|
+
result = parser.parse(" _00abc ")
|
331
|
+
assert_instance_of Result::OK, result
|
275
332
|
|
276
333
|
parser_with_keyword = Identifier.new("abc","efg")
|
277
334
|
result = parser_with_keyword.parse("abc")
|
@@ -294,5 +351,12 @@ class YaparcTest < Test::Unit::TestCase
|
|
294
351
|
assert_equal "%", result.value
|
295
352
|
assert_equal "", result.input
|
296
353
|
end
|
354
|
+
|
355
|
+
def test_literal_parser
|
356
|
+
parser = LiteralParser.new('%')
|
357
|
+
result = parser.parse(" % ")
|
358
|
+
assert_equal "%", result.value
|
359
|
+
assert_equal "", result.input
|
360
|
+
end
|
297
361
|
end
|
298
362
|
|