Skip to content

Commit ce58629

Browse files
committed
SIFOSC 機能の一部を実装。
1 parent a1997a6 commit ce58629

7 files changed

Lines changed: 374 additions & 7 deletions

File tree

FastChatProtocolInterface/CommandLineArguments.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,20 @@ private static void PrintHelp()
164164
Console.WriteLine("/ExecutionMode -m 実行モードを指定する。");
165165
Console.WriteLine(" サーバーの場合は、server を指定する。");
166166
Console.WriteLine(" クライアントの場合は、client を指定する。");
167+
Console.WriteLine(" 下記に完全な実行モードの一覧を示す。");
167168
Console.WriteLine("/HostName -n ホスト名を指定する。");
168169
Console.WriteLine(" この値はクライアントの場合のみ使用される。");
169170
Console.WriteLine("/Port -p ポート番号を指定する。");
170171
Console.WriteLine(" クライアントの場合は必ず指定しなければならない。");
171172
Console.WriteLine("/UserName -u 利用者の表示名を指定する。");
172173
Console.WriteLine();
174+
Console.WriteLine("実行モード一覧");
175+
Console.WriteLine("モード名 説明");
176+
Console.WriteLine("server 最適なサーバーを起動する。");
177+
Console.WriteLine("fachpi 通常のサーバーを起動する。如何なる拡張機能も使用しない事を強制する。");
178+
Console.WriteLine("sifosc SIFOSC 機能を有効にしてサーバーを起動する。");
179+
Console.WriteLine("client クライアントを起動する。");
180+
Console.WriteLine();
173181
Console.WriteLine("注意:幾つかのオプションにはこの説明書に記載されていない別表記があります。");
174182
Console.WriteLine();
175183
}

FastChatProtocolInterface/ExecutionMode.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@
88
using System.Collections.Concurrent;
99
using System.Net;
1010
using System.Threading;
11+
using FastChatProtocolInterface.SimpleFormulaScript;
1112

1213
namespace FastChatProtocolInterface
1314
{
1415
public abstract class ExecutionMode
1516
{
1617
private static readonly ConcurrentDictionary<string, ExecutionMode?> _modes;
1718

18-
public static ExecutionMode Server => ServerImpl._inst;
19+
public static ExecutionMode Server => ServerImpl._inst_fachpi;
1920
public static ExecutionMode Client => ClientImpl._inst;
2021

2122
static ExecutionMode()
2223
{
2324
_modes = new();
24-
_modes.TryAdd("server", ServerImpl._inst);
25+
_modes.TryAdd("server", ServerImpl._inst_fachpi);
26+
_modes.TryAdd("fachpi", ServerImpl._inst_fachpi);
27+
_modes.TryAdd("sifosc", ServerImpl._inst_sifosc);
2528
_modes.TryAdd("client", ClientImpl._inst);
2629
}
2730

@@ -38,21 +41,27 @@ static ExecutionMode()
3841

3942
private sealed class ServerImpl : ExecutionMode
4043
{
41-
internal static readonly ServerImpl _inst = new();
44+
internal static readonly ServerImpl _inst_fachpi = new((ip, port, name) => new FachpiServer(ip, port) { Name = name });
45+
internal static readonly ServerImpl _inst_sifosc = new((ip, port, name) => new SifoscServer(ip, port) { Name = name });
4246

43-
private ServerImpl() { }
47+
private readonly Factory _factory;
48+
49+
private ServerImpl(Factory factory)
50+
{
51+
_factory = factory;
52+
}
4453

4554
public override void Run(in CommandLineArguments args)
4655
{
47-
using var server = new FachpiServer(IPAddress.Any, args.Port) {
48-
Name = args.UserName
49-
};
56+
using var server = _factory(IPAddress.Any, args.Port, args.UserName);
5057

5158
server.Start();
5259
while (true) {
5360
Thread.Yield();
5461
}
5562
}
63+
64+
private delegate FachpiServer Factory(IPAddress ip, int port, string name);
5665
}
5766

5867
private sealed class ClientImpl : ExecutionMode
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/****
2+
* FACHPI: Fast Chat Protocol/Interface
3+
* Copyright (C) 2023 Takym.
4+
*
5+
* distributed under the MIT License.
6+
****/
7+
8+
namespace FastChatProtocolInterface.SimpleFormulaScript
9+
{
10+
public static class SifoscLexer
11+
{
12+
public static bool TryScanKeyword(this SourceCode sc, string keyword)
13+
=> sc.AdvanceIf(keyword) && !(sc.TryPeekChar(out char ch) && IsAlphanum(ch));
14+
15+
public static bool TryScanSignedInteger(this SourceCode sc, out int result)
16+
{
17+
bool shouldRetreat = sc.TryScanSign(out bool isMinus);
18+
19+
if (sc.TryScanUnsignedInteger(out result)) {
20+
if (isMinus) {
21+
result = -result;
22+
}
23+
return true;
24+
}
25+
26+
if (shouldRetreat) {
27+
sc.Retreat();
28+
}
29+
return false;
30+
}
31+
32+
public static bool TryScanSign(this SourceCode sc, out bool isMinus)
33+
{
34+
isMinus = false;
35+
36+
if (sc.TryPeekChar(out char ch)) {
37+
switch (ch) {
38+
case '+':
39+
sc.Advance();
40+
return true;
41+
case '-':
42+
isMinus = true;
43+
goto case '+';
44+
}
45+
}
46+
47+
return false;
48+
}
49+
50+
public static bool TryScanUnsignedInteger(this SourceCode sc, out int result)
51+
{
52+
result = 0;
53+
54+
if (sc.TryPeekChar(out char ch) && IsDigit(ch)) {
55+
do {
56+
result *= 10;
57+
result += ch - '0';
58+
sc.Advance();
59+
} while (sc.TryPeekChar(out ch) && IsDigit(ch));
60+
61+
return true;
62+
}
63+
64+
return false;
65+
}
66+
67+
private static bool IsAlphanum(char ch) => IsAlphabet(ch) || IsDigit(ch) || ch == '_';
68+
private static bool IsAlphabet(char ch) => ch is (>= 'A' and <= 'Z') or (>= 'a' and <= 'z');
69+
private static bool IsDigit (char ch) => ch is >= '0' and <= '9';
70+
}
71+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/****
2+
* FACHPI: Fast Chat Protocol/Interface
3+
* Copyright (C) 2023 Takym.
4+
*
5+
* distributed under the MIT License.
6+
****/
7+
8+
namespace FastChatProtocolInterface.SimpleFormulaScript
9+
{
10+
public record SifoscObject { }
11+
12+
public sealed record SifoscArray : SifoscObject
13+
{
14+
public SifoscObject?[]? Values { get; set; }
15+
}
16+
17+
public sealed record SifoscNull : SifoscObject
18+
{
19+
private static readonly SifoscNull _inst = new();
20+
21+
public static SifoscNull Instance => _inst;
22+
23+
private SifoscNull() { }
24+
}
25+
26+
public sealed record SifoscInteger : SifoscObject
27+
{
28+
public int Value { get; set; }
29+
}
30+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/****
2+
* FACHPI: Fast Chat Protocol/Interface
3+
* Copyright (C) 2023 Takym.
4+
*
5+
* distributed under the MIT License.
6+
****/
7+
8+
using System.Collections.Generic;
9+
using System.Diagnostics.CodeAnalysis;
10+
11+
namespace FastChatProtocolInterface.SimpleFormulaScript
12+
{
13+
public static class SifoscParser
14+
{
15+
public static bool TryParseValue(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscObject? result)
16+
{
17+
sc.SkipSpaces();
18+
19+
if (TryParseArray(sc, out var aryVal)) {
20+
result = aryVal;
21+
return true;
22+
} else if (TryParseNull(sc, out var nulVal)) {
23+
result = nulVal;
24+
return true;
25+
} else if (TryParseNewObject(sc, out var objVal)) {
26+
result = objVal;
27+
return true;
28+
} else if (TryParseInteger(sc, out var intVal)) {
29+
result = intVal;
30+
return true;
31+
} else {
32+
result = null;
33+
return false;
34+
}
35+
}
36+
37+
public static bool TryParseArray(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscArray? result)
38+
{
39+
sc.BeginScope();
40+
41+
if (sc.AdvanceIf('[')) {
42+
var list = new List<SifoscObject>();
43+
44+
while (sc.TryParseValue(out var item)) {
45+
list.Add(item);
46+
47+
sc.SkipSpaces();
48+
if (!sc.AdvanceIf(',')) {
49+
break;
50+
}
51+
}
52+
53+
sc.SkipSpaces();
54+
if (sc.AdvanceIf(']')) {
55+
result = new() { Values = [ ..list ] };
56+
return true;
57+
}
58+
}
59+
60+
result = null;
61+
sc.EndScope(true);
62+
return false;
63+
}
64+
65+
public static bool TryParseNull(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscNull? result)
66+
{
67+
if (sc.TryScanKeyword("null")) {
68+
result = SifoscNull.Instance;
69+
return true;
70+
} else {
71+
result = null;
72+
return false;
73+
}
74+
}
75+
76+
public static bool TryParseNewObject(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscObject? result)
77+
{
78+
if (sc.TryScanKeyword("newobj")) {
79+
result = new();
80+
return true;
81+
} else {
82+
result = null;
83+
return false;
84+
}
85+
}
86+
87+
public static bool TryParseInteger(this SourceCode sc, [NotNullWhen(true)][MaybeNullWhen(false)] out SifoscInteger? result)
88+
{
89+
if (sc.TryScanSignedInteger(out int value)) {
90+
result = new() { Value = value };
91+
return true;
92+
} else {
93+
result = null;
94+
return false;
95+
}
96+
}
97+
}
98+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/****
2+
* FACHPI: Fast Chat Protocol/Interface
3+
* Copyright (C) 2023 Takym.
4+
*
5+
* distributed under the MIT License.
6+
****/
7+
8+
using System;
9+
using System.Net;
10+
11+
namespace FastChatProtocolInterface.SimpleFormulaScript
12+
{
13+
public class SifoscServer(IPAddress ipAddr, int port) : FachpiServer(ipAddr, port)
14+
{
15+
public override void OnConnected()
16+
{
17+
base.OnConnected();
18+
19+
Console.WriteLine("受信した文字列を SIFOSC として解析します。");
20+
Console.WriteLine("この機能には未実装の部分が含まれています。");
21+
}
22+
23+
protected override string ReceiveMessageCore(FachpiCommunicationFlow flow)
24+
{
25+
var sc = new SourceCode(flow.Reader.ReadString());
26+
if (sc.TryParseValue(out var result)) {
27+
return result.ToString();
28+
} else {
29+
return "(有効な SIFOSC ではありませんでした。)" + sc.Text;
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)