@@ -106,6 +106,7 @@ public override string ToString()
106106 sb . AppendLine ( Productions [ i ] . ToString ( ) ) ;
107107 return sb . ToString ( ) ;
108108 }
109+ /*
109110 internal static XbnfDocument Parse(ParseContext pc)
110111 {
111112 var result = new XbnfDocument();
@@ -122,15 +123,158 @@ public static XbnfDocument Parse(IEnumerable<char> @string)
122123 => Parse(ParseContext.Create(@string));
123124 public static XbnfDocument ReadFrom(TextReader reader)
124125 => Parse(ParseContext.CreateFrom(reader));
126+ */
127+ public static XbnfDocument Parse ( IEnumerable < char > input )
128+ {
129+ XbnfDocument result ;
130+ XbnfException . ThrowIfErrors ( _TryParse ( input , null , out result ) ) ;
131+ return result ;
132+ }
133+ public static XbnfDocument ReadFrom ( TextReader input )
134+ {
135+ XbnfDocument result ;
136+ XbnfException . ThrowIfErrors ( TryReadFrom ( input , out result ) ) ;
137+ return result ;
138+ }
125139 public static XbnfDocument ReadFrom ( string filename )
126140 {
127- using ( var sr = File . OpenText ( filename ) )
141+ XbnfDocument result ;
142+ XbnfException . ThrowIfErrors ( TryReadFrom ( filename , out result ) ) ;
143+ return result ;
144+ }
145+ public static XbnfDocument ReadFromUrl ( string url )
146+ {
147+ XbnfDocument result ;
148+ XbnfException . ThrowIfErrors ( TryReadFrom ( url , out result ) ) ;
149+ return result ;
150+ }
151+ static XbnfAttribute _ParseAttribute ( ParseNode p )
152+ {
153+ var name = p . Children [ 0 ] . Value ;
154+ var v = ParseNode . SelectFirst ( p . Children , XbnfParser . attrvalue ) ;
155+ var val = ( object ) true ;
156+ if ( null != v )
157+ {
158+ string s = v . Children [ 0 ] . Value ;
159+ val = ParseContext . Create ( s ) . ParseJsonValue ( ) ;
160+ }
161+ var result = new XbnfAttribute ( name , val ) ;
162+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
163+ return result ;
164+ }
165+ static XbnfExpression _ParseExpression ( ParseNode p )
166+ {
167+ XbnfExpression result = null ;
168+ switch ( p . SymbolId )
128169 {
129- var result = ReadFrom ( sr ) ;
130- result . SetFilename ( filename ) ;
131- return result ;
170+ case XbnfParser . orExpression :
171+ if ( 1 == p . Children . Count )
172+ return _ParseExpression ( p . Children [ 0 ] ) ;
173+ result = new XbnfOrExpression ( _ParseExpression ( p . Children [ 0 ] ) , _ParseExpression ( p . Children [ 2 ] ) ) ;
174+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
175+ return result ;
176+ case XbnfParser . concatExpression :
177+ if ( 1 == p . Children . Count )
178+ return _ParseExpression ( p . Children [ 0 ] ) ;
179+ var right = new List < XbnfExpression > ( p . Children . Count - 1 ) ;
180+ XbnfExpression left = null ;
181+ foreach ( var pch in p . Children )
182+ {
183+ if ( XbnfParser . lparen == pch . SymbolId || XbnfParser . rparen == pch . SymbolId )
184+ continue ;
185+ if ( null == left )
186+ left = _ParseExpression ( pch ) ;
187+ else
188+ right . Add ( _ParseExpression ( pch ) ) ;
189+ }
190+ result = new XbnfConcatExpression ( left , right . ToArray ( ) ) ;
191+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
192+ return result ;
193+ case XbnfParser . optionalExpression :
194+ result = new XbnfOptionalExpression ( _ParseExpression ( p . Children [ 1 ] ) ) ;
195+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
196+ return result ;
197+ case XbnfParser . repeatExpression :
198+ result = new XbnfRepeatExpression ( _ParseExpression ( p . Children [ 1 ] ) , XbnfParser . repeatZero == p . Children [ 2 ] . SymbolId ) ;
199+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
200+ return result ;
201+ case XbnfParser . subexpression :
202+ result = _ParseExpression ( p . Children [ 1 ] ) ;
203+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
204+ return result ;
205+ case XbnfParser . literal :
206+ var pc = ParseContext . Create ( p . Value ) ;
207+ result = new XbnfLiteralExpression ( pc . ParseJsonString ( ) ) ;
208+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
209+ return result ;
210+ case XbnfParser . regex :
211+ pc = ParseContext . Create ( p . Value ) ;
212+ pc . EnsureStarted ( ) ;
213+ pc . Advance ( ) ;
214+ pc . TryReadUntil ( '\' ' , '\\ ' , false ) ;
215+ result = new XbnfRegexExpression ( pc . GetCapture ( ) ) ;
216+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
217+ return result ;
218+ case XbnfParser . identifier :
219+ result = new XbnfRefExpression ( p . Value ) ;
220+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
221+ return result ;
222+ default :
223+ throw new Exception ( "Error in parser implementation" ) ;
224+ }
225+ }
226+ static XbnfProduction _ParseProduction ( ParseNode p )
227+ {
228+ var result = new XbnfProduction ( ) ;
229+ result . SetLocation ( p . Line , p . Column , p . Position ) ;
230+ result . Name = p . Children [ 0 ] . Value ;
231+ var apn = ParseNode . SelectFirst ( p . Children , XbnfParser . attributes ) ;
232+ if ( null != apn )
233+ {
234+ foreach ( var ap in ParseNode . Select ( apn . Children , XbnfParser . attribute ) )
235+ result . Attributes . Add ( _ParseAttribute ( ap ) ) ;
236+ }
237+ var pexp = ParseNode . SelectFirst ( p . Children , XbnfParser . orExpression ) ;
238+ if ( null != pexp )
239+ {
240+ result . Expression = _ParseExpression ( pexp ) ;
241+ }
242+ return result ;
243+ }
244+ public static IList < XbnfMessage > TryReadFrom ( string filename , out XbnfDocument result )
245+ => _TryParse ( new FileReaderEnumerable ( filename ) , filename , out result ) ;
246+ public static IList < XbnfMessage > TryReadFromUrl ( string url , out XbnfDocument result )
247+ => _TryParse ( new UrlReaderEnumerable ( url ) , url , out result ) ;
248+ public static IList < XbnfMessage > TryReadFrom ( TextReader reader , out XbnfDocument result )
249+ => _TryParse ( TextReaderEnumerable . FromReader ( reader ) , null , out result ) ;
250+ public static IList < XbnfMessage > TryParse ( IEnumerable < char > input , out XbnfDocument result )
251+ => _TryParse ( input , null , out result ) ;
252+ static IList < XbnfMessage > _TryParse ( IEnumerable < char > input , string filename , out XbnfDocument result )
253+ {
254+ var msgs = new List < XbnfMessage > ( ) ;
255+ var parser = new XbnfParser ( new XbnfTokenizer ( input ) ) ;
256+ var pt = parser . ParseSubtree ( ) ;
257+ var hasErrors = false ;
258+ foreach ( var pn in ParseNode . Select ( pt . FillDescendantsAndSelf ( ) , "#ERROR" ) )
259+ {
260+ hasErrors = true ;
261+ msgs . Add ( new XbnfMessage ( ErrorLevel . Error , - 1 , "Syntax error: " + pn . Value , pn . Line , pn . Column , pn . Position , filename ) ) ;
262+ }
263+ result = null ;
264+ if ( ! hasErrors )
265+ {
266+ var doc = new XbnfDocument ( ) ;
267+ if ( ! string . IsNullOrEmpty ( filename ) )
268+ doc . SetFilename ( filename ) ;
269+ foreach ( var pc in pt . Children )
270+ {
271+ doc . Productions . Add ( _ParseProduction ( pc ) ) ;
272+ }
273+ result = doc ;
132274 }
275+ return msgs ;
133276 }
277+
134278 #region Value semantics
135279 public bool Equals ( XbnfDocument rhs )
136280 {
0 commit comments