-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Support Parsing "Sheet Music" into Channels
- Loading branch information
Showing
27 changed files
with
1,592 additions
and
184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: .NET Core Desktop | ||
name: Build and Test | ||
|
||
on: | ||
push: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
[assembly: InternalsVisibleTo("SoundMakerTests")] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
namespace SoundMaker.ScoreData.SMSC; | ||
public record Error | ||
{ | ||
internal Error(SMSCReadErrorType type, Token? token) | ||
{ | ||
Type = type; | ||
LineNumber = token?.LineNumber ?? 0; | ||
Literal = token?.Literal ?? ""; | ||
} | ||
|
||
/// <summary> | ||
/// Type of errors <br/> | ||
/// エラーの種類 | ||
/// </summary> | ||
public SMSCReadErrorType Type { get; } | ||
|
||
/// <summary> | ||
/// String of error location <br/> | ||
/// エラー箇所の文字列 | ||
/// </summary> | ||
public string Literal { get; } | ||
|
||
/// <summary> | ||
/// Line number of error.<br/> | ||
/// エラー箇所の行番号 | ||
/// </summary> | ||
public int LineNumber { get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace SoundMaker.ScoreData.SMSC; | ||
internal class Lexer | ||
{ | ||
private readonly Regex _alphaRegex = new("[a-z]|[A-Z]"); | ||
|
||
private readonly string _data = ""; | ||
|
||
public Lexer(string data) | ||
{ | ||
_data = data; | ||
} | ||
|
||
public List<Token> ReadAll() | ||
{ | ||
var tokens = new List<Token>(); | ||
var data = _data.Replace("\r\n", "\n").Replace('\r', '\n'); | ||
// 空白、空文字列、コメントだけの行をあらかじめ除外する | ||
var lines = data.Split('\n').ToArray(); | ||
for (var i = 0; i < lines.Length; i++) | ||
{ | ||
var line = lines[i]; | ||
|
||
// 空白またはコメントだけの行はスキップする | ||
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("//")) | ||
{ | ||
continue; | ||
} | ||
|
||
var lineNumber = i + 1; | ||
var chars = line.ToCharArray(); | ||
var otherTypeLiteralBuilder = new StringBuilder(); | ||
var numberLiteralBuilder = new StringBuilder(); | ||
for (var j = 0; j < chars.Length; j++) | ||
{ | ||
char? next = j + 1 < chars.Length ? chars[j + 1] : null; | ||
// numbers | ||
if (char.IsNumber(chars[j])) | ||
{ | ||
_ = numberLiteralBuilder.Append(chars[j]); | ||
if (otherTypeLiteralBuilder.Length != 0) | ||
{ | ||
var literal = otherTypeLiteralBuilder.ToString(); | ||
var type = MatchOtherType(literal); | ||
tokens.Add(new(type, otherTypeLiteralBuilder.ToString(), lineNumber)); | ||
_ = otherTypeLiteralBuilder.Clear(); | ||
} | ||
continue; | ||
} | ||
// others | ||
if (IsOtherChar(chars[j], next)) | ||
{ | ||
_ = otherTypeLiteralBuilder.Append(chars[j]); | ||
if (numberLiteralBuilder.Length != 0) | ||
{ | ||
var literal = numberLiteralBuilder.ToString(); | ||
tokens.Add(new(TokenType.Number, literal, lineNumber)); | ||
_ = numberLiteralBuilder.Clear(); | ||
} | ||
continue; | ||
} | ||
|
||
if (numberLiteralBuilder.Length != 0) | ||
{ | ||
var literal = numberLiteralBuilder.ToString(); | ||
tokens.Add(new(TokenType.Number, literal, lineNumber)); | ||
_ = numberLiteralBuilder.Clear(); | ||
} | ||
if (otherTypeLiteralBuilder.Length != 0) | ||
{ | ||
var literal = otherTypeLiteralBuilder.ToString(); | ||
var type = MatchOtherType(literal); | ||
tokens.Add(new(type, literal, lineNumber)); | ||
_ = otherTypeLiteralBuilder.Clear(); | ||
} | ||
|
||
// comment out | ||
if (j + 1 < chars.Length && IsCommentPrefix(chars[j], next)) | ||
{ | ||
break; | ||
} | ||
|
||
// space | ||
if (char.IsWhiteSpace(chars[j])) | ||
{ | ||
continue; | ||
} | ||
|
||
// symbols | ||
Token token = chars[j] switch | ||
{ | ||
'.' => new(TokenType.Dot, ".", lineNumber), | ||
'#' => new(TokenType.Sharp, "#", lineNumber), | ||
'(' => new(TokenType.LeftParentheses, "(", lineNumber), | ||
')' => new(TokenType.RightParentheses, ")", lineNumber), | ||
',' => new(TokenType.Comma, ",", lineNumber), | ||
';' => new(TokenType.Semicolon, ";", lineNumber), | ||
_ => new(TokenType.Unknown, chars[j].ToString(), lineNumber), | ||
}; | ||
tokens.Add(token); | ||
} | ||
|
||
if (numberLiteralBuilder.Length != 0) | ||
{ | ||
var literal = numberLiteralBuilder.ToString(); | ||
tokens.Add(new(TokenType.Number, literal, lineNumber)); | ||
_ = numberLiteralBuilder.Clear(); | ||
} | ||
|
||
if (otherTypeLiteralBuilder.Length != 0) | ||
{ | ||
var literal = otherTypeLiteralBuilder.ToString(); | ||
var type = MatchOtherType(literal); | ||
tokens.Add(new(type, literal, lineNumber)); | ||
_ = otherTypeLiteralBuilder.Clear(); | ||
} | ||
|
||
tokens.Add(new(TokenType.LineBreak, "\n", lineNumber)); | ||
} | ||
return tokens; | ||
} | ||
|
||
private TokenType MatchOtherType(string other) | ||
{ | ||
if (int.TryParse(other, out _)) | ||
{ | ||
return TokenType.Number; | ||
} | ||
if (_alphaRegex.IsMatch(other)) | ||
{ | ||
return other switch | ||
{ | ||
"tie" => TokenType.Tie, | ||
"tup" => TokenType.Tuplet, | ||
"rest" => TokenType.Rest, | ||
_ => TokenType.Alphabet, | ||
}; | ||
} | ||
return TokenType.Unknown; | ||
} | ||
|
||
private bool IsOtherChar(char character, char? nextCharacter) | ||
{ | ||
var next = nextCharacter ?? 'a'; // 'a' is not comment prefix. | ||
return | ||
!IsSymbol(character) && | ||
!IsCommentPrefix(character, next) && | ||
!char.IsWhiteSpace(character); | ||
} | ||
|
||
private bool IsCommentPrefix(char character, char? nextCharacter) | ||
{ | ||
return character is '/' && nextCharacter is '/'; | ||
} | ||
|
||
private bool IsSymbol(char character) | ||
{ | ||
return character is '.' or '#' or '(' or ')' or ',' or ';'; | ||
} | ||
} |
Oops, something went wrong.