14 using System.Collections.Generic;
15 using System.Globalization;
27 public readonly
bool CaseSensitive =
true;
32 public string Delimiters = null;
34 public string WhitespaceChars =
" \t\r\n\v";
37 public string LineTerminators =
"\n\r\v";
39 #region Language Flags
79 public CultureInfo DefaultCulture = CultureInfo.InvariantCulture;
99 _currentGrammar =
this;
100 this.CaseSensitive = caseSensitive;
101 bool ignoreCase = !this.CaseSensitive;
102 LanguageStringComparer = StringComparer.Create(System.Globalization.CultureInfo.InvariantCulture, ignoreCase);
108 ConsolePromptMoreInput =
".";
112 #region Reserved words handling
115 foreach (var word
in reservedWords) {
116 var wdTerm = ToTerm(word);
117 wdTerm.SetFlag(TermFlags.IsReservedWord);
122 #region Register/Mark methods
124 RegisterOperators(precedence,
Associativity.Left, opSymbols);
128 foreach (
string op
in opSymbols) {
130 opSymbol.SetFlag(TermFlags.IsOperator);
131 opSymbol.Precedence = precedence;
132 opSymbol.Associativity = associativity;
140 foreach (var term
in opTerms) {
141 term.SetFlag(TermFlags.IsOperator);
142 term.Precedence = precedence;
143 term.Associativity = associativity;
148 KeyTerm openS = ToTerm(openBrace);
149 KeyTerm closeS = ToTerm(closeBrace);
150 openS.SetFlag(TermFlags.IsOpenBrace);
151 openS.IsPairFor = closeS;
152 closeS.SetFlag(TermFlags.IsCloseBrace);
153 closeS.IsPairFor = openS;
157 foreach (
string symbol
in symbols) {
159 term.SetFlag(TermFlags.IsPunctuation|TermFlags.NoAstNode);
164 foreach (
BnfTerm term
in terms)
165 term.SetFlag(TermFlags.IsPunctuation|TermFlags.NoAstNode);
171 nt.Flags |= TermFlags.IsTransient | TermFlags.NoAstNode;
175 foreach (var symbol
in symbols)
176 ToTerm(symbol).SetFlag(TermFlags.IsMemberSelect);
181 foreach (var term
in terms)
182 term.SetFlag(TermFlags.IsNotReported);
185 foreach (var symbol
in symbols)
186 ToTerm(symbol).SetFlag(TermFlags.IsNotReported);
191 #region virtual methods: TryMatch, CreateNode, CreateRuntime, RunSample
203 return node.Term.Name +
" (Syntax error)";
204 if (node.
Token != null)
205 return node.Token.ToString();
206 if(node.
Term == null)
207 return (node.State != null ?
string.Empty :
"(State " + node.State.
Name +
")");
209 if(ntTerm != null && !
string.IsNullOrEmpty(ntTerm.NodeCaptionTemplate))
211 return node.Term.Name;
217 nodeInfo.Term.CreateAstNode(context, nodeInfo);
253 error = context.CurrentParserInput.Token.Value as string;
258 var openBrace = context.OpenBraces.Peek();
261 var expectedTerms = context.GetExpectedTermSet();
262 if (expectedTerms.Count > 0)
263 error = ConstructParserErrorMessage(context, expectedTerms);
268 context.AddParserError(error);
273 #region MakePlusRule, MakeStarRule methods
275 return MakePlusRule(listNonTerminal, null, listMember);
279 bool allowTrailingDelimiter = (options & TermListOptions.AllowTrailingDelimiter) != 0;
280 if (delimiter == null || !allowTrailingDelimiter)
281 return MakePlusRule(listNonTerminal, delimiter, listMember);
284 plusList.Rule = MakePlusRule(listNonTerminal, delimiter, listMember);
285 listNonTerminal.Rule = plusList | plusList + delimiter;
286 listNonTerminal.SetFlag(TermFlags.IsListContainer);
287 return listNonTerminal.Rule;
291 if (delimiter == null)
292 listNonTerminal.Rule = listMember | listNonTerminal + listMember;
294 listNonTerminal.Rule = listMember | listNonTerminal + delimiter + listMember;
295 listNonTerminal.SetFlag(TermFlags.IsList);
296 return listNonTerminal.Rule;
300 return MakeStarRule(listNonTerminal, null, listMember,
TermListOptions.None);
304 return MakeStarRule(listNonTerminal, delimiter, listMember,
TermListOptions.None);
308 bool allowTrailingDelimiter = (options & TermListOptions.AllowTrailingDelimiter) != 0;
309 if (delimiter == null) {
311 listNonTerminal.SetFlag(TermFlags.IsList);
312 listNonTerminal.Rule = _currentGrammar.Empty | listNonTerminal + listMember;
313 return listNonTerminal.Rule;
321 plusList.Rule = MakePlusRule(plusList, delimiter, listMember);
322 plusList.SetFlag(TermFlags.NoAstNode);
323 if (allowTrailingDelimiter)
324 listNonTerminal.Rule = _currentGrammar.Empty | plusList | plusList + delimiter;
326 listNonTerminal.Rule = _currentGrammar.Empty | plusList;
327 listNonTerminal.SetFlag(TermFlags.IsListContainer);
328 return listNonTerminal.Rule;
332 #region Hint utilities
353 hint.Precedence = precedence;
354 hint.Associativity = associativity;
360 #region Term report group methods
403 foreach(var symbol
in symbols)
404 termList.Add(ToTerm(symbol));
409 #region Standard terminals: EOF, Empty, NewLine, Indent, Dedent
435 if(_newLinePlus == null) {
437 MarkPunctuation(_newLinePlus);
438 _newLinePlus.Rule = MakePlusRule(_newLinePlus, NewLine);
446 if(_newLineStar == null) {
448 MarkPunctuation(_newLineStar);
449 _newLineStar.Rule = MakeStarRule(_newLineStar, NewLine);
457 #region KeyTerms (keywords + special symbols)
461 return ToTerm(text, text);
465 if (KeyTerms.TryGetValue(text, out term)) {
467 if (
string.IsNullOrEmpty(term.Name) && !string.IsNullOrEmpty(name))
473 text = text.ToLower();
475 term =
new KeyTerm(text, name);
476 KeyTerms[text] = term;
482 #region CurrentGrammar static field
487 private static Grammar _currentGrammar;
489 get {
return _currentGrammar; }
491 internal static void ClearCurrentGrammar() {
492 _currentGrammar = null;
TokenCategory
Token category.
virtual void CreateTokenFilters(LanguageData language, TokenFilterList filters)
string ConsolePromptMoreInput
void AddTermsReportGroup(string alias, params string[] symbols)
Creates a terminal reporting group, so all terminals in the group will be reported as a single "alias...
virtual LanguageData CreateLanguageData()
void MarkPunctuation(params string[] symbols)
static BnfExpression MakeStarRule(NonTerminal listNonTerminal, BnfTerm listMember)
virtual Token TryMatch(ParsingContext context, ISourceStream source)
bool FlagIsSet(LanguageFlags flag)
KeyTerm ToTerm(string text)
virtual void OnLanguageDataConstructed(LanguageData language)
virtual void OnGrammarDataConstructed(LanguageData language)
A strongly-typed resource class, for looking up localized strings, etc.
void MarkNotReported(params BnfTerm[] terms)
void AddOperatorReportGroup(string alias)
Adds a group and an alias for all operator symbols used in the grammar.
virtual void ReportParseError(ParsingContext context)
static string ErrUnexpEof
Looks up a localized string similar to Unexpected end of file..
virtual void OnScannerSelectTerminal(ParsingContext context)
Override this method to help scanner select a terminal to create token when there are more than one c...
GrammarHint PreferShiftHere()
void MarkTransient(params NonTerminal[] nonTerminals)
static BnfExpression MakeStarRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember, TermListOptions options)
TokenPreviewHint ReduceIf(string symbol)
static string ErrUnexpIndent
Looks up a localized string similar to Unexpected indentation..
void RegisterOperators(int precedence, Associativity associativity, params string[] opSymbols)
Interface for Terminals to access the source stream and produce tokens.
KeyTerm ToTerm(string text, string name)
static string LabelEosLabel
Looks up a localized string similar to [end-of-statement].
static BnfExpression MakePlusRule(NonTerminal listNonTerminal, BnfTerm listMember)
The class provides arguments for custom conflict resolution grammar method.
static string MsgDefaultConsoleGreeting
Looks up a localized string similar to {0} Console. Ctrl-C to exit the program. . ...
void MarkMemberSelect(params string[] symbols)
void AddToNoReportGroup(params string[] symbols)
Adds symbols to a group with no-report type, so symbols will not be shown in expected lists in syntax...
virtual void CreateAstNode(ParsingContext context, ParseTreeNode nodeInfo)
void RegisterOperators(int precedence, params string[] opSymbols)
readonly StringComparer LanguageStringComparer
TokenPreviewHint ShiftIf(string symbol)
GrammarHint ResolveInCode()
static BnfExpression MakePlusRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember)
void MarkNotReported(params string[] symbols)
Func< Scanner > ScannerBuilder
void AddToNoReportGroup(params Terminal[] terminals)
Adds symbols to a group with no-report type, so symbols will not be shown in expected lists in syntax...
virtual string ConstructParserErrorMessage(ParsingContext context, StringSet expectedTerms)
static string MsgDefaultConsoleTitle
Looks up a localized string similar to Console.
readonly TokenStack OpenBraces
string GetNodeCaption(ParseTreeNode node)
void MarkReservedWords(params string[] reservedWords)
void RegisterOperators(int precedence, Associativity associativity, params BnfTerm[] opTerms)
NonTerminal Root
The main root entry for the grammar.
static BnfExpression MakeStarRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember)
static string ErrParserUnexpInput
Looks up a localized string similar to Syntax error, expected: {0}.
virtual void OnResolvingConflict(ConflictResolutionArgs args)
Override this method to provide custom conflict resolution; for example, custom code may decide prope...
void MarkPunctuation(params BnfTerm[] terms)
Tokens are produced by scanner and fed to parser, optionally passing through Token filters in between...
virtual string GetParseNodeCaption(ParseTreeNode node)
static string ErrNoClosingBrace
Looks up a localized string similar to No closing pair for opening symbol {0}.
GrammarHint ImplyPrecedenceHere(int precedence)
void RegisterOperators(int precedence, params BnfTerm[] opTerms)
void RegisterBracePair(string openBrace, string closeBrace)
ParseTreeNode CurrentParserInput
GrammarHint ImplyPrecedenceHere(int precedence, Associativity associativity)
Grammar(bool caseSensitive)
static BnfExpression MakePlusRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember, TermListOptions options)
void AddTermsReportGroup(string alias, params Terminal[] terminals)
Creates a terminal reporting group, so all terminals in the group will be reported as a single "alias...