#include "string.hh"
#include "string-convert.hh"
-#include "notename.hh"
-#include "lexer.hh"
+#include "my-lily-lexer.hh"
#include "varray.hh"
#include "parser.hh"
#include "debug.hh"
#include "input-score.hh"
#include "parseconstruct.hh"
#include "main.hh"
+#include "identifier.hh"
+#define start_quote() \
+ yy_push_state(quote);\
+ yylval.string = new String
+
+#define yylval (*(YYSTYPE*)lexval_l)
+
+#define YY_USER_ACTION add_lexed_char(YYLeng());
%}
%option c++
%option noyywrap
%option nodefault
-%option yylineno
%option debug
-%option yyclass="My_flex_lexer"
+%option yyclass="My_lily_lexer"
%option stack
+%option never-interactive
+%option warn
-%x notes
%x incl
-%x quote
%x lyrics
+%x notes
+%x quote
AA {A}|_
N [0-9]
AN {AA}|{N}
-PUNCT [?!,.:;]
-ACCENT [\\'"^]
+PUNCT [?!,.:;']
+ACCENT \\[`'"^]
NATIONAL [\241-\377]
TEX {AA}|-|{PUNCT}|{ACCENT}|{NATIONAL}
ALPHAWORD {A}+
INT -?{N}+
REAL {INT}?(\.{N}*)?
-
-OPTSIGN !?
-PITCHMOD ['`]*{OPTSIGN}
-RESTNAME r|s|p
+KEYWORD \\{WORD}
+WHITE [ \n\t\f]
+BLACK [^ \n\t\f]
+RESTNAME r
NOTECOMMAND \\{WORD}
-NOTENAME [a-z]+
-UNOTENAME [A-Z][a-z]*
DOTS \.+
-LYRICS {TEX}+
-COMMENT [%#].*\n
+LYRICS {AA}[^0-9 \t\n\f]*
+COMMENT %.*\n
%%
-\$ {
- yy_push_state(notes);
+<lyrics,INITIAL,notes>{COMMENT} {
}
-\@ {
- yy_push_state(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";
+ new_input(s,source_l_g);
+ yy_pop_state();
}
<notes>{RESTNAME} {
mtor << "rest:"<< yylval.string;
return RESTNAME;
}
-<notes>{UNOTENAME} {
- int *p=yylval.ii;
- return ret_notename(p, YYText(), -1);
+<INITIAL,lyrics,notes>\\\${BLACK}*{WHITE} {
+ String s=YYText() + 2;
+ s=s.left_str(s.length_i() - 1);
+ return scan_escaped_word(s);
+}
+<INITIAL,lyrics,notes>\${BLACK}*{WHITE} {
+ String s=YYText() + 1;
+ s=s.left_str(s.length_i() - 1);
+ return scan_bare_word(s);
+}
+<notes>{ALPHAWORD}/\' {
+ post_quotes_b_ = true;
+ return scan_bare_word(YYText());
+}
+<notes>\'+ {
+ yylval.i = YYLeng();
+ if (post_quotes_b_) {
+ post_quotes_b_ = false;
+ return POST_QUOTES;
+ } else
+ return PRE_QUOTES;
}
+<notes>{ALPHAWORD} {
+ return scan_bare_word(YYText());
-<notes>{NOTENAME} {
- int *p=yylval.ii;
- return ret_notename(p, YYText(), 0);
}
<notes>{NOTECOMMAND} {
- String c = YYText() +1;
- mtor << "\\word: " << YYText()+1<<eol;
- int l = lookup_keyword(c);
- if (l != -1)
- return l;
- Identifier * id = lookup_identifier(c);
- if (id) {
- yylval.id = id;
- return IDENTIFIER;
- }
- String *sp = new String( c);
- yylval.string=sp;
- return STRING;
+ return scan_escaped_word(YYText()+1);
}
-<notes>{PITCHMOD} {
- const char *s = YYText();
- mtor << "pitchmod:"<< YYText()<<eol;
- yylval.string = new String (s);
- return PITCHMOD;
-}
<notes>{DOTS} {
yylval.i = strlen(YYText());
return DOTS;
yylval.i = String_convert::dec2_i( String( YYText() ) );
return INT;
}
-<notes>{COMMENT} {
-}
-<notes>[ \t\n]+ {
+<notes>\+\+ {
+ return CONCAT;
}
-<notes>\$ {
- yy_pop_state();
-}
-<notes>\"[^"]*\" {
- String s (YYText()+1);
- s = s.left_str(s.length_i()-1);
- yylval.string = new String(s);
- return STRING;
-}
-<notes>. {
- return yylval.c = YYText()[0];
+<notes>\" {
+ start_quote();
}
+
\" {
- yy_push_state(quote);
+ start_quote();
}
-<quote>[^"]* {
- yylval.string = new String (YYText());
+<quote>\\\\ {
+ *yylval.string += '\\';
+}
+<quote>\\\" {
+ *yylval.string +='\"';
+}
+<quote>[^"]+ {
+ *yylval.string += YYText();
}
<quote>\" {
- mtor << "quoted string\n";
+ mtor << "quoted string: `" << *yylval.string << "'\n";
yy_pop_state();
return STRING;
}
+<lyrics>\" {
+ start_quote();
+}
<lyrics>{DOTS} {
yylval.i = strlen(YYText());
return DOTS;
return INT;
}
<lyrics>{NOTECOMMAND} {
- String c = YYText() +1;
- mtor << "\\word: " << YYText()+1<<eol;
- int l = lookup_keyword(c);
- if (l != -1)
- return l;
-
-/* let's try passing tex's typesetting macros like \ss \alpha \c */
- String* str_p = new String(YYText());//huh?
- return STRING;
-
-/* and skip identifiers...
- Identifier * id = lookup_identifier(c);
- if (id) {
- yylval.id = id;
- return IDENTIFIER;
- }
- String *sp = new String( c);
-
- yylval.string=sp;
- return STRING;
-*/
-}
-<lyrics>\"[^"]*\" {
- String s (YYText()+1);
- s = s.left_str(s.length_i()-1);
- yylval.string = new String(s);
- return STRING;
+ 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 = 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>{COMMENT} {
-
}
<lyrics>[{}] {
return YYText()[0];
<lyrics>[()\[\]|/.^>_-] {
return yylval.c = YYText()[0];
}
-<lyrics>[ \t\n]+ {
-}
-<lyrics>@ {
- yy_pop_state();
-}
<<EOF>> {
- mtor << "<<EOF>>";
+ mtor << "<<eof>>";
- if (! close_input())
+ if (! close_input()) {
yyterminate(); // can't move this, since it actually rets a YY_NULL
+ }
}
-
-
-include {
- yy_push_state(incl);
-}
-<incl>[ \t]* { /* eat the whitespace */ }
-<incl>\"[^"]*\"+ { /* got the include file name */
- String s (YYText()+1);
- s = s.left_str(s.length_i()-1);
- defined_ch_c_l = here_ch_c_l() - String( YYText() ).length_i() - 1;
- new_input(s);
- yy_pop_state();
+{WORD} {
+ return scan_bare_word(YYText());
}
-
-
-{WORD} {
- mtor << "word: " << YYText()<<eol;
- String c = YYText();
- int l = lookup_keyword(c);
- if (l != -1)
- return l;
- Identifier * id = lookup_identifier(c);
- if (id) {
- yylval.id = id;
- return IDENTIFIER;
- }
- String *sp = new String( c);
- mtor << "new id: " << *sp << eol;
- yylval.string=sp;
- return STRING;
+{KEYWORD} {
+ return scan_escaped_word(YYText()+1);
}
-
{REAL} {
Real r;
int cnv=sscanf (YYText(), "%lf", &r);
mtor << "misc char" <<c<<"\n";
return c;
}
-[ \t\n]+ {
+<*>{WHITE}+ {
}
-
-{COMMENT} {
- //ignore
+<notes>. {
+ return yylval.c = YYText()[0];
}
-. {
- error( String( "illegal character: " ) + String( YYText()[0] ), here_ch_c_l() );
+
+<*>. {
+ LexerError( String( "illegal character: " ) +String( YYText()[0] ));
return YYText()[0];
}
%%
+void
+My_lily_lexer::push_note_state()
+{
+ yy_push_state(notes);
+}
+
+void
+My_lily_lexer::push_lyric_state()
+{
+ yy_push_state(lyrics);
+}
+void
+My_lily_lexer::pop_state()
+{
+ yy_pop_state();
+}
+
+int
+My_lily_lexer::scan_escaped_word(String str)
+{
+ mtor << "\\word: `" << str<<"'\n";
+ int l = lookup_keyword(str);
+ if (l != -1) {
+ mtor << "(keyword)\n";
+ return l;
+ }
+ String *sp = new String( str);
+ yylval.string=sp;
+ return STRING;
+}
+int
+My_lily_lexer::scan_bare_word(String str)
+{
+ mtor << "word: `" << str<< "'\n";
+ 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;
+}
+
+bool
+My_lily_lexer::note_state_b() const
+{
+ return YY_START == notes;
+}
+
+bool
+My_lily_lexer::lyric_state_b() const
+{
+ return YY_START == lyrics;
+}