%{ // -*-Fundamental-*-
+/*
+ lexer.l -- implement the Flex lexer
+
+ source file of the LilyPond music typesetter
+
+ (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+/*
+ backup rules
+
+ after making a change to the lexer rules, run
+ flex -b <this lexer file>
+ and make sure that
+ lex.backup
+ contains no backup states, but only the reminder
+ Compressed tables always back up.
+ (don-t forget to rm lex.yy.cc :-)
+ */
+
#include <stdio.h>
+#include <ctype.h>
#include "string.hh"
#include "string-convert.hh"
#include "varray.hh"
#include "parser.hh"
#include "debug.hh"
-#include "input-score.hh"
#include "parseconstruct.hh"
#include "main.hh"
#include "identifier.hh"
+void strip_trailing_white(String&);
+void strip_leading_white(String&);
+
#define start_quote() \
yy_push_state(quote);\
%option warn
%x incl
+%x header
%x lyrics
%x notes
%x quote
-
+%x longcomment
A [a-zA-Z]
WORD {A}{AN}*
ALPHAWORD {A}+
INT -?{N}+
-REAL {INT}?(\.{N}+)?
+REAL ({INT}\.{N}*)|(-?\.{N}+)
KEYWORD \\{WORD}
WHITE [ \n\t\f]
+HORIZONTALWHITE [ \t]
BLACK [^ \n\t\f]
RESTNAME [rs]
-NOTECOMMAND \\{WORD}
-DOTS \.+
-LYRICS {AA}[^0-9 \t\n\f]*
-COMMENT %.*\n
+NOTECOMMAND \\{A}+
+LYRICS ({AA}|{NATIONAL})[^0-9 \t\n\f]*
%%
-<lyrics,INITIAL,notes>{COMMENT} {
+
+<notes,incl,INITIAL,lyrics>{
+ "%{" {
+ yy_push_state(longcomment);
+ }
+ %[^{\n].*\n {
+ }
+ %[^{\n] { // backup rule
+ }
+ %\n {
+ }
+ %[^{\n].* {
+ }
+ {WHITE}+ {
+
+ }
}
+<longcomment>{
+ [^\%]* {
+ }
+ \%*[^}%]* {
+ }
+ "%"+"}" {
+ yy_pop_state();
+ }
+ <<EOF>> {
+ LexerError("EOF found inside a comment");
+ if (! close_input())
+ yyterminate(); // can't move this, since it actually rets a YY_NULL
+ }
+}
+<header>{
+ [\{\}] {
+ return YYText()[0];
+ }
+ ^{WORD} {
+ String s=YYText();
+ yylval.string = new String(s);
+ return FIELDNAME;
+ }
+ {HORIZONTALWHITE}+{BLACK}.*\n {
+ String s=YYText();
+ strip_leading_white(s);
+ strip_trailing_white(s);
+ yylval.string = new String(s);
+ return RECORDLINE;
+ }
+ {WHITE}* {
+ }
-<notes,INITIAL,lyrics>
-\\include {
+ . {
+ return YYText()[0];
+ }
+}
+
+
+<notes,INITIAL,lyrics>\\include {
yy_push_state(incl);
}
-<incl>{WHITE}* { /* eat the whitespace */ }
<incl>\"[^"]*\" { /* got the include file name */
String s (YYText()+1);
s = s.left_str(s.length_i()-1);
- mtor << "#include `" << s << "\'\n";
+ DOUT << "#include `" << s << "\'\n";
new_input(s,source_l_g);
yy_pop_state();
}
-<*>{WHITE}+ {
-
+<incl>\"[^"]* { // backup rule
+ cerr << "missing end quote" << endl;
+ exit( 1 );
}
<notes>{RESTNAME} {
const char *s = YYText();
yylval.string = new String (s);
- mtor << "rest:"<< yylval.string;
+ DOUT << "rest:"<< yylval.string;
return RESTNAME;
}
<INITIAL,lyrics,notes>\\\${BLACK}*{WHITE} {
s=s.left_str(s.length_i() - 1);
return scan_bare_word(s);
}
-<notes>{ALPHAWORD}/\' {
- post_quotes_b_ = true;
- return scan_bare_word(YYText());
+<INITIAL,lyrics,notes>\\\${BLACK}* { // backup rule
+ cerr << "white expected" << endl;
+ exit( 1 );
}
-<notes>\'+ {
- yylval.i = YYLeng();
- if (post_quotes_b_) {
- post_quotes_b_ = false;
- return POST_QUOTES;
- } else
- return PRE_QUOTES;
+<INITIAL,lyrics,notes>\${BLACK}* { // backup rule
+ cerr << "white expected" << endl;
+ exit( 1 );
}
-<notes>{ALPHAWORD} {
- return scan_bare_word(YYText());
+<notes>{
+ {ALPHAWORD}/\' {
+ post_quotes_b_ = true;
+ return scan_bare_word(YYText());
+ }
+ \'+ {
+ yylval.i = YYLeng();
+ if (post_quotes_b_) {
+ post_quotes_b_ = false;
+ return POST_QUOTES;
+ } else
+ return PRE_QUOTES;
+ }
+ {ALPHAWORD} {
+ return scan_bare_word(YYText());
-}
+ }
-<notes>{NOTECOMMAND} {
- return scan_escaped_word(YYText()+1);
-}
+ {NOTECOMMAND} {
+ return scan_escaped_word(YYText()+1);
+ }
-<notes>{DOTS} {
- yylval.i = strlen(YYText());
- return DOTS;
-}
-<notes>{INT} {
- yylval.i = String_convert::dec2_i( String( YYText() ) );
- return INT;
-}
+ {INT} {
+ yylval.i = String_convert::dec2_i( String( YYText() ) );
+ return INT;
+ }
-<notes>\+\+ {
- return CONCAT;
-}
-<notes>\" {
- start_quote();
+ \" {
+ start_quote();
+ }
}
-
\" {
start_quote();
}
-<quote>\\\\ {
- *yylval.string += '\\';
-}
-<quote>\\\" {
- *yylval.string +='\"';
-}
-<quote>[^"]+ {
- *yylval.string += YYText();
-}
-<quote>\" {
- mtor << "quoted string: `" << *yylval.string << "'\n";
- yy_pop_state();
- return STRING;
+<quote>{
+ \\\\ {
+ *yylval.string += '\\';
+ }
+ \\\" {
+ *yylval.string +='\"';
+ }
+ [^"]+ {
+ *yylval.string += YYText();
+ }
+ \" {
+ DOUT << "quoted string: `" << *yylval.string << "'\n";
+ yy_pop_state();
+ return STRING;
+ }
}
-<lyrics>\" {
- start_quote();
-}
-<lyrics>{DOTS} {
- yylval.i = strlen(YYText());
- return DOTS;
-}
-<lyrics>{INT} {
- yylval.i = String_convert::dec2_i( String( YYText() ) );
- return INT;
-}
-<lyrics>{NOTECOMMAND} {
- return scan_escaped_word(YYText()+1);
-}
-<lyrics>{LYRICS} {
- /* ugr. This sux. */
- String s (YYText());
- int i = 0;
- while ((i=s.index_i("_")) != -1) // change word binding "_" to " "
- *(s.ch_l() + i) = ' ';
- if ((i=s.index_i("\\,")) != -1) // change "\," to TeX's "\c "
- {
- *(s.ch_l() + i + 1) = 'c';
- s = s.left_str(i+2) + " " + s.right_str(s.length_i()-i-2);
- }
- yylval.string = new String(s);
- mtor << "lyric : `" << s << "'\n";
- return STRING;
-}
-<lyrics>\| {
- return YYText()[0];
-}
-<lyrics>[{}] {
- return YYText()[0];
-}
-<lyrics>. {
- return yylval.c = YYText()[0];
+<lyrics>{
+
+ \" {
+ start_quote();
+ }
+ {INT} {
+ yylval.i = String_convert::dec2_i( String( YYText() ) );
+ return INT;
+ }
+ {NOTECOMMAND} {
+ return scan_escaped_word(YYText()+1);
+ }
+ {LYRICS} {
+ /* ugr. This sux. */
+ String s (YYText());
+ int i = 0;
+ while ((i=s.index_i("_")) != -1) // change word binding "_" to " "
+ *(s.ch_l() + i) = ' ';
+ if ((i=s.index_i("\\,")) != -1) // change "\," to TeX's "\c "
+ {
+ *(s.ch_l() + i + 1) = 'c';
+ s = s.left_str(i+2) + " " + s.right_str(s.length_i()-i-2);
+ }
+ yylval.string = new String(s);
+ DOUT << "lyric : `" << s << "'\n";
+ return STRING;
+ }
+ . {
+ return yylval.c = YYText()[0];
+ }
}
<<EOF>> {
- mtor << "<<eof>>";
+ DOUT << "<<eof>>";
if (! close_input()) {
yyterminate(); // can't move this, since it actually rets a YY_NULL
Real r;
int cnv=sscanf (YYText(), "%lf", &r);
assert(cnv == 1);
- mtor << "REAL" << r<<'\n';
+ DOUT << "REAL" << r<<'\n';
yylval.real = r;
return REAL;
}
+{INT} {
+ yylval.i = String_convert::dec2_i( String( YYText() ) );
+ return INT;
+}
+
[{}] {
- mtor << "parens\n";
+ DOUT << "parens\n";
return YYText()[0];
}
[*:=] {
char c = YYText()[0];
- mtor << "misc char" <<c<<"\n";
+ DOUT << "misc char" <<c<<"\n";
return c;
}
<INITIAL,notes>. {
return yylval.c = YYText()[0];
}
+
<INITIAL,lyrics,notes>\\. {
char c= YYText()[1];
yylval.c = c;
int
My_lily_lexer::scan_escaped_word(String str)
{
- mtor << "\\word: `" << str<<"'\n";
+ DOUT << "\\word: `" << str<<"'\n";
int l = lookup_keyword(str);
if (l != -1) {
- mtor << "(keyword)\n";
+ DOUT << "(keyword)\n";
return l;
}
Identifier * id = lookup_identifier(str);
if (id) {
- mtor << "(identifier)\n";
+ DOUT << "(identifier)\n";
yylval.id = id;
return id->token_code_i_;
}
- mtor << "(string)";
+ if ( YYSTATE != notes ) {
+ Melodic_req * mel_l = lookup_melodic_req_l(str);
+ if (mel_l) {
+ DOUT << "(notename)\n";
+ yylval.melreq = mel_l;
+ return NOTENAME_ID;
+ }
+ }
+ LexerError( "Unknown escaped string: `" + str + "'");
+ DOUT << "(string)";
String *sp = new String( str);
yylval.string=sp;
return STRING;
int
My_lily_lexer::scan_bare_word(String str)
{
- mtor << "word: `" << str<< "'\n";
+ DOUT << "word: `" << str<< "'\n";
if (YYSTATE == notes){
Melodic_req * mel_l = lookup_melodic_req_l(str);
if (mel_l) {
- mtor << "(notename)\n";
+ DOUT << "(notename)\n";
yylval.melreq = mel_l;
return NOTENAME_ID;
}
}
- if (YYSTATE != notes) {
- // ugr. Should do this in note mode?
- Identifier * id = lookup_identifier(str);
- if (id) {
- mtor << "(identifier)\n";
- yylval.id = id;
- return id->token_code_i_;
- }
- }
+
yylval.string=new String( str );
return STRING;
}
{
return YY_START == lyrics;
}
+
+void
+My_lily_lexer::push_header_state()
+{
+ yy_push_state(header);
+}
+
+void strip_trailing_white(String&s)
+{
+ int i=0;
+ for (; i < s.length_i(); i++)
+ if (!isspace(s[i]))
+ break;
+
+ s = s.nomid_str(0, i);
+}
+void strip_leading_white(String&s)
+{
+ int i=s.length_i();
+ while (i--)
+ if (!isspace(s[i]))
+ break;
+
+ s = s.left_str(i+1);
+
+}