LCOV - code coverage report
Current view: top level - src/braille/internal - brailleinputparser.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 180 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2023 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "brailleinputparser.h"
      24              : 
      25              : #include <QString>
      26              : 
      27              : #include "braillecode.h"
      28              : 
      29              : namespace mu::engraving {
      30              : static BiePattern pattern_accord = { "accord", { &Braille_FullMeasureAccord } };
      31              : 
      32              : static BiePattern pattern_accidentals = { "accidental",
      33              :                                           { &Braille_NaturalAccidental, &Braille_SharpAccidental, &Braille_FlatAccidental } };
      34              : 
      35              : static BiePattern pattern_octaves = { "octave",
      36              :                                       { &Braille_Octave0, &Braille_Octave1, &Braille_Octave2,
      37              :                                         &Braille_Octave3, &Braille_Octave4, &Braille_Octave5,
      38              :                                         &Braille_Octave6, &Braille_Octave7, &Braille_Octave8 } };
      39              : 
      40              : static BiePattern pattern_notes ={ "note",
      41              :                                    { &Braille_aWhole, &Braille_aHalf, &Braille_aQuarter, &Braille_a8th,
      42              :                                      &Braille_bWhole, &Braille_bHalf, &Braille_bQuarter, &Braille_b8th,
      43              :                                      &Braille_cWhole, &Braille_cHalf, &Braille_cQuarter, &Braille_c8th,
      44              :                                      &Braille_dWhole, &Braille_dHalf, &Braille_dQuarter, &Braille_d8th,
      45              :                                      &Braille_eWhole, &Braille_eHalf, &Braille_eQuarter, &Braille_f8th,
      46              :                                      &Braille_fWhole, &Braille_fHalf, &Braille_fQuarter, &Braille_e8th,
      47              :                                      &Braille_gWhole, &Braille_gHalf, &Braille_gQuarter, &Braille_g8th } };
      48              : 
      49              : static BiePattern pattern_c_notes ={ "c-note",
      50              :                                      { &Braille_cWhole, &Braille_cHalf, &Braille_cQuarter, &Braille_c8th } };
      51              : 
      52              : static BiePattern pattern_dot = { "dot", { &Braille_Dot } };
      53              : static BiePattern pattern_dot_2 = { "dot-2", { &Braille_Dot } };
      54              : static BiePattern pattern_dot_3 = { "dot-3", { &Braille_Dot } };
      55              : static BiePattern pattern_tie = { "tie", { &Braille_NoteTie } };
      56              : static BiePattern pattern_note_slur = { "note-slur", { &Braille_NoteSlur } };
      57              : static BiePattern pattern_slur_start = { "long-slur-start", { &Braille_LongSlurOpenBracket } };
      58              : static BiePattern pattern_slur_stop = { "long-slur-stop", { &Braille_LongSlurCloseBracket } };
      59              : 
      60              : static BiePattern pattern_rests ={ "rest",
      61              :                                    { &Braille_RestWhole, &Braille_RestHalf, &Braille_RestQuarter, &Braille_Rest8th } };
      62              : 
      63              : static BiePattern pattern_intervals ={ "interval",
      64              :                                        { &Braille_Interval2, &Braille_Interval3, &Braille_Interval4, &Braille_Interval5,
      65              :                                          &Braille_Interval6, &Braille_Interval7, &Braille_Interval8 } };
      66              : 
      67              : static BiePattern pattern_fingerings ={ "fingering",
      68              :                                         { &Braille_Finger0, &Braille_Finger1, &Braille_Finger2,
      69              :                                           &Braille_Finger3, &Braille_Finger4, &Braille_Finger5 } };
      70              : 
      71              : static BiePattern pattern_tuplet_indicator ={ "tuplet-indicator", { &Braille_Tuplet3 } };
      72              : static BiePattern pattern_tuplet3 ={ "tuplet3", { &Braille_Tuplet3 } };
      73              : static BiePattern pattern_tuplet_prefix ={ "tuplet-prefix", { &Braille_TupletPrefix } };
      74              : static BiePattern pattern_tuplet_suffix ={ "tuplet-suffix", { &Braille_Dot } };
      75              : 
      76              : static BiePattern pattern_tuplet_numbers ={ "tuplet-number",
      77              :                                             { &Braille_Lower2, &Braille_Lower3, &Braille_Lower5, &Braille_Lower6,
      78              :                                               &Braille_Lower7, &Braille_Lower8, &Braille_Lower9 } };
      79              : 
      80            0 : static int maxPatternLength(BiePattern* pattern)
      81              : {
      82            0 :     int max = 0;
      83            0 :     for (auto code : pattern->codes) {
      84            0 :         if (code->num_cells > max) {
      85            0 :             max = code->num_cells;
      86              :         }
      87              :     }
      88            0 :     return max;
      89              : }
      90              : 
      91            0 : BieSequencePattern::BieSequencePattern(BieSequencePatternType t, std::string sequence)
      92              : {
      93            0 :     _type = t;
      94            0 :     patterns.clear();
      95            0 :     max_cell_length = 0;
      96              : 
      97            0 :     size_t len = sequence.length();
      98            0 :     QString key;
      99            0 :     bool mandatory = false;
     100            0 :     char openning = ' ';
     101            0 :     for (size_t i = 0; i < len; ++i) {
     102            0 :         char c = sequence.at(i);
     103              :         //LOGD() << i << " c=" << c << " open=" << openning;
     104            0 :         switch (c) {
     105            0 :         case '(': {
     106            0 :             if (openning != ' ') {
     107            0 :                 _valid = false;
     108            0 :                 return;
     109              :             }
     110            0 :             mandatory = true;
     111            0 :             openning = '(';
     112            0 :             break;
     113              :         }
     114            0 :         case ')': {
     115            0 :             if (openning != '(') {
     116            0 :                 _valid = false;
     117            0 :                 return;
     118              :             }
     119            0 :             openning = ' ';
     120            0 :             break;
     121              :         }
     122            0 :         case '[': {
     123            0 :             if (openning != ' ') {
     124            0 :                 _valid = false;
     125            0 :                 return;
     126              :             }
     127            0 :             mandatory = false;
     128            0 :             openning = '[';
     129            0 :             break;
     130              :         }
     131            0 :         case ']': {
     132            0 :             if (openning != '[') {
     133            0 :                 _valid = false;
     134            0 :                 return;
     135              :             }
     136            0 :             openning = ' ';
     137            0 :             break;
     138              :         }
     139            0 :         case '{': {
     140              :             // ignore
     141            0 :             break;
     142              :         }
     143            0 :         case '}': {
     144              :             // ignore
     145            0 :             break;
     146              :         }
     147            0 :         default: {
     148            0 :             key.push_back(sequence.at(i));
     149            0 :             break;
     150              :         }
     151              :         }
     152              : 
     153            0 :         if (openning == ' ' && !key.isEmpty()) {
     154              :             //LOGD() << key << " " << mandatory;
     155            0 :             BiePattern* pattern = NULL;
     156            0 :             if (key == "accord") {
     157            0 :                 pattern = &pattern_accord;
     158            0 :             } else if (key == "accord") {
     159            0 :                 pattern = &pattern_accord;
     160            0 :             } else if (key == "accidental") {
     161            0 :                 pattern = &pattern_accidentals;
     162            0 :             } else if (key == "octave") {
     163            0 :                 pattern = &pattern_octaves;
     164            0 :             } else if (key == "note") {
     165            0 :                 pattern = &pattern_notes;
     166            0 :             } else if (key == "dot") {
     167            0 :                 pattern = &pattern_dot;
     168            0 :             } else if (key == "dot-2") {
     169            0 :                 pattern = &pattern_dot_2;
     170            0 :             } else if (key == "dot-3") {
     171            0 :                 pattern = &pattern_dot_3;
     172            0 :             } else if (key == "tie") {
     173            0 :                 pattern = &pattern_tie;
     174            0 :             } else if (key == "note-slur") {
     175            0 :                 pattern = &pattern_note_slur;
     176            0 :             } else if (key == "long-slur-start") {
     177            0 :                 pattern = &pattern_slur_start;
     178            0 :             } else if (key == "long-slur-stop") {
     179            0 :                 pattern = &pattern_slur_stop;
     180            0 :             } else if (key == "rest") {
     181            0 :                 pattern = &pattern_rests;
     182            0 :             } else if (key == "interval") {
     183            0 :                 pattern = &pattern_intervals;
     184            0 :             } else if (key == "fingering") {
     185            0 :                 pattern = &pattern_fingerings;
     186            0 :             } else if (key == "tuplet-indicator") {
     187            0 :                 pattern = &pattern_tuplet_indicator;
     188            0 :             } else if (key == "tuplet3") {
     189            0 :                 pattern = &pattern_tuplet3;
     190            0 :             } else if (key == "tuplet-prefix") {
     191            0 :                 pattern = &pattern_tuplet_prefix;
     192            0 :             } else if (key == "tuplet-number") {
     193            0 :                 pattern = &pattern_tuplet_numbers;
     194            0 :             } else if (key == "tuplet-suffix") {
     195            0 :                 pattern = &pattern_tuplet_suffix;
     196            0 :             } else if (key == "c-note") {
     197            0 :                 pattern = &pattern_c_notes;
     198              :             }
     199            0 :             if (pattern != NULL) {
     200            0 :                 patterns.push_back({ pattern->name, pattern->codes, mandatory });
     201            0 :                 int n = maxPatternLength(pattern);
     202            0 :                 if (max_cell_length < n) {
     203            0 :                     max_cell_length = n;
     204              :                 }
     205            0 :                 if (mandatory) {
     206            0 :                     _mandatories++;
     207              :                 }
     208              :             }
     209            0 :             mandatory = false;
     210            0 :             key = QString();
     211              :         }
     212              :     }
     213            0 :     _valid = true;
     214            0 : }
     215              : 
     216            0 : BieSequencePattern::~BieSequencePattern()
     217              : {
     218              :     // TODO
     219            0 : }
     220              : 
     221            0 : BieSequencePatternType BieSequencePattern::type() const
     222              : {
     223            0 :     return _type;
     224              : }
     225              : 
     226            0 : bool BieSequencePattern::recognize(std::string braille)
     227              : {
     228            0 :     _res.clear();
     229              : 
     230            0 :     size_t pos = 0;
     231            0 :     size_t cursor = 0;
     232              : 
     233            0 :     int mandatory_matches = 0;
     234            0 :     while (cursor < braille.length() && pos < patterns.size()) {
     235              :         //LOGD() << "cursor: " << cursor;
     236            0 :         bool match = false;
     237            0 :         for (auto code : patterns[pos].codes) {
     238            0 :             int len = code->num_cells;
     239            0 :             if (cursor + len <= braille.length()) {
     240            0 :                 std::string bxt = braille.substr(cursor, len);
     241            0 :                 if (bxt == code->braille) {
     242              :                     //code->print();
     243            0 :                     match = true;
     244            0 :                     _res[patterns[pos].name] = code;
     245            0 :                     if (patterns[pos].mandatory) {
     246            0 :                         mandatory_matches++;
     247              :                     }
     248            0 :                     pos++;
     249            0 :                     cursor += len;
     250            0 :                     break;
     251              :                 }
     252            0 :             }
     253              :         }
     254            0 :         if (!match) {
     255            0 :             if (patterns[pos].mandatory) {
     256            0 :                 return false;
     257              :             } else {
     258            0 :                 pos++;
     259              :             }
     260              :         }
     261              :     }
     262              :     //for(std::map<std::string, braille_code *>::iterator it = _res.begin(); it != _res.end(); ++it) {
     263              :     //    LOGD() << "Key: " << it->first << " value: " << it->second->tag;
     264              :     //}
     265            0 :     return mandatory_matches == _mandatories && cursor >= braille.length();
     266              : }
     267              : 
     268            0 : const std::map<std::string, braille_code*>& BieSequencePattern::res() const
     269              : {
     270            0 :     return _res;
     271              : }
     272              : 
     273            0 : braille_code* BieSequencePattern::res(std::string key)
     274              : {
     275            0 :     return _res[key];
     276              : }
     277              : 
     278            0 : bool BieSequencePattern::valid() const
     279              : {
     280            0 :     return _valid;
     281              : }
     282              : 
     283            0 : BieSequencePattern* BieRecognize(std::string braille, bool tuplet_indicator)
     284              : {
     285              :     //static const std::string note_input_seq = "{[accord][long-slur-start][accidental][octave](note)[dot][dot-2][dot-3][fingering][note-slur][long-slur-stop][tie]}";
     286            0 :     static const std::string note_input_seq = "{[accord][long-slur-start][accidental][octave](note)}";
     287            0 :     static BieSequencePattern bie_note_input(BieSequencePatternType::Note, note_input_seq);
     288              : 
     289              :     //static const std::string rest_input_seq = "{[accord](rest)[dot][dot-2][dot-3][slur]}";
     290            0 :     static const std::string rest_input_seq = "{[accord](rest)}";
     291            0 :     static BieSequencePattern bie_rest_input(BieSequencePatternType::Rest, rest_input_seq);
     292              : 
     293            0 :     static const std::string interval_input_seq = "{[accidental][octave](interval)}";
     294            0 :     static BieSequencePattern bie_interval_input(BieSequencePatternType::Interval, interval_input_seq);
     295              : 
     296            0 :     static const std::string tuplet3_seq = "{(tuplet3)}";
     297            0 :     static BieSequencePattern bie_tuplet3(BieSequencePatternType::Tuplet3, tuplet3_seq);
     298              : 
     299            0 :     static const std::string tuplet_seq = "{(tuplet-prefix)(tuplet-number)(c-note)(tuplet-suffix)}";
     300            0 :     static BieSequencePattern bie_tuplet(BieSequencePatternType::Tuplet, tuplet_seq);
     301              : 
     302            0 :     static const std::string dot_seq = "{(dot)}";
     303            0 :     static BieSequencePattern bie_dot(BieSequencePatternType::Dot, dot_seq);
     304              : 
     305            0 :     static const std::string tie_seq = "{(tie)}";
     306            0 :     static BieSequencePattern bie_tie(BieSequencePatternType::Tie, tie_seq);
     307              : 
     308            0 :     static const std::string noteslur_seq = "{(note-slur)}";
     309            0 :     static BieSequencePattern bie_noteslur(BieSequencePatternType::NoteSlur, noteslur_seq);
     310              : 
     311            0 :     static const std::string longslur_seq = "{(long-slur-stop)}";
     312            0 :     static BieSequencePattern bie_longslur(BieSequencePatternType::LongSlurStop, longslur_seq);
     313              : 
     314            0 :     BieSequencePattern* res = NULL;
     315              : 
     316            0 :     if (!tuplet_indicator) { // check note input before tuplet
     317            0 :         if (bie_note_input.valid() && bie_note_input.recognize(braille)) {
     318            0 :             res = &bie_note_input;
     319            0 :         } else if (bie_rest_input.valid() && bie_rest_input.recognize(braille)) {
     320            0 :             res = &bie_rest_input;
     321            0 :         } else if (bie_interval_input.valid() && bie_interval_input.recognize(braille)) {
     322            0 :             res = &bie_interval_input;
     323            0 :         } else if (bie_tuplet3.valid() && bie_tuplet3.recognize(braille)) {
     324            0 :             res = &bie_tuplet3;
     325              :             //} else if(bie_tuplet.valid() && bie_tuplet.recognize(braille)) {
     326              :             //    res = &bie_tuplet;
     327            0 :         } else if (bie_tie.valid() && bie_tie.recognize(braille)) {
     328            0 :             res = &bie_tie;
     329            0 :         } else if (bie_noteslur.valid() && bie_noteslur.recognize(braille)) {
     330            0 :             res = &bie_noteslur;
     331            0 :         } else if (bie_longslur.valid() && bie_longslur.recognize(braille)) {
     332            0 :             res = &bie_longslur;
     333            0 :         } else if (bie_dot.valid() && bie_dot.recognize(braille)) {
     334            0 :             res = &bie_dot;
     335              :         }
     336              :     } else { // check tuplet input
     337            0 :         if (bie_tuplet.valid() && bie_tuplet.recognize(braille)) {
     338            0 :             res = &bie_tuplet;
     339              :         }
     340              :     }
     341              : 
     342            0 :     return res;
     343              : }
     344              : }
        

Generated by: LCOV version 2.0-1