%left ADDLYRICS
%right ':' UNSIGNED REAL E_UNSIGNED EVENT_IDENTIFIER EVENT_FUNCTION '^' '_'
- HYPHEN EXTENDER DURATION_IDENTIFIER
+ HYPHEN EXTENDER DURATION_IDENTIFIER '!'
/* The above are needed for collecting tremoli and other items (that
could otherwise be interpreted as belonging to the next function
parser->parser_error (*i, s);
}
+// The following are somewhat precarious constructs as they may change
+// the value of the lookahead token. That implies that the lookahead
+// token must not yet have made an impact on the state stack other
+// than causing the reduction of the current rule, or switching the
+// lookahead token while Bison is mulling it over will cause trouble.
+
#define MYBACKUP(Token, Value, Location) \
-do \
- if (yychar == YYEMPTY) \
- { \
+ do { \
+ if (yychar != YYEMPTY) \
+ parser->lexer_->push_extra_token \
+ (yylloc, yychar, yylval); \
if (Token) \
- parser->lexer_->push_extra_token (Token, Value); \
- parser->lexer_->push_extra_token (BACKUP); \
- } else { \
- parser->parser_error \
- (Location, _("Too much lookahead")); \
- } \
-while (0)
+ parser->lexer_->push_extra_token \
+ (Location, Token, Value); \
+ parser->lexer_->push_extra_token (Location, BACKUP); \
+ yychar = YYEMPTY; \
+ } while (0)
#define MYREPARSE(Location, Pred, Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- parser->lexer_->push_extra_token (Token, Value); \
- parser->lexer_->push_extra_token (REPARSE, \
- Pred); \
- } else { \
- parser->parser_error \
- (Location, _("Too much lookahead")); \
- } \
-while (0)
+ do { \
+ if (yychar != YYEMPTY) \
+ parser->lexer_->push_extra_token \
+ (yylloc, yychar, yylval); \
+ parser->lexer_->push_extra_token \
+ (Location, Token, Value); \
+ parser->lexer_->push_extra_token \
+ (Location, REPARSE, Pred); \
+ yychar = YYEMPTY; \
+ } while (0)
%}
SCM proc = parser->lexer_->lookup_identifier ("toplevel-bookpart-handler");
scm_call_2 (proc, parser->self_scm (), $1);
}
+ | BOOK_IDENTIFIER {
+ SCM proc = parser->lexer_->lookup_identifier
+ (unsmob_book($1)->paper_
+ ? "toplevel-book-handler"
+ : "toplevel-bookpart-handler");
+ scm_call_2 (proc, parser->self_scm (), $1);
+ }
| score_block {
SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler");
scm_call_2 (proc, parser->self_scm (), $1);
{
SCM proc = parser->lexer_->lookup_identifier ("toplevel-text-handler");
scm_call_2 (proc, parser->self_scm (), out);
+ } else if (unsmob_score ($1))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("toplevel-score-handler");
+ scm_call_2 (proc, parser->self_scm (), $1);
} else if (!scm_is_eq ($1, SCM_UNSPECIFIED))
parser->parser_error (@1, _("bad expression type"));
}
{
SCM proc = parser->lexer_->lookup_identifier ("book-text-handler");
scm_call_2 (proc, $1, out);
+ } else if (unsmob_score ($2))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("book-score-handler");
+ scm_call_2 (proc, $1, $2);
} else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _("bad expression type"));
}
{
SCM proc = parser->lexer_->lookup_identifier ("bookpart-text-handler");
scm_call_2 (proc, $1, out);
+ } else if (unsmob_score ($2))
+ {
+ SCM proc = parser->lexer_->lookup_identifier ("bookpart-score-handler");
+ scm_call_2 (proc, $1, $2);
} else if (!scm_is_eq ($2, SCM_UNSPECIFIED))
parser->parser_error (@2, _("bad expression type"));
}
score_block:
SCORE '{' score_body '}' {
+ unsmob_score ($3)->origin ()->set_spot (@$);
$$ = $3;
}
;
SCM scorify = ly_lily_module_constant ("scorify-music");
$$ = scm_call_2 (scorify, $2, parser->self_scm ());
- unsmob_score ($$)->origin ()->set_spot (@2);
if (scm_is_pair ($1) && ly_is_module (scm_car ($1)))
{
unsmob_score ($$)->set_header (scm_car ($1));
}
}
| embedded_scm_active {
- Score *score;
- if (unsmob_score ($1))
- score = new Score (*unsmob_score ($1));
- else {
- score = new Score;
+ if (!unsmob_score ($1))
+ {
+ $$ = (new Score)->unprotect ();
parser->parser_error (@1, _("score expected"));
}
- unsmob_score ($$)->origin ()->set_spot (@$);
- $$ = score->unprotect ();
}
| score_body
{
else {
$$ = scm_cons (loc_on_music (@3, $1), $3);
MYBACKUP (UNSIGNED, $5, @5);
- parser->lexer_->push_extra_token ('-');
+ parser->lexer_->push_extra_token (@4, '-');
}
}
(scm_object_property (scm_car ($1),
ly_symbol2scm ("is-grob?")))) {
$$ = ly_symbol2scm ("Bottom");
- parser->lexer_->push_extra_token (SCM_IDENTIFIER, $1);
+ parser->lexer_->push_extra_token (@1, SCM_IDENTIFIER, $1);
} else {
$$ = scm_car ($1);
- parser->lexer_->push_extra_token (SCM_IDENTIFIER,
+ parser->lexer_->push_extra_token (@1, SCM_IDENTIFIER,
scm_cdr ($1));
}
}
;
event_function_event:
- EVENT_FUNCTION function_arglist_closed {
+ EVENT_FUNCTION function_arglist {
$$ = MAKE_SYNTAX ("music-function", @$,
$1, $2);
}
direction_less_event {
$$ = $1;
}
- | script_dir music_function_call_closed {
+ | script_dir music_function_call {
$$ = $2;
if (!unsmob_music ($2)->is_mus_type ("post-event")) {
parser->parser_error (@2, _ ("post-event expected"));
;
questions:
- { $$ = SCM_UNDEFINED; }
+// This precedence rule is rather weird. It triggers when '!' is
+// encountered after a pitch, and is used for deciding whether to save
+// this instead for a figure modification. This should not actually
+// occur in practice as pitches and figures are generated in different
+// modes. Using a greedy (%right) precedence makes sure that we don't
+// get stuck in a wrong interpretation.
+ { $$ = SCM_UNDEFINED; } %prec ':'
| questions '?'
{
if (SCM_UNBNDP ($1))
SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
parser->lexer_->push_note_state (nn);
} '{' score_body '}' {
+ unsmob_score ($4)->origin ()->set_spot (@$);
$$ = scm_list_1 (scm_list_2 (ly_lily_module_constant ("score-lines-markup-list"), $4));
parser->lexer_->pop_state ();
}
SCM nn = parser->lexer_->lookup_identifier ("pitchnames");
parser->lexer_->push_note_state (nn);
} '{' score_body '}' {
+ unsmob_score ($4)->origin ()->set_spot (@$);
$$ = scm_list_2 (ly_lily_module_constant ("score-markup"), $4);
parser->lexer_->pop_state ();
}
*destination = p->self_scm ();
p->unprotect ();
return OUTPUT_DEF_IDENTIFIER;
+ } else if (unsmob_score (sid)) {
+ *destination = unsmob_score (sid)->clone ()->unprotect ();
+ return SCM_IDENTIFIER;
}
return -1;
lex->lexval_ = s;
lex->lexloc_ = loc;
+ int tok = lex->pop_extra_token ();
+ if (tok >= 0)
+ return tok;
lex->prepare_for_next_token ();
return lex->yylex ();
}