Mercury.Formats library 1.0 The library provides format parsers for the Mercury library components.

- Main Page
- Packages
- Classes
- Files

- File List

All Classes Namespaces Files Functions Properties
GrammarParser.cs
Go to the documentation of this file.
1 using Mercury.Scanning;
2 using Mercury.Syntax;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Linq;
7
8 namespace Mercury.Formats.Basic
9 {
10 //=============================================================================
11 // StreamGrammarParser
12 //=============================================================================
13
59 public class GrammarParser : IDisposable
60 {
61 private static Tokenizer inputTokenizer
62 = new Tokenizer(new[] { '@', '_' }, new[] { "->", "root", "epsilon", "metagrammar" }, TokenizerOptions.CompiledMatch);
63
64 //--[ Private fields ]-----------------------------------------------
65
66 private StreamReader source = null;
67 private string filename = null;
68
69 //--[ Constructors ]-------------------------------------------------
70
79 public GrammarParser(StreamReader reader)
80 {
81 if (reader == null) throw new ArgumentNullException("reader");
82
83 source = reader;
84 }
85
90 public GrammarParser(string filename)
91 : this(new StreamReader(filename))
92 {
93 this.filename = filename;
94 }
95
96 //--[ Methods ]------------------------------------------------------
97
98 private GrammarBuilder GetBuilder(ref int linenum)
99 {
100 linenum = 0;
101 string line = null;
102
103 List<Token> tokens = new List<Token>();
104
105 bool header = true;
106 Symbol root = null;
107 Symbol epsilon = null;
108 while (header && ((line = source.ReadLine()) != null))
109 {
110 ++linenum;
111
112 tokens.Clear();
113 tokens.AddRange(inputTokenizer.Tokenize(line));
114
115 if ((tokens.Count == 0) || (tokens[0].Value == "#"))
116 continue;
117
118 if (tokens[0].Type != TokenType.Keyword)
119 { header = false; break; }
120
121 switch(tokens[0].Value)
122 {
123 case "root":
124 if (root != null) goto alreadyset;
125 if (tokens.Count != 2) goto syntaxerr;
126
127 root = new Symbol(tokens[1].Value, SymbolType.Nonterminal);
128 break;
129
130 case "epsilon":
131 if (epsilon != null) goto alreadyset;
132 if (tokens.Count != 2) goto syntaxerr;
133
134 epsilon = new Symbol(tokens[1].Value, SymbolType.Epsilon);
135 break;
136
137 alreadyset: throw new FormatException(string.Format("'{0}' option is already set", tokens[0].Value));
138 syntaxerr: throw new FormatException(string.Format("Invalid syntax of '{0}'", tokens[0].Value));
139
140 default:
141 header = false;
142 break;
143 }
144 }
145
146 GrammarBuilder builder= new GrammarBuilder(
147 root ?? new Symbol(Defaults.Root),
148 epsilon ?? new Symbol(Defaults.Epsilon, SymbolType.Epsilon));
149
150 List<Token> ruletok = new List<Token>();
151 GrammarEntityParser gep = new GrammarEntityParser(builder.Epsilon);
152
153 Action parse = delegate()
154 {
155 if (ruletok.Count != 0)
156 foreach (var rule in gep.ParseMultiRule(ruletok)) builder.AddRule(rule);
157 ruletok.Clear();
158 };
159
160 while(line != null)
161 {
162 if ((tokens.Count != 0) && (tokens[0].Value != "#"))
163 {
164 if (tokens[0].Value != "|")
165 parse.Invoke();
166
167 ruletok.AddRange(tokens);
168 }
169
170 ++linenum;
171 tokens.Clear();
172 line = source.ReadLine();
173
174 if (line == null)
175 parse.Invoke();
176 else
177 tokens.AddRange(inputTokenizer.Tokenize(line));
178 }
179
180 return builder;
181 }
182
188 public GrammarBuilder GetBuilder()
189 {
190 int linenum = 0;
191
192 try
193 {
194 return GetBuilder(ref linenum);
195 }
196 catch (Exception ex)
197 {
198 string msg = filename == null
199 ? string.Format("In line {0}: {1}", linenum, ex.Message)
200 : string.Format("In '{0}' line {1}: {2}", filename, linenum, ex.Message);
201
202 throw new FormatException(msg, ex);
203 }
204 }
205
206 //--[ Interface implementation ]-------------------------------------
207
208 #region [ IDisposable ]
209
210 public void Dispose()
211 { if (filename != null) source.Close(); }
212
213 #endregion
214
215 }
216 }
Mercury.Formats.Basic.GrammarParser
Parses a grammar from a StreamReader. Grammar is expected in the format
Definition: GrammarParser.cs:59
Mercury.Formats.Basic.GrammarParser.GetBuilder
GrammarBuilder GetBuilder()
Parses the file provided by the constructor's argument and returns the builder.
Definition: GrammarParser.cs:188
Mercury.Formats.Basic.GrammarParser.GrammarParser
GrammarParser(StreamReader reader)
Creates a parser that will parse grammar from provided StreamReader instance.
Definition: GrammarParser.cs:79
Mercury.Formats.Basic.GrammarParser.Dispose
void Dispose()
Definition: GrammarParser.cs:210
Mercury.Formats.Basic.GrammarParser.GrammarParser
GrammarParser(string filename)
Initializes a new instance of the GrammarParser class.
Definition: GrammarParser.cs:90