1
ļ»æ// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
5
using System.Collections.Generic;
6
using System.Diagnostics;
10
using ICSharpCode.NRefactory.VB.Ast;
11
using ICSharpCode.NRefactory.VB.Visitors;
13
namespace ICSharpCode.NRefactory.VB.Parser
15
internal partial class VBParser : IDisposable
19
CompilationUnit compilationUnit;
20
int errDist = MinErrDist;
22
const int MinErrDist = 2;
23
const string ErrMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
25
public VBParser(VBLexer lexer)
27
this.errors = lexer.Errors;
28
errors.SynErr = new ErrorCodeProc(SynErr);
29
this.lexer = (VBLexer)lexer;
30
this.stack = new Stack<AstNode>();
33
#region Infrastructure
34
void NodeStart(AstNode node)
39
void NodeEnd(AstNode currentNode, Role role)
41
AstNode node = stack.Pop();
42
Debug.Assert(currentNode == node);
43
stack.Peek().AddChildUntyped(node, role);
46
void AddTerminal(Role<VBTokenNode> role)
48
stack.Peek().AddChild(new VBTokenNode(t.Location, t.EndLocation), role);
51
void AddChild<T>(T childNode, Role<T> role) where T : AstNode
53
if (childNode != null) {
54
stack.Peek().AddChild(childNode, role);
58
StringBuilder qualidentBuilder = new StringBuilder();
62
[System.Diagnostics.DebuggerStepThrough]
70
[System.Diagnostics.DebuggerStepThrough]
72
return lexer.LookAhead;
87
public void Error(string s)
89
if (errDist >= MinErrDist) {
90
this.Errors.Error(la.line, la.col, s);
102
public AstType ParseAstType()
108
// public Expression ParseExpression()
110
// lexer.SetInitialContext(SnippetType.Expression);
111
// lexer.NextToken();
112
// Location startLocation = la.Location;
115
// while (la.kind == Tokens.EOL) lexer.NextToken();
116
// if (expr != null) {
117
// expr.StartLocation = startLocation;
118
// expr.EndLocation = t.EndLocation;
119
// expr.AcceptVisitor(new SetParentVisitor(), null);
121
// Expect(Tokens.EOF);
125
// public BlockStatement ParseBlock()
127
// lexer.NextToken();
128
// compilationUnit = new CompilationUnit();
130
// Location startLocation = la.Location;
134
// st.StartLocation = startLocation;
136
// st.EndLocation = t.EndLocation;
138
// st.EndLocation = la.Location;
139
// st.AcceptVisitor(new SetParentVisitor(), null);
141
// Expect(Tokens.EOF);
142
// return st as BlockStatement;
145
// public List<AstNode> ParseTypeMembers()
147
// lexer.NextToken();
148
// TypeDeclaration newType = new TypeDeclaration(Modifiers.None, null);
149
// BlockStart(newType);
150
// ClassBody(newType);
152
// Expect(Tokens.EOF);
153
// newType.AcceptVisitor(new SetParentVisitor(), null);
154
// return newType.Children;
158
#region Conflict Resolvers
159
bool IsAliasImportsClause()
161
return IsIdentifierToken(la) && Peek(1).Kind == Tokens.Assign;
164
static bool IsIdentifierToken(Token tk)
166
return Tokens.IdentifierTokens[tk.kind] || tk.kind == Tokens.Identifier;
170
/* True, if "." is followed by an ident */
171
bool DotAndIdentOrKw () {
172
int peek = Peek(1).kind;
173
return la.kind == Tokens.Dot && (peek == Tokens.Identifier || peek >= Tokens.AddHandler);
176
bool IsIdentifiedExpressionRange()
180
// Peek(1) = As or Assign
181
Token token = Peek(1);
182
return IsIdentifierToken(la) && (token.kind == Tokens.As || token.kind == Tokens.Assign);
185
bool IsQueryExpression()
187
return (la.kind == Tokens.From || la.kind == Tokens.Aggregate) && IsIdentifierToken(Peek(1));
190
bool IsEndStmtAhead()
192
int peek = Peek(1).kind;
193
return la.kind == Tokens.End && (peek == Tokens.EOL || peek == Tokens.Colon);
196
bool IsNotClosingParenthesis() {
197
return la.kind != Tokens.CloseParenthesis;
201
True, if ident is followed by "=" or by ":" and "="
203
bool IsNamedAssign() {
204
return Peek(1).kind == Tokens.ColonAssign;
207
bool IsObjectCreation() {
208
return la.kind == Tokens.As && Peek(1).kind == Tokens.New;
211
bool IsNewExpression() {
212
return la.kind == Tokens.New;
216
True, if "<" is followed by the ident "assembly" or "module"
218
bool IsGlobalAttrTarget () {
220
return la.kind == Tokens.LessThan && ( string.Equals(pt.val, "assembly", StringComparison.InvariantCultureIgnoreCase) || string.Equals(pt.val, "module", StringComparison.InvariantCultureIgnoreCase));
224
True if the next token is a "(" and is followed by "," or ")"
228
int peek = Peek(1).kind;
229
return la.kind == Tokens.OpenParenthesis
230
&& (peek == Tokens.Comma || peek == Tokens.CloseParenthesis);
234
True if the next token is an identifier
236
bool IsLoopVariableDeclaration()
238
if (!IsIdentifierToken(la))
241
Token x = lexer.Peek();
242
if (x.kind == Tokens.OpenParenthesis) {
245
} while (x.kind == Tokens.Comma);
246
if (x.kind != Tokens.CloseParenthesis)
250
return x.kind == Tokens.As || x.kind == Tokens.Assign;
255
return la.kind == Tokens.OpenParenthesis;
259
True, if the comma is not a trailing one,
260
like the last one in: a, b, c,
262
bool NotFinalComma() {
263
int peek = Peek(1).kind;
264
return la.kind == Tokens.Comma &&
265
peek != Tokens.CloseCurlyBrace;
269
True, if the next token is "Else" and this one
274
int peek = Peek(1).kind;
275
return la.kind == Tokens.Else && peek == Tokens.If;
279
True if the next token is goto and this one is
280
followed by minus ("-") (this is allowd in in
283
bool IsNegativeLabelName()
285
int peek = Peek(1).kind;
286
return la.kind == Tokens.GoTo && peek == Tokens.Minus;
290
True if the next statement is a "Resume next" statement
294
int peek = Peek(1).kind;
295
return la.kind == Tokens.Resume && peek == Tokens.Next;
299
/// Returns True, if ident/literal integer is followed by ":"
303
return (la.kind == Tokens.Identifier || la.kind == Tokens.LiteralInteger)
304
&& Peek(1).kind == Tokens.Colon;
308
/// Returns true if a property declaration is an automatic property.
310
bool IsAutomaticProperty()
316
// look for attributes
317
while (tn.kind == Tokens.LessThan) {
318
while (braceCount > 0 || tn.kind != Tokens.GreaterThan) {
320
if (tn.kind == Tokens.OpenParenthesis)
322
if (tn.kind == Tokens.CloseParenthesis)
325
Debug.Assert(tn.kind == Tokens.GreaterThan);
329
// look for modifiers
330
var allowedTokens = new[] {
331
Tokens.Public, Tokens.Protected,
332
Tokens.Friend, Tokens.Private
335
while (allowedTokens.Contains(tn.kind))
338
if (tn.Kind != Tokens.Get && tn.Kind != Tokens.Set)
344
bool IsNotStatementSeparator()
346
return la.kind == Tokens.Colon && Peek(1).kind == Tokens.EOL;
349
static bool IsMustOverride(AttributedNode node)
351
return node.Modifiers.HasFlag(Modifiers.MustOverride);
354
/* Writes the type name represented through the expression into the string builder. */
355
/* Returns true when the expression was converted successfully, returns false when */
356
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */
357
// bool WriteFullTypeName(StringBuilder b, Expression expr)
359
// MemberReferenceExpression fre = expr as MemberReferenceExpression;
360
// if (fre != null) {
361
// bool result = WriteFullTypeName(b, fre.TargetObject);
362
// if (b.Length > 0) b.Append('.');
363
// b.Append(fre.MemberName);
365
// } else if (expr is SimpleNameExpression) {
366
// b.Append(((SimpleNameExpression)expr).Identifier);
373
void EnsureIsZero(Expression expr)
375
if (!(expr is PrimitiveExpression) || (expr as PrimitiveExpression).StringValue != "0")
376
Error("lower bound of array must be zero");
379
public bool ParseMethodBodies { get; set; }
381
public VBLexer Lexer {
387
public Errors Errors {
393
public CompilationUnit CompilationUnit {
395
return compilationUnit;
401
if (errDist >= MinErrDist) {
402
errors.SynErr(lexer.LookAhead.line, lexer.LookAhead.col, n);
407
void SemErr(string msg)
409
if (errDist >= MinErrDist) {
410
errors.Error(lexer.Token.line, lexer.Token.col, msg);
417
if (lexer.LookAhead.kind == n) {
424
#region System.IDisposable interface implementation
425
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
426
public void Dispose()