%{ // -*-Fundamental-*- /* lexer.l -- implement the Flex lexer source file of the LilyPond music typesetter (c) 1996--2000 Han-Wen Nienhuys
Jan Nieuwenhuizen Modified as a front end GUI for lilypond: (c) 2003-2005 Richard Shann */ #include{ \\{ESCAPED} { g_string_append_c (quoted_string, escaped_char (*(yytext+1))); } [^\\"]+ { g_string_append (quoted_string, yytext); } \" { end_quote(); RETURN (STRING_); } . { g_string_append (quoted_string, yytext); } }{ \" { start_quote (); } {FRACTION} { scan_fraction(yytext, &lylval.t.t); RETURN (FRACTION); } {UNSIGNED} { lylval.i.i = atoi (YYText ()); RETURN (UNSIGNED); } {NOTECOMMAND} { return scan_escaped_word (YYText () + 1); } {LYRICS} { if (!strcmp(yytext, "__")) RETURN (EXTENDER); if (!strcmp(yytext, "--")) RETURN (HYPHEN); lylval.gstr.gstr = g_string_new(yytext); RETURN (STRING_); } . { RETURN (*yytext); } } { {ALPHAWORD} { return scan_bare_word (YYText ()); } {NOTECOMMAND} { return scan_escaped_word (YYText () + 1); } {FRACTION} { scan_fraction(yytext, &lylval.t.t); RETURN (FRACTION); } {UNSIGNED} { lylval.i.i = atoi (YYText ()); RETURN (UNSIGNED); } \" { start_quote (); } - { RETURN (CHORD_MINUS); } : { RETURN (CHORD_COLON); } \/\+ { RETURN (CHORD_BASS); } \^ { RETURN (CHORD_CARET); } . { RETURN (*yytext); } } < > { set_trailing_white_space(input_text); g_free(input_text);input_text=NULL;/* note that YY_USER_ACTION has not been run */ yyterminate (); } {WORD} { return scan_bare_word (YYText ()); } {KEYWORD} { return scan_escaped_word (YYText () + 1); } {REAL} { double r; int cnv=sscanf (YYText (), "%lf", &r); g_assert (cnv == 1); lylval.r.r = r; RETURN (REAL); } {UNSIGNED} { lylval.i.i = atoi (YYText ()); RETURN (UNSIGNED); } [{}] { RETURN (*yytext); } [*:=] { char c = YYText ()[0]; RETURN (c); } . { RETURN (*yytext); } \\. { char c= *(yytext+1); switch (c) { case '>': RETURN (E_BIGGER); case '<': RETURN (E_SMALLER); case '!': RETURN (E_EXCLAMATION); case '(': RETURN (E_OPEN); case ')': RETURN (E_CLOSE); case '[': RETURN (E_LEFTSQUARE); case ']': RETURN (E_RIGHTSQUARE); case '~': RETURN (E_TILDE); case '\\': RETURN (E_BACKSLASH); default: RETURN (E_CHAR); } } <*>. { g_error("invalid character: `%c'", *yytext); RETURN (*yytext); } %% void push_note_state () { yy_push_state (notes); } void push_figuredbass_state () { yy_push_state (figures); } void push_chord_state () { yy_push_state (chords); } void push_lyric_state () { yy_push_state (lyrics); } void pop_state () { yy_pop_state (); } int scan_escaped_word (gchar * str) { nodeglist *sid; /* a definition of an identifier already turned into a typed glist by the parser encountering an assignment */ nodegstr *scm_str; int look = lookup_keyword (str); if (look != -1) { RETURN (look); /* this is many of the tokens eg /times and so on */ } sid = lookup_identifier (str); /* there follows all the things that can have been defined using the = syntax */ if (sid) { lylval.id.id = sid->branch; RETURN (sid->type); } scm_str = lookup_scm_identifier (str); if (scm_str) { lylval.gstr.type = scm_str->type; lylval.gstr.gstr = g_string_new (scm_str->gstr->str); return scm_str->type; } if ((YYSTATE != notes) && (YYSTATE != chords)) { #ifdef LATER /* SCM pitch = scm_hashq_get_handle (pitchname_tab_, str); some sort of lookup of pitchnames to yield a pitch object to be stored in lylval */ if (gh_pair_p (pitch)) { lylval.id.id = ly_cdr (pitch); RETURN (NOTENAME_PITCH); } #endif } #if 0 parser_error (g_strdup_printf ("scan escaped word: Unknown escaped string: `\\%s'", str), yylineno); #endif lylval.gstr.gstr = g_string_new (yytext); RETURN (STRING_); } /* scan_bare_word takes a string and if in chords or notes it tries to interpret the word as a notename of one sort or another eg NOTENAME_PITCH etc. It uses tables for notes pitchname_tab_ and chordmodifier_tab_ which I will need to create similar things for (ultimately they can be changed by the include file). My lylval should have a field for the str and another for the pitchname in some binary form ready to be attached to a mudelaobject... Otherwise it returns a STRING_ token. */ int scan_bare_word (gchar * str) { if ((YYSTATE == notes) || (YYSTATE == chords)) { if (lookup_pitch (str)) { lylval.t.t.a = *str - 'a'; lylval.t.t.b = lookup_enshift (str + 1); RETURN ((YYSTATE != chords) ? NOTENAME_PITCH : TONICNAME_PITCH); } } #ifdef LATER else if ((pitch = scm_hashq_get_handle (chordmodifier_tab_, str)) != SCM_BOOL_F) { lylval.id.id = ly_cdr (pitch); RETURN (CHORDMODIFIER_PITCH); } #endif lylval.gstr.gstr = g_string_new (yytext); RETURN (STRING_); } gboolean note_state_b () { return YY_START == notes; } gboolean chord_state_b () { return YY_START == chords; } gboolean lyric_state_b () { return YY_START == lyrics; } gboolean figure_state_b () { return YY_START == figures; } void reset_initial_lexer_state () { while (YY_START != INITIAL) yy_pop_state (); } /* 1.3.146 == removal of ; Lilypond_version oldest_version ("1.3.146"); */ static void scan_fraction (gchar * str, struct twoints *pt) { #ifndef G_OS_WIN32 char *slash = index (lytext, '/'); sscanf (lytext, "%d", &pt->a); if (slash) sscanf (slash + 1, "%d", &pt->b); else pt->b = 1; #else char *slash; for(slash=lytext;*slash && *slash!='/';slash++) ; sscanf (lytext, "%d", &pt->a); if (*slash) sscanf (slash + 1, "%d", &pt->b); else pt->b = 1; #endif } static nodeglist * lookup_identifier (gchar * str) { return (nodeglist *) g_hash_table_lookup (name_value_pairs, str); } static nodegstr * lookup_scm_identifier (gchar * str) { return (nodegstr *) g_hash_table_lookup (scm_identifiers, str); } static gboolean lookup_pitch (gchar * str) { if (*str < 'a' || *str > 'g') return FALSE; if (lookup_enshift (str + 1) == BAD_ENSHIFT) return FALSE; return TRUE; } static int lookup_enshift (gchar * str) { if (*str == 0) return 0; if (!strcmp (str, "es")) return -1; if (!strcmp (str, "is")) return 1; if (!strcmp (str, "eses")) return -2; if (!strcmp (str, "isis")) return 2; return BAD_ENSHIFT; } static char escaped_char (char c) { switch (c) { case 'n': return '\n'; case 't': return '\t'; case '\'': case '\"': case '\\': return c; } return 0; }