%{
/*
* Gregorio is a program that translates gabc files to GregorioTeX
* This file implements the note parser.
*
* Copyright (C) 2006-2021 The Gregorio Project (see CONTRIBUTORS.md)
*
* This file is part of Gregorio.
*
* This program 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.
*
* This program 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
* this program. If not, see .
*/
#include "config.h"
#include
#include /* for tolower */
#include "bool.h"
#include "struct.h"
#include "messages.h"
#include "support.h"
#include "gabc.h"
#define YY_NO_INPUT
#define YY_USER_ACTION gabc_update_location(¬es_lloc, \
gabc_notes_determination_text, gabc_notes_determination_leng);
static gregorio_scanner_location notes_lloc;
static gregorio_note *current_note;
static char char_for_brace;
static unsigned int nbof_isolated_episema;
static char *notesmacros[10];
static char tempstr[256];
static unsigned short overbrace_var = 0, underbrace_var = 0;
static const char *overbrace_var_kind;
static int before_ledger_type;
static char *before_ledger_length = NULL;
static unsigned short ledger_var[2] = { 0, 0 };
static unsigned char staff_lines;
static signed char highest_pitch;
static signed char high_ledger_line_pitch;
static bool legacy_oriscus_orientation;
static unsigned short he_adjustment_index[2] = { 0, 0 };
static signed char bracket_low_pitch, bracket_high_pitch;
static unsigned short left_bracket_texverb = 0;
#define LEDGER(WHICH, SPECIFICITY, VALUE) \
if (LEDGER_##SPECIFICITY > current_note->WHICH##_ledger_specificity) { \
current_note->WHICH##_ledger_line = VALUE; \
current_note->WHICH##_ledger_specificity = LEDGER_##SPECIFICITY; \
}
typedef struct slur_info {
unsigned short var;
char shift;
gregorio_note *start;
} slur_info;
static slur_info slur[2] = { { 0, '\0', NULL }, { 0, '\0', NULL } };
static __inline gregorio_sign_orientation letter_to_sign_orientation(
const char letter) {
switch (letter) {
case 'u': /* "u"under */
return SO_UNDER;
case 'o': /* "o"ver */
return SO_OVER;
}
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(letter_to_sign_orientation,
"invalid sign orientation letter: %c", letter);
return SO_OVER;
/* LCOV_EXCL_STOP */
}
static __inline int letter_to_pitch_adjustment(const char letter) {
switch (letter_to_sign_orientation(letter)) {
case SO_OVER:
return 1;
case SO_UNDER:
return -1;
}
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(letter_to_pitch_adjustment,
"invalid sign orientation letter: %c", letter);
return 0;
/* LCOV_EXCL_STOP */
}
static __inline signed char pitch_letter_to_height(const char pitch) {
char result = pitch - 'a' + LOWEST_PITCH;
if (pitch == 'p') {
--result;
}
if (result > highest_pitch) {
gregorio_messagef("pitch_letter_to_height", VERBOSITY_ERROR, 0,
_("invalid pitch for %u lines: %c"), (unsigned int)staff_lines,
pitch);
}
if (left_bracket_texverb) {
if (result < bracket_low_pitch) {
bracket_low_pitch = result;
}
if (result > bracket_high_pitch) {
bracket_high_pitch = result;
}
}
return result;
}
static gregorio_shape punctum_inclinatum(const char orientation)
{
switch (orientation) {
case '0':
return S_PUNCTUM_INCLINATUM_DESCENDENS;
case '2':
return S_PUNCTUM_INCLINATUM_STANS;
case '1':
return S_PUNCTUM_INCLINATUM_ASCENDENS;
}
return S_PUNCTUM_INCLINATUM_UNDETERMINED;
}
static __inline void lex_add_note(int i, gregorio_shape shape, char signs,
char liquescentia)
{
signed char height = pitch_letter_to_height(tolower(
(unsigned char)gabc_notes_determination_text[i]));
nbof_isolated_episema = 0;
gregorio_add_note(¤t_note, height, shape, signs, liquescentia, NULL,
¬es_lloc);
current_note->he_adjustment_index[SO_OVER] = he_adjustment_index[SO_OVER];
current_note->he_adjustment_index[SO_UNDER] = he_adjustment_index[SO_UNDER];
if (height >= high_ledger_line_pitch) {
LEDGER(high, DRAWN, true);
} else if (ledger_var[SO_OVER]) {
LEDGER(high, EXPLICIT, true);
}
if (height <= LOW_LEDGER_LINE_PITCH) {
LEDGER(low, DRAWN, true);
} else if (ledger_var[SO_UNDER]) {
LEDGER(low, EXPLICIT, true);
}
}
static __inline void add_bar_as_note(gregorio_bar bar)
{
nbof_isolated_episema = 0;
gregorio_add_bar_as_note(¤t_note, bar, ¬es_lloc);
}
static __inline void error(void)
{
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("undefined macro used: m%d"),
gabc_notes_determination_text[3] - '0');
}
static void add_h_episema(void)
{
grehepisema_size size = H_NORMAL;
gregorio_vposition vposition = VPOS_AUTO;
bool disable_bridge = false;
char *ptr = gabc_notes_determination_text;
char current;
/* first character is the underscore */
while ((current = *(++ptr))) {
switch(current) {
case '0':
vposition = VPOS_BELOW;
break;
case '1':
vposition = VPOS_ABOVE;
break;
case '2':
disable_bridge = true;
break;
case '3':
size = H_SMALL_LEFT;
break;
case '4':
size = H_SMALL_CENTRE;
break;
case '5':
size = H_SMALL_RIGHT;
break;
default:
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(gabc_notes_determination,
"unrecognized horizontal episema modifier: %c", current);
break;
/* LCOV_EXCL_STOP */
};
}
gregorio_add_h_episema(current_note, size, vposition, disable_bridge,
&nbof_isolated_episema);
}
static void add_sign(gregorio_sign sign)
{
gregorio_vposition vposition = VPOS_AUTO;
switch(gabc_notes_determination_text[1]) {
case '0':
vposition = VPOS_BELOW;
break;
case '1':
vposition = VPOS_ABOVE;
break;
}
gregorio_add_sign(current_note, sign, vposition);
}
static void save_before_ledger(const char *const before_ledger)
{
if (strcmp(before_ledger, "0") == 0) {
before_ledger_type = 0;
before_ledger_length = "";
} else if (strcmp(before_ledger, "1") == 0) {
before_ledger_type = 1;
before_ledger_length = "";
} else {
before_ledger_type = 2;
before_ledger_length = gregorio_strdup(before_ledger);
}
}
static void add_static_ledger(const gregorio_sign_orientation type,
const char *length) {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreDrawAdditionalLine{%d}{%s}{%d}{%s}{0}{}",
type, length + 1, before_ledger_type, before_ledger_length);
if (before_ledger_type == 2) {
free(before_ledger_length);
before_ledger_length = NULL;
}
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(tempstr),
GRE_TEXVERB_GLYPH, ¬es_lloc);
}
static __inline const char *over_or_under(
const gregorio_sign_orientation type) {
switch (type) {
case SO_OVER:
return "over";
case SO_UNDER:
return "under";
}
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(over_or_under, "invalid ledger type %d", type);
return "";
/* LCOV_EXCL_STOP */
}
static void add_variable_ledger(const gregorio_sign_orientation type,
const char *after_ledger)
{
if (ledger_var[type]) {
const char *const typename = over_or_under(type);
gregorio_messagef("add_variable_ledger", VERBOSITY_ERROR, 0,
_("variable %s-staff ledger line without termination of "
"previous %s-staff ledger line"), typename, typename);
} else {
int after_ledger_type;
const char *after_ledger_length;
++after_ledger;
if (strcmp(after_ledger, "0") == 0) {
after_ledger_type = 0;
after_ledger_length = "";
} else if (strcmp(after_ledger, "1") == 0) {
after_ledger_type = 1;
after_ledger_length = "";
} else {
after_ledger_type = 2;
after_ledger_length = after_ledger;
}
ledger_var[type] = ++tex_position_id;
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{0}{1}"
"\\GreDrawAdditionalLine{%d}{\\GreVarBraceLength{%hu}}"
"{%d}{%s}{%d}{%s}",
ledger_var[type], type, ledger_var[type], before_ledger_type,
before_ledger_length, after_ledger_type, after_ledger_length);
if (before_ledger_type == 2) {
free(before_ledger_length);
before_ledger_length = NULL;
}
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(tempstr),
GRE_TEXVERB_GLYPH, ¬es_lloc);
}
}
static void end_variable_ledger(const gregorio_sign_orientation type)
{
if (!ledger_var[type]) {
const char *const typename = over_or_under(type);
gregorio_messagef("end_variable_ledger", VERBOSITY_ERROR, 0,
_("variable %s-staff ledger line termination without variable "
"%s-staff ledger line start"), typename, typename);
} else {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{0}{2}", ledger_var[type]);
ledger_var[type] = 0;
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(tempstr),
GRE_TEXVERB_GLYPH, ¬es_lloc);
}
}
static __inline int parse_clef_line(char line)
{
line -= '0';
if (line < 0 || line > staff_lines) {
gregorio_messagef("parse_clef_line", VERBOSITY_ERROR, 0,
_("invalid clef line for %u lines: %d"),
(unsigned int)staff_lines, (int)line);
return 1;
}
return line;
}
static __inline gregorio_bar parse_dominican_bar(char bar)
{
bar -= '0';
if (bar < 1 || bar > (2 * (staff_lines - 1))) {
gregorio_messagef("parse_dominican_line", VERBOSITY_ERROR, 0,
_("invalid Dominican bar for %u lines: ;%d"),
(unsigned int)staff_lines, (int)bar);
}
switch (bar) {
case 1:
return B_DIVISIO_MINOR_D1;
case 2:
return B_DIVISIO_MINOR_D2;
case 3:
return B_DIVISIO_MINOR_D3;
case 4:
return B_DIVISIO_MINOR_D4;
case 5:
return B_DIVISIO_MINOR_D5;
case 6:
return B_DIVISIO_MINOR_D6;
case 7:
return B_DIVISIO_MINOR_D7;
case 8:
return B_DIVISIO_MINOR_D8;
}
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(check_dominican_line, "invalid dominican bar: %d", (int)bar);
return B_NO_BAR;
/* LCOV_EXCL_STOP */
}
static __inline gregorio_clef letter_to_clef(char letter)
{
switch (letter) {
case 'c':
return CLEF_C;
case 'f':
return CLEF_F;
}
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_fail2(letter_to_clef, "invalid clef: %c", letter);
return CLEF_C;
/* LCOV_EXCL_STOP */
}
/* this assertion should only fail if the lex rules are incorrect */
static __inline void slur_assert(char *fn, bool test) {
if (!test) {
/* not reachable unless there's a programming error */
/* LCOV_EXCL_START */
gregorio_message(_("invalid slur text"), fn, VERBOSITY_FATAL, 0);
exit(1);
/* LCOV_EXCL_STOP */
}
}
static char *parse_slur_shift(char *shift)
{
char *c;
c = strchr(gabc_notes_determination_text, ':');
slur_assert("parse_slur_shift", c != NULL);
slur_assert("parse_slur_shift", *(++c) != '\0');
*shift = *c;
return c;
}
static void parse_slur(void)
{
const int direction = letter_to_pitch_adjustment(
gabc_notes_determination_text[1]);
char shift, *width, *height, *end;
if (!current_note || current_note->type != GRE_NOTE) {
gregorio_message(
_("cannot add a slur to something that is not a note"),
"parse_slur", VERBOSITY_ERROR, 0);
return;
}
end = parse_slur_shift(&shift);
width = strchr(end, ';');
slur_assert("parse_slur", width != NULL);
height = strchr(++width, ',');
slur_assert("parse_slur", height != NULL);
*height = '\0';
end = strchr(++height, ']');
slur_assert("parse_slur", end != NULL);
*end = '\0';
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreSlur{%d}{%d}{%c}{%s}{%s}{}",
current_note->u.note.pitch + direction, direction, shift, width,
height);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
static void start_var_slur(void)
{
const gregorio_sign_orientation index = letter_to_sign_orientation(
gabc_notes_determination_text[1]);
if (!current_note || current_note->type != GRE_NOTE) {
gregorio_message(
_("cannot add a slur to something that is not a note"),
"start_var_slur", VERBOSITY_ERROR, 0);
return;
}
if (slur[index].var) {
gregorio_messagef("start_var_slur", VERBOSITY_ERROR, 0,
_("variable %s-note slur without termination of previous slur"),
over_or_under(index));
return;
}
slur[index].var = ++tex_position_id;
parse_slur_shift(&(slur[index].shift));
slur[index].start = current_note;
}
static void end_var_slur(void)
{
const int direction = letter_to_pitch_adjustment(
gabc_notes_determination_text[1]);
const gregorio_sign_orientation index = letter_to_sign_orientation(
gabc_notes_determination_text[1]);
char shift;
if (!current_note || current_note->type != GRE_NOTE) {
gregorio_message(
_("cannot add a slur to something that is not a note"),
"end_var_slur", VERBOSITY_ERROR, 0);
return;
}
if (!slur[index].var || !slur[index].shift || !slur[index].start) {
gregorio_messagef("end_var_slur", VERBOSITY_ERROR, 0,
_("variable %s-note slur end without start"),
over_or_under(index));
return;
}
parse_slur_shift(&shift);
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%c}{1}"
"\\GreSlur{%d}{%d}{%c}{\\GreVarBraceLength{%hu}}{}{%d}",
slur[index].var, slur[index].shift,
slur[index].start->u.note.pitch + direction, direction,
slur[index].shift, slur[index].var,
current_note->u.note.pitch + direction);
gregorio_add_texverb_to_note(slur[index].start, gregorio_strdup(tempstr));
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%c}{2}", slur[index].var, shift);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
slur[index].var = 0;
slur[index].shift = '\0';
slur[index].start = NULL;
}
static void left_bracket(void)
{
if (left_bracket_texverb) {
gregorio_message(
_("cannot add a left bracket before closing the previous one"),
"left_bracket", VERBOSITY_ERROR, 0);
return;
}
/* when setting the left bracket, temporarily store the point-and-click
* information in the texverb */
if (notes_lloc.generate_point_and_click) {
gregorio_snprintf(tempstr, sizeof tempstr, "%u:%u:%u",
notes_lloc.first_line, notes_lloc.first_offset,
notes_lloc.first_column + 1);
} else {
tempstr[0] = '\0';
}
left_bracket_texverb = gregorio_add_texverb_as_note(¤t_note,
gregorio_strdup(tempstr), GRE_TEXVERB_GLYPH, ¬es_lloc);
bracket_low_pitch = MAX_PITCH;
bracket_high_pitch = LOWEST_PITCH;
}
static void right_bracket(void)
{
if (!left_bracket_texverb) {
gregorio_message(
_("cannot add a right bracket without a matching left bracket"),
"right_bracket", VERBOSITY_ERROR, 0);
return;
}
if (bracket_high_pitch < bracket_low_pitch) {
gregorio_message(
_("cannot add brackets without notes between them"),
"right_bracket", VERBOSITY_ERROR, 0);
return;
}
gregorio_snprintf(tempstr, sizeof tempstr, "\\GreBracket{0}{%d}{%d}{%s}",
bracket_low_pitch, bracket_high_pitch,
gregorio_texverb(left_bracket_texverb));
gregorio_change_texverb(left_bracket_texverb, gregorio_strdup(tempstr));
if (notes_lloc.generate_point_and_click) {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreBracket{1}{%d}{%d}{%u:%u:%u}", bracket_low_pitch,
bracket_high_pitch, notes_lloc.first_line,
notes_lloc.first_offset, notes_lloc.first_column + 1);
} else {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreBracket{1}{%d}{%d}{}", bracket_low_pitch,
bracket_high_pitch);
}
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(tempstr),
GRE_TEXVERB_GLYPH, ¬es_lloc);
left_bracket_texverb = 0;
}
static void parse_hepisema_adjustment(void)
{
/* See https://github.com/gregorio-project/gregorio/issues/872
*
* [xh:yzw]
*
* - x is o(ver) or u(under)
* - y is optional and is
* - l for low in the space (chooses ol or ul depending on x)
* - m for middle of the space
* - h for high in the space (chooses oh or uh depending on x)
* - ol for low in the space as if the episema were over the note
* - oh for high in the space as if the episema were over the note
* - ul for low in the space as if the episema were under the note
* - uh for high in the space as if the episema were under the note
* - z is an optional nudge and must start with + or -
* - w is optional and may be { to start a range or } to end a range.
*
* at least one of y, z, or w must be provided
* if y and z are omitted, the : may be omitted
* y and z are not permitted when w is }
*/
const gregorio_sign_orientation index = letter_to_sign_orientation(
gabc_notes_determination_text[1]);
gregorio_sign_orientation det_index = index;
char *ch = gabc_notes_determination_text + 3;
gregorio_hepisema_vbasepos vbasepos = HVB_AUTO;
char *nudge = NULL;
char save;
short hepisema_adjustment_id;
if (he_adjustment_index[index]) {
gregorio_messagef("parse_hepisema_adustment", VERBOSITY_ERROR, 0,
_("horizontal %s-episema adjustment start before ending the "
"previous adjustment"), over_or_under(index));
return;
}
if (*ch == ':') {
++ch;
if (*ch == 'm') {
vbasepos = HVB_MIDDLE;
} else {
switch (*ch) {
case 'o':
++ch;
det_index = SO_OVER;
break;
case 'u':
++ch;
det_index = SO_UNDER;
break;
}
switch (*ch) {
case 'l':
switch (det_index) {
case SO_OVER:
vbasepos = HVB_O_LOW;
break;
case SO_UNDER:
vbasepos = HVB_U_LOW;
break;
}
break;
case 'h':
switch (det_index) {
case SO_OVER:
vbasepos = HVB_O_HIGH;
break;
case SO_UNDER:
vbasepos = HVB_U_HIGH;
break;
}
break;
}
}
if (vbasepos) {
++ch;
}
if (*ch == '+' || *ch == '-') {
nudge = ch;
do {
++ch;
} while (*ch && *ch != '{' && *ch != ']');
save = *ch;
*ch = '\0';
nudge = gregorio_strdup(nudge);
*ch = save;
}
}
hepisema_adjustment_id = gregorio_add_hepisema_adjustment(vbasepos, nudge);
if (*ch == '{') {
he_adjustment_index[index] = hepisema_adjustment_id;
} else {
if (!current_note || current_note->type != GRE_NOTE) {
gregorio_message(_("cannot add a horizontal episema adjustment to "
"something that is not a note"),
"parse_hepisema_adjustment", VERBOSITY_ERROR, 0);
return;
}
current_note->he_adjustment_index[index] = hepisema_adjustment_id;
}
}
static void end_hepisema_adjustment(void)
{
/* [xh:}]
* - x indicates l(ow) or h(igh) episema
* - : is optional
*/
const gregorio_sign_orientation index = letter_to_sign_orientation(
gabc_notes_determination_text[1]);
if (!he_adjustment_index[index]) {
gregorio_messagef("end_hepisema_adustment", VERBOSITY_ERROR, 0,
_("horizontal %s-episema adjustment end with no matching "
"start"), over_or_under(index));
return;
}
he_adjustment_index[index] = 0;
}
void gabc_det_notes_finish(void)
{
gregorio_sign_orientation orientation;
if (overbrace_var) {
gregorio_message(_("unclosed variable over-staff brace"),
"gabc_det_notes_finish", VERBOSITY_ERROR, 0);
overbrace_var = 0;
}
if (underbrace_var) {
gregorio_message(_("unclosed variable under-staff brace"),
"gabc_det_notes_finish", VERBOSITY_ERROR, 0);
underbrace_var = 0;
}
for (orientation = SO_OVER; orientation <= SO_UNDER; ++orientation) {
const char *name = over_or_under(orientation);
if (ledger_var[orientation]) {
gregorio_messagef("gabc_det_notes_finish", VERBOSITY_ERROR, 0,
_("unclosed variable %s-staff ledger line"), name);
ledger_var[orientation] = 0;
}
if (slur[orientation].var) {
gregorio_messagef("gabc_det_notes_finish", VERBOSITY_ERROR, 0,
_("unclosed variable %s-note slur"), name);
slur[orientation].var = 0;
slur[orientation].shift = '\0';
slur[orientation].start = NULL;
}
if (he_adjustment_index[orientation]) {
gregorio_messagef("gabc_det_notes_finish", VERBOSITY_ERROR, 0,
_("unclosed horizontal %s-episema adjustment"),
over_or_under(orientation));
ledger_var[orientation] = 0;
}
}
if (left_bracket_texverb) {
gregorio_message(_("unclosed left bracket"),
"gabc_det_notes_finish", VERBOSITY_ERROR, 0);
left_bracket_texverb = 0;
}
}
%}
%option stack
%option 8bit
%option pointer
%option nounput
%option noyy_push_state
%option noyy_pop_state
%option noyy_top_state
%option full
%option noread
%option nomain
%option align
%option noyylineno
%option prefix="gabc_notes_determination_"
%option noyywrap
%x texverbnote
%x texverbglyph
%x texverbelement
%x choralsign
%x choralnabc
%x alt
%x comments
%x overbrace
%x underbrace
%x overcurlybrace
%x overcurlyaccentusbrace
%x space
%x nbspace
%x overledger overledger2
%x underledger underledger2
%x endledger
%%
\% {
BEGIN(comments);
}
(\n|\r)+ {
BEGIN(INITIAL);
}
[^\n\r]* {
/* ignored */
}
\[cs: {
BEGIN(choralsign);
}
\[cn: {
BEGIN(choralnabc);
}
\[ob:[01]; {
char_for_brace = gabc_notes_determination_text[4]-'0';
BEGIN(overbrace);
}
\[ub:[01]; {
char_for_brace = gabc_notes_determination_text[4]-'0';
BEGIN(underbrace);
}
\[ocb:[01]; {
char_for_brace = gabc_notes_determination_text[5]-'0';
BEGIN(overcurlybrace);
}
\[ocba:[01]; {
char_for_brace = gabc_notes_determination_text[6]-'0';
BEGIN(overcurlyaccentusbrace);
}
\[ob:[01]\{\] {
if (overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace without termination of "
"previous overbrace"));
} else {
char_for_brace = gabc_notes_determination_text[4]-'0';
overbrace_var = ++tex_position_id;
overbrace_var_kind = "ob";
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{1}"
"\\GreOverBrace{\\GreVarBraceLength{%hu}}{0pt}{0pt}{%d}",
overbrace_var, char_for_brace, overbrace_var, char_for_brace);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ub:[01]\{\] {
if (underbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable underbrace without termination of "
"previous underbrace"));
} else {
char_for_brace = gabc_notes_determination_text[4]-'0';
underbrace_var = ++tex_position_id;
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{1}"
"\\GreUnderBrace{\\GreVarBraceLength{%hu}}{0pt}{0pt}{%d}",
underbrace_var, char_for_brace, underbrace_var, char_for_brace);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ocb:[01]\{\] {
if (overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace without termination of "
"previous overbrace"));
} else {
char_for_brace = gabc_notes_determination_text[5]-'0';
overbrace_var = ++tex_position_id;
overbrace_var_kind = "ocb";
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{1}"
"\\GreOverCurlyBrace{\\GreVarBraceLength{%hu}}{0pt}{0pt}{%d}{0}",
overbrace_var, char_for_brace, overbrace_var, char_for_brace);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ocba:[01]\{\] {
if (overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace without termination of "
"previous overbrace"));
} else {
char_for_brace = gabc_notes_determination_text[6]-'0';
overbrace_var = ++tex_position_id;
overbrace_var_kind = "ocba";
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{1}"
"\\GreOverCurlyBrace{\\GreVarBraceLength{%hu}}{0pt}{0pt}{%d}{1}",
overbrace_var, char_for_brace, overbrace_var, char_for_brace);
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ob:[01]\}\] {
if (!overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace termination without "
"variable overbrace start"));
} else if (strcmp (overbrace_var_kind, "ob")) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace started with %s "
"and terminated with ob"),
overbrace_var_kind);
} else {
char_for_brace = gabc_notes_determination_text[4]-'0';
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{2}", overbrace_var,
char_for_brace);
overbrace_var = 0;
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ub:[01]\}\] {
if (!underbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable underbrace termination without "
"variable underbrace start"));
} else {
char_for_brace = gabc_notes_determination_text[4]-'0';
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{2}", underbrace_var,
char_for_brace);
underbrace_var = 0;
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ocb:[01]\}\] {
if (!overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace termination without "
"variable overbrace start"));
} else if (strcmp (overbrace_var_kind, "ocb")) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace started with %s "
"and terminated with ocb"),
overbrace_var_kind);
} else {
char_for_brace = gabc_notes_determination_text[5]-'0';
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{2}", overbrace_var,
char_for_brace);
overbrace_var = 0;
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[ocba:[01]\}\] {
if (!overbrace_var) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace termination without "
"variable overbrace start"));
} else if (strcmp (overbrace_var_kind, "ocba")) {
gregorio_messagef("gabc_notes_determination", VERBOSITY_ERROR, 0,
_("variable overbrace started with %s "
"and terminated with ocba"),
overbrace_var_kind);
} else {
char_for_brace = gabc_notes_determination_text[6]-'0';
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreVarBraceSavePos{%hu}{%d}{2}", overbrace_var,
char_for_brace);
overbrace_var = 0;
gregorio_add_texverb_to_note(current_note, gregorio_strdup(tempstr));
}
}
\[nm[1-9]\] {
if (notesmacros[gabc_notes_determination_text[3]-'0']) {
gregorio_add_texverb_to_note(current_note, gregorio_strdup(
notesmacros[gabc_notes_determination_text[3]-'0']));
} else error();
}
\[gm[1-9]\] {
if (notesmacros[gabc_notes_determination_text[3]-'0']) {
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(
notesmacros[gabc_notes_determination_text[3]-'0']),
GRE_TEXVERB_GLYPH, ¬es_lloc);
} else error();
}
\[em[1-9]\] {
if (notesmacros[gabc_notes_determination_text[3]-'0']) {
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(
notesmacros[gabc_notes_determination_text[3]-'0']),
GRE_TEXVERB_ELEMENT, ¬es_lloc);
} else error();
}
\[altm[1-9]\] {
if (notesmacros[gabc_notes_determination_text[5]-'0']) {
gregorio_add_texverb_as_note(¤t_note, gregorio_strdup(
notesmacros[gabc_notes_determination_text[5]-'0']),
GRE_TEXVERB_ELEMENT, ¬es_lloc);
} else error();
}
\[nv: {
BEGIN(texverbnote);
}
\[gv: {
BEGIN(texverbglyph);
}
\[ev: {
BEGIN(texverbelement);
}
\[alt: {
BEGIN(alt);
}
{
gregorio_add_nlba_as_note(¤t_note, NLBA_BEGINNING, ¬es_lloc);
}
<\/nlba> {
gregorio_add_nlba_as_note(¤t_note, NLBA_END, ¬es_lloc);
}
@\[ {
gregorio_start_autofuse(¤t_note, ¬es_lloc);
}
\] {
gregorio_end_autofuse(¤t_note, ¬es_lloc);
}
(\$.|[^\]])+ {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreOverBrace{%s}{0pt}{0pt}{%d}",
gabc_notes_determination_text, char_for_brace);
gregorio_add_texverb_to_note(current_note, gabc_unescape(tempstr));
}
(\$.|[^\]])+ {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreUnderBrace{%s}{0pt}{0pt}{%d}",
gabc_notes_determination_text, char_for_brace);
gregorio_add_texverb_to_note(current_note, gabc_unescape(tempstr));
}
(\$.|[^\]])+ {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreOverCurlyBrace{%s}{0pt}{0pt}{%d}{0}",
gabc_notes_determination_text, char_for_brace);
gregorio_add_texverb_to_note(current_note, gabc_unescape(tempstr));
}
(\$.|[^\]])+ {
gregorio_snprintf(tempstr, sizeof tempstr,
"\\GreOverCurlyBrace{%s}{0pt}{0pt}{%d}{1}",
gabc_notes_determination_text, char_for_brace);
gregorio_add_texverb_to_note(current_note, gabc_unescape(tempstr));
}
(\$.|[^\]])+ {
gregorio_add_cs_to_note(¤t_note,
gabc_unescape(gabc_notes_determination_text), false);
}
(\$.|[^\]])+ {
gregorio_add_cs_to_note(¤t_note,
gabc_unescape(gabc_notes_determination_text), true);
}
(\$.|[^\]])+ {
gregorio_add_texverb_to_note(current_note,
gabc_unescape(gabc_notes_determination_text));
}
(\$.|[^\]])+ {
gregorio_add_texverb_as_note(¤t_note,
gabc_unescape(gabc_notes_determination_text),
GRE_TEXVERB_GLYPH, ¬es_lloc);
}
(\$.|[^\]])+ {
gregorio_add_texverb_as_note(¤t_note,
gabc_unescape(gabc_notes_determination_text),
GRE_TEXVERB_ELEMENT, ¬es_lloc);
}
(\$.|[^\]])+ {
gregorio_add_texverb_as_note(¤t_note,
gabc_unescape(gabc_notes_determination_text), GRE_ALT,
¬es_lloc);
}
\/\[ {
BEGIN(space);
}
-?(\.[0-9]+|[0-9]+(\.[0-9]*)?)/\] {
gregorio_add_space_as_note(¤t_note, SP_AD_HOC_SPACE,
gregorio_strdup(gabc_notes_determination_text), ¬es_lloc);
}
!\/\[ {
BEGIN(nbspace);
}
-?(\.[0-9]+|[0-9]+(\.[0-9]*)?)/\] {
gregorio_add_space_as_note(¤t_note, SP_AD_HOC_SPACE_NB,
gregorio_strdup(gabc_notes_determination_text), ¬es_lloc);
}
\[oll:1\] {
LEDGER(high, EXPLICITLY_DRAWN, true);
}
\[oll:0\] {
LEDGER(high, EXPLICITLY_DRAWN, false);
}
\[oll:\}\] {
end_variable_ledger(SO_OVER);
}
\[oll: {
BEGIN(overledger);
}
[^;{]+ {
save_before_ledger(gabc_notes_determination_text);
BEGIN(overledger2);
}
;[^\]]+ {
add_static_ledger(SO_OVER, gabc_notes_determination_text);
BEGIN(endledger);
}
\{[^\]]+ {
add_variable_ledger(SO_OVER, gabc_notes_determination_text);
BEGIN(endledger);
}
\[ull:1\] {
LEDGER(low, EXPLICITLY_DRAWN, true);
}
\[ull:0\] {
LEDGER(low, EXPLICITLY_DRAWN, false);
}
\[ull:\}\] {
end_variable_ledger(SO_UNDER);
}
\[ull: {
BEGIN(underledger);
}
[^;{]+ {
save_before_ledger(gabc_notes_determination_text);
BEGIN(underledger2);
}
;[^\]]+ {
add_static_ledger(SO_UNDER, gabc_notes_determination_text);
BEGIN(endledger);
}
\{[^\]]+ {
add_variable_ledger(SO_UNDER, gabc_notes_determination_text);
BEGIN(endledger);
}
\] {
BEGIN(INITIAL);
}
\[[ou]slur:[012];[^,]+,[^\]]+\] {
parse_slur();
}
\[[ou]slur:[012]\{\] {
start_var_slur();
}
\[[ou]slur:[012]\}\] {
end_var_slur();
}
\[[ou]h(?x:
:(m|[ou]?[lh])\{?
| :(m|[ou]?[lh])?[+-][^\]\{]+\{?
| :?\{
)\] {
parse_hepisema_adjustment();
}
\[[ou]h:?\}\] {
end_hepisema_adjustment();
}
\[\[ {
left_bracket();
}
\]\] {
right_bracket();
}
\{ {
gregorio_add_texverb_as_note(¤t_note,
gregorio_strdup("\\hbox to 0pt{"), GRE_TEXVERB_ELEMENT,
¬es_lloc);
}
\} {
gregorio_add_texverb_as_note(¤t_note,
gregorio_strdup("\\hss%\n}%\n\\GreNoBreak\\relax "),
GRE_TEXVERB_ELEMENT, ¬es_lloc);
}
[a-np]\+ {
gregorio_add_manual_custos_as_note(¤t_note,
pitch_letter_to_height(gabc_notes_determination_text[0]),
¬es_lloc);
}
[\t\r\n]+ /* ignore ends of line and tabs */;
\[nocustos\] {
gregorio_add_suppress_custos_as_note(¤t_note, ¬es_lloc);
}
z0 {
gregorio_add_custos_as_note(¤t_note, ¬es_lloc);
}
z {
gregorio_add_end_of_line_as_note(¤t_note, false, false, false,
¬es_lloc);
}
z\+ {
gregorio_add_end_of_line_as_note(¤t_note, false, true, true,
¬es_lloc);
}
z- {
gregorio_add_end_of_line_as_note(¤t_note, false, true, false,
¬es_lloc);
}
Z {
gregorio_add_end_of_line_as_note(¤t_note, true, false, false,
¬es_lloc);
}
Z\+ {
gregorio_add_end_of_line_as_note(¤t_note, true, true, true,
¬es_lloc);
}
Z- {
gregorio_add_end_of_line_as_note(¤t_note, true, true, false,
¬es_lloc);
}
[cf][1-5] {
gregorio_add_clef_as_note(¤t_note,
letter_to_clef(gabc_notes_determination_text[0]),
parse_clef_line(gabc_notes_determination_text[1]), false,
¬es_lloc);
}
[cf]b[1-5] {
gregorio_add_clef_as_note(¤t_note,
letter_to_clef(gabc_notes_determination_text[0]),
parse_clef_line(gabc_notes_determination_text[2]), true,
¬es_lloc);
}
@[cf][1-5] {
gregorio_add_secondary_clef_to_note(current_note,
letter_to_clef(gabc_notes_determination_text[1]),
parse_clef_line(gabc_notes_determination_text[2]), false);
}
@[cf]b[1-5] {
gregorio_add_secondary_clef_to_note(current_note,
letter_to_clef(gabc_notes_determination_text[1]),
parse_clef_line(gabc_notes_determination_text[3]), true);
}
` {
add_bar_as_note(B_VIRGULA);
}
`0 {
add_bar_as_note(B_VIRGULA_HIGH);
}
`\? {
add_bar_as_note(B_VIRGULA_PAREN);
}
`0\?|`\?0 {
add_bar_as_note(B_VIRGULA_PAREN_HIGH);
}
\^ {
add_bar_as_note(B_DIVISIO_MINIMIS);
}
\^0 {
add_bar_as_note(B_DIVISIO_MINIMIS_HIGH);
}
, {
add_bar_as_note(B_DIVISIO_MINIMA);
}
,0 {
add_bar_as_note(B_DIVISIO_MINIMA_HIGH);
}
,\? {
add_bar_as_note(B_DIVISIO_MINIMA_PAREN);
}
,0\?|,\?0 {
add_bar_as_note(B_DIVISIO_MINIMA_PAREN_HIGH);
}
[,;][1-8] {
add_bar_as_note(parse_dominican_bar(gabc_notes_determination_text[1]));
}
; {
add_bar_as_note(B_DIVISIO_MINOR);
}
: {
add_bar_as_note(B_DIVISIO_MAIOR);
}
:: {
add_bar_as_note(B_DIVISIO_FINALIS);
}
:\? {
add_bar_as_note(B_DIVISIO_MAIOR_DOTTED);
}
r {
gregorio_add_cavum(current_note);
}
R {
gregorio_change_shape(current_note, S_LINEA_PUNCTUM,
legacy_oriscus_orientation);
}
r0 {
gregorio_change_shape(current_note, S_LINEA_PUNCTUM,
legacy_oriscus_orientation);
gregorio_add_cavum(current_note);
}
r1 {
gregorio_add_special_sign(current_note, _ACCENTUS);
}
r2 {
gregorio_add_special_sign(current_note, _ACCENTUS_REVERSUS);
}
r3 {
gregorio_add_special_sign(current_note, _CIRCULUS);
}
r4 {
gregorio_add_special_sign(current_note, _SEMI_CIRCULUS);
}
r5 {
gregorio_add_special_sign(current_note, _SEMI_CIRCULUS_REVERSUS);
}
r6 {
gregorio_add_special_sign(current_note, _MUSICA_FICTA_FLAT);
}
r7 {
gregorio_add_special_sign(current_note, _MUSICA_FICTA_NATURAL);
}
r8 {
gregorio_add_special_sign(current_note, _MUSICA_FICTA_SHARP);
}
x {
gregorio_change_shape(current_note, S_FLAT,
legacy_oriscus_orientation);
}
x\? {
gregorio_change_shape(current_note, S_FLAT_PAREN,
legacy_oriscus_orientation);
}
# {
gregorio_change_shape(current_note, S_SHARP,
legacy_oriscus_orientation);
}
#\? {
gregorio_change_shape(current_note, S_SHARP_PAREN,
legacy_oriscus_orientation);
}
y {
gregorio_change_shape(current_note, S_NATURAL,
legacy_oriscus_orientation);
}
y\? {
gregorio_change_shape(current_note, S_NATURAL_PAREN,
legacy_oriscus_orientation);
}
!?\/0 {
gregorio_add_space_as_note(¤t_note, SP_HALF_SPACE, NULL,
¬es_lloc);
}
!?\/! {
gregorio_add_space_as_note(¤t_note, SP_INTERGLYPH_SPACE, NULL,
¬es_lloc);
}
\/ {
gregorio_add_space_as_note(¤t_note, SP_NEUMATIC_CUT, NULL,
¬es_lloc);
}
\//\/\[ {
gregorio_add_space_as_note(¤t_note, SP_NEUMATIC_CUT, NULL,
¬es_lloc);
}
\/\/ {
gregorio_add_space_as_note(¤t_note, SP_LARGER_SPACE, NULL,
¬es_lloc);
}
\ {
gregorio_add_space_as_note(¤t_note, SP_GLYPH_SPACE, NULL,
¬es_lloc);
}
!\/ {
gregorio_add_space_as_note(¤t_note, SP_NEUMATIC_CUT_NB, NULL,
¬es_lloc);
}
!\//\/\[ {
gregorio_add_space_as_note(¤t_note, SP_NEUMATIC_CUT_NB, NULL,
¬es_lloc);
}
!\/\/ {
gregorio_add_space_as_note(¤t_note, SP_LARGER_SPACE_NB, NULL,
¬es_lloc);
}
!\ {
gregorio_add_space_as_note(¤t_note, SP_GLYPH_SPACE_NB, NULL,
¬es_lloc);
}
!/[^\/ ] {
gregorio_add_space_as_note(¤t_note, SP_ZERO_WIDTH, NULL,
¬es_lloc);
}
= {
gregorio_change_shape(current_note, S_LINEA,
legacy_oriscus_orientation);
}
[a-npA-NP]vv {
lex_add_note(0, S_BIVIRGA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]vvv {
lex_add_note(0, S_TRIVIRGA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]VV {
lex_add_note(0, S_BIVIRGA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]VVV {
lex_add_note(0, S_TRIVIRGA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]ss {
lex_add_note(0, S_DISTROPHA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]ss(\<|\>) {
lex_add_note(0, S_DISTROPHA, _NO_SIGN, L_AUCTUS_ASCENDENS);
}
[a-npA-NP]sss {
lex_add_note(0, S_TRISTROPHA, _NO_SIGN, L_NO_LIQUESCENTIA);
}
[a-npA-NP]sss(\<|\>) {
lex_add_note(0, S_TRISTROPHA, _NO_SIGN, L_AUCTUS_ASCENDENS);
}
[a-np] {
lex_add_note(0, S_PUNCTUM, _NO_SIGN, L_NO_LIQUESCENTIA);
}
-[a-np] {
lex_add_note(1, S_PUNCTUM, _NO_SIGN, L_INITIO_DEBILIS);
}
@[a-np] {
lex_add_note(1, S_PUNCTUM, _NO_SIGN, L_FUSED);
}
[A-NP][012]? {
lex_add_note(0, punctum_inclinatum(gabc_notes_determination_text[1]),
_NO_SIGN, L_NO_LIQUESCENTIA);
}
-[A-NP][012]? {
lex_add_note(1, punctum_inclinatum(gabc_notes_determination_text[2]),
_NO_SIGN, L_INITIO_DEBILIS);
}
@[A-NP][012]? {
lex_add_note(1, punctum_inclinatum(gabc_notes_determination_text[2]),
_NO_SIGN, L_FUSED);
}
\'[01]? {
add_sign(_V_EPISEMA);
}
_[0-5]* {
add_h_episema();
}
\.[01]? {
add_sign(_PUNCTUM_MORA);
}
~ {
gregorio_add_tail_liquescentia(current_note, L_DEMINUTUS,
legacy_oriscus_orientation);
}
> {
gregorio_add_tail_liquescentia(current_note, L_AUCTUS_DESCENDENS,
legacy_oriscus_orientation);
}
\< {
gregorio_add_tail_liquescentia(current_note, L_AUCTUS_ASCENDENS,
legacy_oriscus_orientation);
}
q {
gregorio_change_shape(current_note, S_QUADRATUM,
legacy_oriscus_orientation);
}
o {
gregorio_change_shape(current_note, S_ORISCUS_UNDETERMINED,
legacy_oriscus_orientation);
}
o0 {
gregorio_change_shape(current_note, S_ORISCUS_DESCENDENS,
legacy_oriscus_orientation);
}
o1 {
gregorio_change_shape(current_note, S_ORISCUS_ASCENDENS,
legacy_oriscus_orientation);
}
O {
gregorio_change_shape(current_note, S_ORISCUS_SCAPUS_UNDETERMINED,
legacy_oriscus_orientation);
}
O0 {
gregorio_change_shape(current_note, S_ORISCUS_SCAPUS_DESCENDENS,
legacy_oriscus_orientation);
}
O1 {
gregorio_change_shape(current_note, S_ORISCUS_SCAPUS_ASCENDENS,
legacy_oriscus_orientation);
}
w {
gregorio_change_shape(current_note, S_QUILISMA,
legacy_oriscus_orientation);
}
W {
gregorio_change_shape(current_note, S_QUILISMA_QUADRATUM,
legacy_oriscus_orientation);
}
v {
gregorio_change_shape(current_note, S_VIRGA,
legacy_oriscus_orientation);
}
V {
gregorio_change_shape(current_note, S_VIRGA_REVERSA,
legacy_oriscus_orientation);
}
s {
gregorio_change_shape(current_note, S_STROPHA,
legacy_oriscus_orientation);
}
\[hl:1\] {
LEDGER(high, EXPLICIT, true);
}
\[hl:0\] {
LEDGER(high, EXPLICIT, false);
}
\[ll:1\] {
LEDGER(low, EXPLICIT, true);
}
\[ll:0\] {
LEDGER(low, EXPLICIT, false);
}
.|\n {
gregorio_messagef("det_notes_from_string", VERBOSITY_ERROR, 0,
_("unrecognized character: \"%c\""),
gabc_notes_determination_text[0]);
}
%%
gregorio_note *gabc_det_notes_from_string(char *str, char *newmacros[10],
gregorio_scanner_location *loc, const gregorio_score *const score)
{
int i;
YY_BUFFER_STATE buf;
notes_lloc.first_line = loc->first_line;
notes_lloc.first_column = loc->first_column;
notes_lloc.first_offset = loc->first_offset;
/* yes... I do mean to set values from loc->first_* */
notes_lloc.last_line = loc->first_line;
notes_lloc.last_column = loc->first_column;
notes_lloc.last_offset = loc->first_offset;
notes_lloc.generate_point_and_click = loc->generate_point_and_click;
staff_lines = score->staff_lines;
highest_pitch = score->highest_pitch;
high_ledger_line_pitch = score->high_ledger_line_pitch;
legacy_oriscus_orientation = score->legacy_oriscus_orientation;
/* a small optimization could uccur here: we could do it only once at the
* beginning of the score, not at each syllable */
for (i = 0; i < 10; i++) {
notesmacros[i] = newmacros[i];
}
nbof_isolated_episema = 0;
current_note = NULL;
buf = yy_scan_string(str);
yylex();
yy_flush_buffer(buf);
yy_delete_buffer(buf);
gregorio_go_to_first_note(¤t_note);
return current_note;
}