--- /dev/null
+%{ // -*-Fundamental-*-
+
+#include <fstream.h>
+#include <stdio.h>
+#include "glob.hh"
+#include "string.hh"
+
+#include "lexer.hh"
+#include "keyword.hh"
+#include "vray.hh"
+#include "parser.hh"
+#include "debug.hh"
+
+sstack<istream *> include_stack;
+static int last_print;
+const int DOTPRINT=50; // every 50 lines dots
+%}
+
+%option c++
+%option noyywrap
+%option nodefault
+%option yylineno
+%option debug
+%x notes
+%x incl
+%x quote
+
+
+NOTECOMMAND \\{WORD}
+OPTSIGN !?
+NOTENAMEI A|B|C|D|E|F|G|As|Bes|Ces|Des|Es|Fes|Ges|Ais|Bis|Cis|Dis|Eis|Fis|Gis
+NOTENAMEII a|b|c|d|e|f|g|as|bes|ces|des|es|fes|ges|ais|bis|cis|dis|eis|fis|gis
+NOTENAMEIII Ases|Beses|Ceses|Deses|Eses|Feses|Geses|Aisis|Bisis|Cisis|Disis|Eisis|Fisis|Gisis
+NOTENAMEIIII ases|beses|ceses|deses|eses|feses|geses|aisis|bisis|cisis|disis|eisis|fisis|gisis
+RESTNAME r|s
+NOTENAME {NOTENAMEI}|{NOTENAMEII}|{NOTENAMEIII}|{NOTENAMEIIII}
+PITCH ['`]*{OPTSIGN}{NOTENAME}
+DURNAME 1|2|4|8|16|32
+DURATION {DURNAME}\.*
+FULLNOTE {PITCH}{DURATION}?
+WORD [a-zA-Z][a-zA-Z0-9_]+
+REAL [0-9]+(\.[0-9]*)?
+
+%%
+
+\$ {
+ BEGIN(notes); return '$';
+}
+
+<notes>{NOTECOMMAND} {
+ String c = YYText() +1;
+ int l = lookup_keyword(c);
+ if (l == -1) {
+ String e("unknown NOTECOMMAND: \\");
+ e += c;
+ yyerror(e);
+ }
+ return l;
+}
+
+<notes>{RESTNAME} {
+ const char *s = YYText();
+ yylval.string = new String (s);
+ mtor << "rest:"<< yylval.string;
+ return RESTNAME;
+}
+<notes>{PITCH} {
+ const char *s = YYText();
+ yylval.string = new String (s);
+ mtor << "pitch:"<< *yylval.string;
+ return PITCH;
+}
+<notes>{DURATION} {
+ yylval.string = new String (YYText());
+ return DURATION;
+}
+<notes>\| {
+}
+<notes>[:space:]+ {
+}
+<notes>[ \t\n]+ {
+}
+<notes>%.* {
+
+}
+<notes>\$ {
+ BEGIN(INITIAL); return '$';
+}
+<notes>[\[){] { /* parens () are NO mistake */
+ yylval.c = YYText()[0];
+ return OPEN_REQUEST_PARENS;
+}
+<notes>[\]()}] { /* parens () are NO mistake */
+ yylval.c = YYText()[0];
+ return CLOSE_REQUEST_PARENS;
+}
+
+<notes>. {
+ String s("lexer error: illegal character found: " + String(YYText()));
+ yyerror(s);
+}
+
+\" {
+ BEGIN(quote);
+}
+<quote>[^\"]* {
+ yylval.string = new String (YYText());
+}
+<quote>\" {
+ BEGIN(INITIAL);
+ return STRING;
+}
+
+<<EOF>> {
+ if(!close_input())
+ yyterminate();
+}
+{WORD} {
+ int l = lookup_keyword(YYText());
+ if (l != -1)
+ return l;
+ Identifier * id = lookup_identifier(YYText());
+ if (id) {
+ yylval.id = id;
+ return IDENTIFIER;
+ }
+ String *sp = new String( YYText());
+ mtor << "new id: " << *sp;
+ yylval.string=sp;
+ return NEWIDENTIFIER;
+}
+
+{REAL} {
+ Real r;
+ int cnv=sscanf (YYText(), "%lf", &r);
+ assert(cnv == 1);
+ mtor << "token (REAL)" << r;
+ yylval.real = r;
+ return REAL;
+}
+
+[\{\}\[\]\(\)] {
+
+ mtor << "parens\n";
+ return YYText()[0];
+}
+[:=] {
+ char c = YYText()[0];
+ mtor << "misc char" <<c<<"\n";
+ return c;
+}
+[ \t\n]+ {
+
+}
+
+%.* {
+ //ignore
+}
+. {
+ error("lexer error: illegal character '"+String(YYText()[0])+
+ "' encountered");
+ return YYText()[0];
+}
+
+%%
+
+yyFlexLexer *lexer=0;
+
+// set the new input to s, remember old file.
+void
+new_input(String s)
+{
+ istream *newin ;
+
+ if (s=="")
+ newin = &cin;
+ else
+ newin = new ifstream( s ); //
+
+ if ( ! *newin)
+ error("cant open " + s);
+ cout << "["<<s<<flush;
+
+ include_stack.push(newin);
+
+ if (!lexer) {
+ lexer = new yyFlexLexer;
+ lexer->set_debug( !monitor.silence("Lexer"));
+ }
+
+ lexer->switch_streams(newin);
+}
+
+
+// pop the inputstack.
+bool
+close_input()
+{
+
+ istream *closing= include_stack.pop();
+ if (closing != &cin)
+ delete closing;
+
+ cout << "]" << flush;
+
+ if (include_stack.empty()) {
+ return false ;
+ } else
+ lexer->switch_streams(include_stack.top());
+ return true;
+}
+
+int
+yylex() {
+ return lexer->yylex();
+}
+
+void
+yyerror(const char *s)
+{
+ *mlog << "error in line " << lexer->lineno() << ": " << s << '\n';
+ exit(1);
+}
+
+void
+kill_lexer()
+{
+ delete lexer;
+}
--- /dev/null
+%{ // -*-Fundamental-*-
+#include <iostream.h>
+
+#include "lexer.hh"
+#include "paper.hh"
+#include "staff.hh"
+#include "score.hh"
+#include "main.hh"
+#include "keyword.hh"
+#include "scommands.hh"
+#include "debug.hh"
+#include "parseconstruct.hh"
+#include "dimen.hh"
+#include "identifier.hh"
+
+#ifndef NDEBUG
+#define YYDEBUG 1
+#endif
+
+svec<Request*> pre_reqs, post_reqs;
+%}
+
+
+%union {
+ Real real;
+ Command *command;
+ Identifier *id;
+ Score_commands *scommands;
+ Voice *voice;
+ Voice_element *el;
+ Staff *staff;
+ String *string;
+ Score *score;
+ const char *consstr;
+ Paperdef *paper;
+ Request* request;
+ int i;
+ char c;
+}
+
+%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
+%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
+%token MELODICSTAFF GEOMETRIC START_T DURATIONCOMMAND OCTAVECOMMAND
+
+%token <id> IDENTIFIER
+%token <string> NEWIDENTIFIER
+%token <string> PITCH DURATION RESTNAME
+%token <real> REAL
+%token <string> STRING
+%token <i> OPEN_REQUEST_PARENS CLOSE_REQUEST_PARENS
+
+
+%type <consstr> unit
+
+%type <id> declaration
+%type <paper> paper_block paper_body
+%type <real> dim
+%type <voice> voice_block voice_body voice_elts voice_elts_dollar
+%type <el> voice_elt
+%type <command> score_command
+%type <score> score_block score_body
+%type <staff> staff_block rhythmstaff_block rhythmstaff_body
+%type <staff> melodicstaff_block melodicstaff_body staffdecl
+%type <i> int
+%type <scommands> score_commands_block score_commands_body
+%type <request> post_request pre_request
+
+
+%%
+
+mudela: /* empty */
+ | mudela score_block {
+ add_score($2);
+ }
+ | mudela add_declaration { }
+ ;
+
+add_declaration: declaration {
+ add_identifier($1);
+ }
+ ;
+
+declaration:
+ NEWIDENTIFIER '=' staff_block {
+ $$ = new Staff_id(*$1, $3);
+ delete $1; // this sux
+ }
+ | NEWIDENTIFIER '=' voice_block {
+ $$ = new Voice_id(*$1, $3);
+ delete $1;
+ }
+ ;
+
+
+score_block: SCORE '{' score_body '}' { $$ = $3; }
+ ;
+
+score_body: { $$ = new Score; }
+ | score_body staff_block { $$->add($2); }
+ | score_body score_commands_block { $$->set($2); }
+ | score_body paper_block { $$->set($2); }
+ ;
+score_commands_block:
+ COMMANDS '{' score_commands_body '}' { $$ =$3;}
+ ;
+
+score_commands_body: { $$ = new Score_commands; }
+ | score_commands_body score_command {
+ $$->parser_add($2);
+ }
+ ;
+
+paper_block:
+ PAPER '{' paper_body '}' { $$ = $3; }
+ ;
+
+paper_body:
+ /* empty */ { $$ = new Paperdef; }
+ | paper_body WIDTH dim { $$->linewidth = $3;}
+ | paper_body OUTPUT STRING { $$->outfile = *$3;
+ delete $3;
+ }
+ | paper_body UNITSPACE dim { $$->whole_width = $3; }
+ | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
+ ;
+
+dim:
+ REAL unit { $$ = convert_dimen($1,$2); }
+ ;
+
+
+unit: CM { $$ = "cm"; }
+ |IN { $$ = "in"; }
+ |MM { $$ = "mm"; }
+ |PT { $$ = "pt"; }
+ ;
+
+/*
+ staff
+*/
+staff_block:
+ staffdecl
+ | rhythmstaff_block
+ | melodicstaff_block
+ ;
+
+staffdecl: STAFF '{' IDENTIFIER '}' { $$ = $3->staff()->clone(); }
+ ;
+
+rhythmstaff_block:
+ RHYTHMSTAFF '{' rhythmstaff_body '}' { $$ = $3; }
+ ;
+
+rhythmstaff_body:
+ /* empty */ { $$ = get_new_rhythmstaff(); }
+ | rhythmstaff_body voice_block { $$->add_voice($2); }
+ ;
+
+melodicstaff_block:
+ MELODICSTAFF '{' melodicstaff_body '}' { $$ = $3; }
+ ;
+
+melodicstaff_body:
+ /* empty */ { $$ = get_new_melodicstaff(); }
+ | melodicstaff_body voice_block { $$->add_voice($2); }
+ ;
+
+/*
+ voice
+*/
+voice_block:
+ VOICE '{' voice_body '}' { $$ = $3; }
+ ;
+
+
+voice_body:
+ IDENTIFIER { $$ = new Voice(*$1->voice()); }
+ | voice_elts_dollar { $$ = $1; }
+ | voice_body START_T REAL { $$->start = $3; }
+ ;
+
+
+
+
+voice_elts_dollar:
+ '$' voice_elts '$' { $$ = $2; }
+ ;
+
+voice_elts:
+ /* empty */ {
+ $$ = new Voice;
+ }
+ | voice_elts pre_requests voice_elt post_requests {
+ add_requests($3, pre_reqs);
+ add_requests($3, post_reqs);
+ $$->add($3);
+ }
+
+ | voice_elts voice_command { }
+ ;
+
+post_requests:
+ {
+ assert(post_reqs.empty());
+ }
+ | post_requests post_request {
+ post_reqs.add($2);
+ }
+ ;
+
+post_request:
+ CLOSE_REQUEST_PARENS { $$ = get_request($1); }
+ ;
+
+pre_requests:
+ | pre_requests pre_request {
+ pre_reqs.add($2);
+ }
+ ;
+
+pre_request:
+ OPEN_REQUEST_PARENS { $$ = get_request($1); }
+ ;
+/*
+*/
+voice_command:
+ DURATIONCOMMAND DURATION {
+ set_default_duration(*$2);
+ delete $2;
+ }
+ | OCTAVECOMMAND PITCH {
+ set_default_pitch(*$2);
+ delete $2;
+ }
+ ;
+
+voice_elt:
+ PITCH DURATION {
+ $$ = get_note_element(*$1, *$2);
+ delete $1;
+ delete $2;
+ }
+ | RESTNAME DURATION {
+ $$ = get_rest_element(*$1, *$2);
+ delete $1;
+ delete $2;
+ }
+ | PITCH { $$ = get_note_element(*$1, "");
+ delete $1;
+ }
+ | RESTNAME { $$ = get_rest_element(*$1, "");
+ delete $1;
+ }
+ ;
+
+score_command:
+ SKIP int ':' REAL {
+ $$ = get_skip_command($2, $4);
+ }
+ | METER int int {
+ $$ = get_meterchange_command($2, $3);
+ }
+/* | PARTIALMEASURE REAL {
+ $$ = get_partial_command($2);
+ }*/
+ ;
+
+
+int:
+ REAL {
+ $$ = int($1);
+ if (ABS($1-Real(int($$))) > 1e-8)
+ yyerror("expecting integer number");
+
+ }
+ ;
+
+%%
+
+void
+parse_file(String s)
+{
+ *mlog << "Parsing ... ";
+#ifdef YYDEBUG
+ yydebug = !monitor.silence("Parser");
+#endif
+ new_input(s);
+ yyparse();
+ delete_identifiers();
+ kill_lexer();
+ *mlog << "\n";
+}