-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParser.cs
203 lines (157 loc) · 5.43 KB
/
Parser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace Bakera.RedFace{
public class RedFaceParser : ParserEventSender{
private List<ParserLog> myLogs = new List<ParserLog>();
private bool myStopFlag = false;
private bool myEncodingChangingFlag = false;
private Tokenizer myTokenizer = null;
private TreeConstruction myTreeConstruction = null;
private Stream myStream = null;
private InputStream myInputStream = null;
private bool myFramesetOK = true;
private Encoding myDefaultEncoding = Encoding.UTF8;
private Encoding myForceEncoding = null;
// プロパティ
public DateTime StartTime {get; private set;}
public DateTime EndTime {get; private set;}
public string CurrentTokenState{
get{
return myTokenizer.CurrentTokenState.Name;
}
}
public string CurrentInsertionMode{
get{
return myTreeConstruction.CurrentInsertionMode.Name;
}
}
public bool IsStopped{
get{
return myStopFlag;
}
}
public Document Document{
get{
return myTreeConstruction.Document;
}
}
public bool FramesetOK{
get{return myFramesetOK;}
set{myFramesetOK = value;}
}
public bool Scripting{
get{return false;}
}
public StackOfElements StackOfOpenElements{
get{
return myTreeConstruction.StackOfOpenElements;
}
}
public EncodingConfidence EncodingConfidence{
get{return myTokenizer.InputStream.EncodingConfidence;}
}
public InputStream InputStream{
get{return myInputStream;}
}
// コンストラクタ
// メソッド
public ParserLog[] GetLogs(){
return myLogs.ToArray();
}
// パース系
public void Parse(Stream s){
if(s.CanSeek){
myStream = s;
} else {
myStream = new MemoryStream();
s.CopyTo(myStream);
}
Initialize();
StartTime = DateTime.Now;
if(myForceEncoding != null){
OnMessageRaised(new GenericVerbose(string.Format("文字符号化方式 {0} が指定されています。", myForceEncoding.EncodingName)));
myInputStream.SetEncoding(myForceEncoding, EncodingConfidence.Certain);
} else {
OnMessageRaised(new GenericVerbose("文字符号化方式が指定されていないため、Sniffingを行います。"));
Encoding enc = myInputStream.SniffEncoding();
if(enc == null){
OnMessageRaised(new SniffingFailureWarning(myDefaultEncoding.EncodingName));
myInputStream.SetEncoding(myDefaultEncoding, EncodingConfidence.Tentative);
}
}
// パースする
OnMessageRaised(new GenericVerbose("構文解析を開始します。"));
TreeConstruct();
// EncodingChangedイベントで停止した場合、一度だけ再実行
if(myEncodingChangingFlag){
OnMessageRaised(new DifferentCharsetWarning(myInputStream.Encoding, myForceEncoding.EncodingName));
myStopFlag = false;
myEncodingChangingFlag = false;
Initialize();
myInputStream.SetEncoding(myForceEncoding, EncodingConfidence.Certain);
TreeConstruct();
} else {
OnMessageRaised(new GenericVerbose("Tree Constructが終了しました。"));
}
OnMessageRaised(new GenericVerbose("パース終了しました。"));
EndTime = DateTime.Now;
}
// パース停止フラグをONにします。
// 次のトークンの読み取りを止めて停止します。
public void Stop(){
// ToDo: Stop処理実装
myStopFlag = true;
}
public void ChangeTokenState<T>() where T : TokenizationState, new(){
myTokenizer.ChangeTokenState<T>();
}
private void TreeConstruct(){
while(!myStopFlag){
Token t = myTokenizer.GetToken();
if(t == null) continue;
OnMessageRaised(new GenericVerbose(string.Format("Tokenを作成しました。: {0}", t)));
// AppendTokenを実行。
// 実行後にReprocessフラグが立てられている場合は同じトークンを再処理する
do{
myTreeConstruction.ReprocessFlag = false;
myTreeConstruction.AppendToken(t);
} while(myTreeConstruction.ReprocessFlag);
if(t is EndOfFileToken){
OnMessageRaised(new GenericVerbose("ファイルの終端に達したため、終了します。"));
break;
}
}
}
private void EncodeChanged(Object sender, EncodingChangedEventArgs e){
myStopFlag = true;
myEncodingChangingFlag = true;
myForceEncoding = e.Encoding;
}
private void Initialize(){
myStream.Position = 0;
myInputStream = new InputStream(myStream);
myInputStream.ParserEventRaised += OnParserEventRaised;
myInputStream.EncodingChanged += EncodeChanged;
myTokenizer = new Tokenizer(this);
myTokenizer.ParserEventRaised += OnParserEventRaised;
myTreeConstruction = new TreeConstruction(this);
myTreeConstruction.ParserEventRaised += OnParserEventRaised;
}
// エンコード
// charsetを明示的に指定します。
// encoding判定は行われず、ここで指定したEncodingが強制的に使用されるようになります。
public void SetForceEncoding(string s){
OnMessageRaised(new GenericVerbose(string.Format("文字符号化方式 {0} をセットします。", s)));
myForceEncoding = EncodingSniffer.GetEncodingByName(s);
}
// デフォルトのcharsetを指定します。
// encoding判定に失敗した際に、ここで指定したEncodingが使用されるようになります。
// このメソッドを呼ばない場合のデフォルトは UTF-8 です。
public void SetDefaultEncoding(string s){
myDefaultEncoding = EncodingSniffer.GetEncodingByName(s);
}
}
}