Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1586 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
20 changed files with 3045 additions and 3837 deletions
@ -0,0 +1,506 @@ |
|||||||
|
/* |
||||||
|
* Created by SharpDevelop. |
||||||
|
* User: Daniel Grunwald |
||||||
|
* Date: 16.07.2006 |
||||||
|
* Time: 15:55 |
||||||
|
*/ |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Text; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.NRefactory.Parser.AST; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.Parser.CSharp |
||||||
|
{ |
||||||
|
internal sealed partial class Parser : AbstractParser |
||||||
|
{ |
||||||
|
Lexer lexer; |
||||||
|
|
||||||
|
public Parser(ILexer lexer) : base(lexer) |
||||||
|
{ |
||||||
|
this.lexer = (Lexer)lexer; |
||||||
|
} |
||||||
|
|
||||||
|
string assemblyName = null; |
||||||
|
StringBuilder qualidentBuilder = new StringBuilder(); |
||||||
|
|
||||||
|
public string ContainingAssembly { |
||||||
|
set { |
||||||
|
assemblyName = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Token t { |
||||||
|
[System.Diagnostics.DebuggerStepThrough] |
||||||
|
get { |
||||||
|
return lexer.Token; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Token la { |
||||||
|
[System.Diagnostics.DebuggerStepThrough] |
||||||
|
get { |
||||||
|
return lexer.LookAhead; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Error(string s) |
||||||
|
{ |
||||||
|
if (errDist >= minErrDist) { |
||||||
|
errors.Error(la.line, la.col, s); |
||||||
|
} |
||||||
|
errDist = 0; |
||||||
|
} |
||||||
|
|
||||||
|
public override Expression ParseExpression() |
||||||
|
{ |
||||||
|
lexer.NextToken(); |
||||||
|
Expression expr; |
||||||
|
Expr(out expr); |
||||||
|
return expr; |
||||||
|
} |
||||||
|
// Begin ISTypeCast
|
||||||
|
bool IsTypeCast() |
||||||
|
{ |
||||||
|
if (la.kind != Tokens.OpenParenthesis) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (IsSimpleTypeCast()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return GuessTypeCast(); |
||||||
|
} |
||||||
|
|
||||||
|
// "(" ( typeKW [ "[" {","} "]" | "*" ] | void ( "[" {","} "]" | "*" ) ) ")"
|
||||||
|
// only for built-in types, all others use GuessTypeCast!
|
||||||
|
bool IsSimpleTypeCast () |
||||||
|
{ |
||||||
|
// assert: la.kind == _lpar
|
||||||
|
lexer.StartPeek(); |
||||||
|
Token pt = lexer.Peek(); |
||||||
|
|
||||||
|
if (!IsTypeKWForTypeCast(ref pt)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (pt.kind == Tokens.Question) |
||||||
|
pt = lexer.Peek(); |
||||||
|
return pt.kind == Tokens.CloseParenthesis; |
||||||
|
} |
||||||
|
|
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
bool IsTypeKWForTypeCast(ref Token pt) |
||||||
|
{ |
||||||
|
if (Tokens.TypeKW[pt.kind]) { |
||||||
|
pt = lexer.Peek(); |
||||||
|
return IsPointerOrDims(ref pt) && SkipQuestionMark(ref pt); |
||||||
|
} else if (pt.kind == Tokens.Void) { |
||||||
|
pt = lexer.Peek(); |
||||||
|
return IsPointerOrDims(ref pt); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
bool IsTypeNameOrKWForTypeCast(ref Token pt) |
||||||
|
{ |
||||||
|
if (IsTypeKWForTypeCast(ref pt)) |
||||||
|
return true; |
||||||
|
else |
||||||
|
return IsTypeNameForTypeCast(ref pt); |
||||||
|
} |
||||||
|
|
||||||
|
// TypeName = ident [ "::" ident ] { ["<" TypeNameOrKW { "," TypeNameOrKW } ">" ] "." ident } ["?"] PointerOrDims
|
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
bool IsTypeNameForTypeCast(ref Token pt) |
||||||
|
{ |
||||||
|
// ident
|
||||||
|
if (pt.kind != Tokens.Identifier) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
pt = Peek(); |
||||||
|
// "::" ident
|
||||||
|
if (pt.kind == Tokens.DoubleColon) { |
||||||
|
pt = Peek(); |
||||||
|
if (pt.kind != Tokens.Identifier) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
// { ["<" TypeNameOrKW { "," TypeNameOrKW } ">" ] "." ident }
|
||||||
|
while (true) { |
||||||
|
if (pt.kind == Tokens.LessThan) { |
||||||
|
do { |
||||||
|
pt = Peek(); |
||||||
|
if (!IsTypeNameOrKWForTypeCast(ref pt)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} while (pt.kind == Tokens.Comma); |
||||||
|
if (pt.kind != Tokens.GreaterThan) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
if (pt.kind != Tokens.Dot) |
||||||
|
break; |
||||||
|
pt = Peek(); |
||||||
|
if (pt.kind != Tokens.Identifier) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
// ["?"]
|
||||||
|
if (pt.kind == Tokens.Question) { |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
if (pt.kind == Tokens.Times || pt.kind == Tokens.OpenSquareBracket) { |
||||||
|
return IsPointerOrDims(ref pt); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// "(" TypeName ")" castFollower
|
||||||
|
bool GuessTypeCast () |
||||||
|
{ |
||||||
|
// assert: la.kind == _lpar
|
||||||
|
StartPeek(); |
||||||
|
Token pt = Peek(); |
||||||
|
|
||||||
|
if (!IsTypeNameForTypeCast(ref pt)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// ")"
|
||||||
|
if (pt.kind != Tokens.CloseParenthesis) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
// check successor
|
||||||
|
pt = Peek(); |
||||||
|
return Tokens.CastFollower[pt.kind] || (Tokens.TypeKW[pt.kind] && lexer.Peek().kind == Tokens.Dot); |
||||||
|
} |
||||||
|
// END IsTypeCast
|
||||||
|
|
||||||
|
/* Checks whether the next sequences of tokens is a qualident * |
||||||
|
* and returns the qualident string */ |
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
bool IsQualident(ref Token pt, out string qualident) |
||||||
|
{ |
||||||
|
if (pt.kind == Tokens.Identifier) { |
||||||
|
qualidentBuilder.Length = 0; qualidentBuilder.Append(pt.val); |
||||||
|
pt = Peek(); |
||||||
|
while (pt.kind == Tokens.Dot || pt.kind == Tokens.DoubleColon) { |
||||||
|
pt = Peek(); |
||||||
|
if (pt.kind != Tokens.Identifier) { |
||||||
|
qualident = String.Empty; |
||||||
|
return false; |
||||||
|
} |
||||||
|
qualidentBuilder.Append('.'); |
||||||
|
qualidentBuilder.Append(pt.val); |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
qualident = qualidentBuilder.ToString(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
qualident = String.Empty; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/* Skips generic type extensions */ |
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
|
||||||
|
/* skip: { "*" | "[" { "," } "]" } */ |
||||||
|
/* !!! Proceeds from current peek position !!! */ |
||||||
|
bool IsPointerOrDims (ref Token pt) |
||||||
|
{ |
||||||
|
for (;;) { |
||||||
|
if (pt.kind == Tokens.OpenSquareBracket) { |
||||||
|
do pt = Peek(); |
||||||
|
while (pt.kind == Tokens.Comma); |
||||||
|
if (pt.kind != Tokens.CloseSquareBracket) return false; |
||||||
|
} else if (pt.kind != Tokens.Times) break; |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/* Return the n-th token after the current lookahead token */ |
||||||
|
void StartPeek() |
||||||
|
{ |
||||||
|
lexer.StartPeek(); |
||||||
|
} |
||||||
|
|
||||||
|
Token Peek() |
||||||
|
{ |
||||||
|
return lexer.Peek(); |
||||||
|
} |
||||||
|
|
||||||
|
Token Peek (int n) |
||||||
|
{ |
||||||
|
lexer.StartPeek(); |
||||||
|
Token x = la; |
||||||
|
while (n > 0) { |
||||||
|
x = lexer.Peek(); |
||||||
|
n--; |
||||||
|
} |
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
/*-----------------------------------------------------------------* |
||||||
|
* Resolver routines to resolve LL(1) conflicts: * * |
||||||
|
* These resolution routine return a boolean value that indicates * |
||||||
|
* whether the alternative at hand shall be choosen or not. * |
||||||
|
* They are used in IF ( ... ) expressions. * |
||||||
|
*-----------------------------------------------------------------*/ |
||||||
|
|
||||||
|
/* True, if ident is followed by "=" */ |
||||||
|
bool IdentAndAsgn () |
||||||
|
{ |
||||||
|
return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.Assign; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsAssignment () { return IdentAndAsgn(); } |
||||||
|
|
||||||
|
/* True, if ident is followed by ",", "=", or ";" */ |
||||||
|
bool IdentAndCommaOrAsgnOrSColon () { |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Identifier && |
||||||
|
(peek == Tokens.Comma || peek == Tokens.Assign || peek == Tokens.Semicolon); |
||||||
|
} |
||||||
|
bool IsVarDecl () { return IdentAndCommaOrAsgnOrSColon(); } |
||||||
|
|
||||||
|
/* True, if the comma is not a trailing one, * |
||||||
|
* like the last one in: a, b, c, */ |
||||||
|
bool NotFinalComma () { |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Comma && |
||||||
|
peek != Tokens.CloseCurlyBrace && peek != Tokens.CloseSquareBracket; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "void" is followed by "*" */ |
||||||
|
bool NotVoidPointer () { |
||||||
|
return la.kind == Tokens.Void && Peek(1).kind != Tokens.Times; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "checked" or "unchecked" are followed by "{" */ |
||||||
|
bool UnCheckedAndLBrace () { |
||||||
|
return la.kind == Tokens.Checked || la.kind == Tokens.Unchecked && |
||||||
|
Peek(1).kind == Tokens.OpenCurlyBrace; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "." is followed by an ident */ |
||||||
|
bool DotAndIdent () { |
||||||
|
return la.kind == Tokens.Dot && Peek(1).kind == Tokens.Identifier; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if ident is followed by ":" */ |
||||||
|
bool IdentAndColon () { |
||||||
|
return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.Colon; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsLabel () { return IdentAndColon(); } |
||||||
|
|
||||||
|
/* True, if ident is followed by "(" */ |
||||||
|
bool IdentAndLPar () { |
||||||
|
return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.OpenParenthesis; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "catch" is followed by "(" */ |
||||||
|
bool CatchAndLPar () { |
||||||
|
return la.kind == Tokens.Catch && Peek(1).kind == Tokens.OpenParenthesis; |
||||||
|
} |
||||||
|
bool IsTypedCatch () { return CatchAndLPar(); } |
||||||
|
|
||||||
|
/* True, if "[" is followed by the ident "assembly" */ |
||||||
|
bool IsGlobalAttrTarget () { |
||||||
|
Token pt = Peek(1); |
||||||
|
return la.kind == Tokens.OpenSquareBracket && |
||||||
|
pt.kind == Tokens.Identifier && pt.val == "assembly"; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "[" is followed by "," or "]" */ |
||||||
|
bool LBrackAndCommaOrRBrack () { |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.OpenSquareBracket && |
||||||
|
(peek == Tokens.Comma || peek == Tokens.CloseSquareBracket); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsDims () { return LBrackAndCommaOrRBrack(); } |
||||||
|
|
||||||
|
/* True, if "[" is followed by "," or "]" */ |
||||||
|
/* or if the current token is "*" */ |
||||||
|
bool TimesOrLBrackAndCommaOrRBrack () { |
||||||
|
return la.kind == Tokens.Times || LBrackAndCommaOrRBrack(); |
||||||
|
} |
||||||
|
bool IsPointerOrDims () { return TimesOrLBrackAndCommaOrRBrack(); } |
||||||
|
bool IsPointer () { return la.kind == Tokens.Times; } |
||||||
|
|
||||||
|
|
||||||
|
bool SkipGeneric(ref Token pt) |
||||||
|
{ |
||||||
|
if (pt.kind == Tokens.LessThan) { |
||||||
|
do { |
||||||
|
pt = Peek(); |
||||||
|
if (!IsTypeNameOrKWForTypeCast(ref pt)) return false; |
||||||
|
} while (pt.kind == Tokens.Comma); |
||||||
|
if (pt.kind != Tokens.GreaterThan) return false; |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
bool SkipQuestionMark(ref Token pt) |
||||||
|
{ |
||||||
|
if (pt.kind == Tokens.Question) { |
||||||
|
pt = Peek(); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead is a primitive type keyword, or */ |
||||||
|
/* if it is a type declaration followed by an ident */ |
||||||
|
bool IsLocalVarDecl () { |
||||||
|
if (IsYieldStatement()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if ((Tokens.TypeKW[la.kind] && Peek(1).kind != Tokens.Dot) || la.kind == Tokens.Void) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
StartPeek(); |
||||||
|
Token pt = la; |
||||||
|
return IsTypeNameOrKWForTypeCast(ref pt) && pt.kind == Tokens.Identifier; |
||||||
|
} |
||||||
|
|
||||||
|
/* True if lookahead is type parameters (<...>) followed by the specified token */ |
||||||
|
bool IsGenericFollowedBy(int token) |
||||||
|
{ |
||||||
|
Token t = la; |
||||||
|
if (t.kind != Tokens.LessThan) return false; |
||||||
|
StartPeek(); |
||||||
|
return SkipGeneric(ref t) && t.kind == token; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsExplicitInterfaceImplementation() |
||||||
|
{ |
||||||
|
StartPeek(); |
||||||
|
Token pt = la; |
||||||
|
pt = Peek(); |
||||||
|
if (pt.kind == Tokens.Dot || pt.kind == Tokens.DoubleColon) |
||||||
|
return true; |
||||||
|
if (pt.kind == Tokens.LessThan) { |
||||||
|
if (SkipGeneric(ref pt)) |
||||||
|
return pt.kind == Tokens.Dot; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead ident is "where" */ |
||||||
|
bool IdentIsWhere () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "where"; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead ident is "get" */ |
||||||
|
bool IdentIsGet () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "get"; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead ident is "set" */ |
||||||
|
bool IdentIsSet () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "set"; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead ident is "add" */ |
||||||
|
bool IdentIsAdd () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "add"; |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead ident is "remove" */ |
||||||
|
bool IdentIsRemove () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "remove"; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsNotYieldStatement () { |
||||||
|
return !IsYieldStatement(); |
||||||
|
} |
||||||
|
/* True, if lookahead ident is "yield" and than follows a break or return */ |
||||||
|
bool IsYieldStatement () { |
||||||
|
return la.kind == Tokens.Identifier && la.val == "yield" && (Peek(1).kind == Tokens.Return || Peek(1).kind == Tokens.Break); |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if lookahead is a local attribute target specifier, * |
||||||
|
* i.e. one of "event", "return", "field", "method", * |
||||||
|
* "module", "param", "property", or "type" */ |
||||||
|
bool IsLocalAttrTarget () { |
||||||
|
int cur = la.kind; |
||||||
|
string val = la.val; |
||||||
|
|
||||||
|
return (cur == Tokens.Event || cur == Tokens.Return || |
||||||
|
(cur == Tokens.Identifier && |
||||||
|
(val == "field" || val == "method" || val == "module" || |
||||||
|
val == "param" || val == "property" || val == "type"))) && |
||||||
|
Peek(1).kind == Tokens.Colon; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsShiftRight() |
||||||
|
{ |
||||||
|
Token next = Peek(1); |
||||||
|
// TODO : Add col test (seems not to work, lexer bug...) : && la.col == next.col - 1
|
||||||
|
return (la.kind == Tokens.GreaterThan && next.kind == Tokens.GreaterThan); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsTypeReferenceExpression(Expression expr) |
||||||
|
{ |
||||||
|
if (expr is TypeReferenceExpression) return ((TypeReferenceExpression)expr).TypeReference.GenericTypes.Count == 0; |
||||||
|
while (expr is FieldReferenceExpression) { |
||||||
|
expr = ((FieldReferenceExpression)expr).TargetObject; |
||||||
|
if (expr is TypeReferenceExpression) return true; |
||||||
|
} |
||||||
|
return expr is IdentifierExpression; |
||||||
|
} |
||||||
|
|
||||||
|
TypeReferenceExpression GetTypeReferenceExpression(Expression expr, List<TypeReference> genericTypes) |
||||||
|
{ |
||||||
|
TypeReferenceExpression tre = expr as TypeReferenceExpression; |
||||||
|
if (tre != null) { |
||||||
|
return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes)); |
||||||
|
} |
||||||
|
StringBuilder b = new StringBuilder(); |
||||||
|
if (!WriteFullTypeName(b, expr)) { |
||||||
|
// there is some TypeReferenceExpression hidden in the expression
|
||||||
|
while (expr is FieldReferenceExpression) { |
||||||
|
expr = ((FieldReferenceExpression)expr).TargetObject; |
||||||
|
} |
||||||
|
tre = expr as TypeReferenceExpression; |
||||||
|
if (tre != null) { |
||||||
|
TypeReference typeRef = tre.TypeReference; |
||||||
|
if (typeRef.GenericTypes.Count == 0) { |
||||||
|
typeRef = typeRef.Clone(); |
||||||
|
typeRef.Type += "." + b.ToString(); |
||||||
|
typeRef.GenericTypes.AddRange(genericTypes); |
||||||
|
} else { |
||||||
|
typeRef = new InnerClassTypeReference(typeRef, b.ToString(), genericTypes); |
||||||
|
} |
||||||
|
return new TypeReferenceExpression(typeRef); |
||||||
|
} |
||||||
|
} |
||||||
|
return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes)); |
||||||
|
} |
||||||
|
|
||||||
|
/* Writes the type name represented through the expression into the string builder. */ |
||||||
|
/* Returns true when the expression was converted successfully, returns false when */ |
||||||
|
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */ |
||||||
|
bool WriteFullTypeName(StringBuilder b, Expression expr) |
||||||
|
{ |
||||||
|
FieldReferenceExpression fre = expr as FieldReferenceExpression; |
||||||
|
if (fre != null) { |
||||||
|
bool result = WriteFullTypeName(b, fre.TargetObject); |
||||||
|
if (b.Length > 0) b.Append('.'); |
||||||
|
b.Append(fre.FieldName); |
||||||
|
return result; |
||||||
|
} else if (expr is IdentifierExpression) { |
||||||
|
b.Append(((IdentifierExpression)expr).Identifier); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,269 @@ |
|||||||
|
/* |
||||||
|
* Created by SharpDevelop. |
||||||
|
* User: Daniel Grunwald |
||||||
|
* Date: 16.07.2006 |
||||||
|
* Time: 15:55 |
||||||
|
*/ |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Text; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.NRefactory.Parser.AST; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.Parser.VB |
||||||
|
{ |
||||||
|
internal sealed partial class Parser : AbstractParser |
||||||
|
{ |
||||||
|
Lexer lexer; |
||||||
|
|
||||||
|
public Parser(ILexer lexer) : base(lexer) |
||||||
|
{ |
||||||
|
this.lexer = (Lexer)lexer; |
||||||
|
} |
||||||
|
|
||||||
|
private StringBuilder qualidentBuilder = new StringBuilder(); |
||||||
|
|
||||||
|
Token t |
||||||
|
{ |
||||||
|
[System.Diagnostics.DebuggerStepThrough] |
||||||
|
get { |
||||||
|
return lexer.Token; |
||||||
|
} |
||||||
|
} |
||||||
|
Token la |
||||||
|
{ |
||||||
|
[System.Diagnostics.DebuggerStepThrough] |
||||||
|
get { |
||||||
|
return lexer.LookAhead; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Return the n-th token after the current lookahead token */ |
||||||
|
void StartPeek() |
||||||
|
{ |
||||||
|
lexer.StartPeek(); |
||||||
|
} |
||||||
|
|
||||||
|
Token Peek() |
||||||
|
{ |
||||||
|
return lexer.Peek(); |
||||||
|
} |
||||||
|
|
||||||
|
Token Peek (int n) |
||||||
|
{ |
||||||
|
lexer.StartPeek(); |
||||||
|
Token x = la; |
||||||
|
while (n > 0) { |
||||||
|
x = lexer.Peek(); |
||||||
|
n--; |
||||||
|
} |
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
public void Error(string s) |
||||||
|
{ |
||||||
|
if (errDist >= minErrDist) { |
||||||
|
errors.Error(la.line, la.col, s); |
||||||
|
} |
||||||
|
errDist = 0; |
||||||
|
} |
||||||
|
|
||||||
|
public override Expression ParseExpression() |
||||||
|
{ |
||||||
|
lexer.NextToken(); |
||||||
|
Expression expr; |
||||||
|
Expr(out expr); |
||||||
|
return expr; |
||||||
|
} |
||||||
|
|
||||||
|
bool LeaveBlock() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return Tokens.BlockSucc[la.kind] && (la.kind != Tokens.End || peek == Tokens.EOL || peek == Tokens.Colon); |
||||||
|
} |
||||||
|
|
||||||
|
/* True, if "." is followed by an ident */ |
||||||
|
bool DotAndIdentOrKw () { |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Dot && (peek == Tokens.Identifier || peek >= Tokens.AddHandler); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsEndStmtAhead() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.End && (peek == Tokens.EOL || peek == Tokens.Colon); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsNotClosingParenthesis() { |
||||||
|
return la.kind != Tokens.CloseParenthesis; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if ident is followed by "=" |
||||||
|
*/ |
||||||
|
bool IdentAndAsgn () { |
||||||
|
if(la.kind == Tokens.Identifier) { |
||||||
|
if(Peek(1).kind == Tokens.Assign) return true; |
||||||
|
if(Peek(1).kind == Tokens.Colon && Peek(2).kind == Tokens.Assign) return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if ident is followed by "=" or by ":" and "=" |
||||||
|
*/ |
||||||
|
bool IsNamedAssign() { |
||||||
|
// if(Peek(1).kind == Tokens.Assign) return true; // removed: not in the lang spec
|
||||||
|
if(Peek(1).kind == Tokens.Colon && Peek(2).kind == Tokens.Assign) return true; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsObjectCreation() { |
||||||
|
return la.kind == Tokens.As && Peek(1).kind == Tokens.New; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if "<" is followed by the ident "assembly" or "module" |
||||||
|
*/ |
||||||
|
bool IsGlobalAttrTarget () { |
||||||
|
Token pt = Peek(1); |
||||||
|
return la.kind == Tokens.LessThan && ( string.Equals(pt.val, "assembly", StringComparison.InvariantCultureIgnoreCase) || string.Equals(pt.val, "module", StringComparison.InvariantCultureIgnoreCase)); |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True if the next token is a "(" and is followed by "," or ")" |
||||||
|
*/ |
||||||
|
bool IsDims() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.OpenParenthesis |
||||||
|
&& (peek == Tokens.Comma || peek == Tokens.CloseParenthesis); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsSize() |
||||||
|
{ |
||||||
|
return la.kind == Tokens.OpenParenthesis; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if the comma is not a trailing one, |
||||||
|
like the last one in: a, b, c, |
||||||
|
*/ |
||||||
|
bool NotFinalComma() { |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Comma && |
||||||
|
peek != Tokens.CloseCurlyBrace; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if the next token is "Else" and this one |
||||||
|
if followed by "If" |
||||||
|
*/ |
||||||
|
bool IsElseIf() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Else && peek == Tokens.If; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True if the next token is goto and this one is |
||||||
|
followed by minus ("-") (this is allowd in in |
||||||
|
error clauses) |
||||||
|
*/ |
||||||
|
bool IsNegativeLabelName() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.GoTo && peek == Tokens.Minus; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True if the next statement is a "Resume next" statement |
||||||
|
*/ |
||||||
|
bool IsResumeNext() |
||||||
|
{ |
||||||
|
int peek = Peek(1).kind; |
||||||
|
return la.kind == Tokens.Resume && peek == Tokens.Next; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if ident/literal integer is followed by ":" |
||||||
|
*/ |
||||||
|
bool IsLabel() |
||||||
|
{ |
||||||
|
return (la.kind == Tokens.Identifier || la.kind == Tokens.LiteralInteger) |
||||||
|
&& Peek(1).kind == Tokens.Colon; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsNotStatementSeparator() |
||||||
|
{ |
||||||
|
return la.kind == Tokens.Colon && Peek(1).kind == Tokens.EOL; |
||||||
|
} |
||||||
|
|
||||||
|
bool IsAssignment () |
||||||
|
{ |
||||||
|
return IdentAndAsgn(); |
||||||
|
} |
||||||
|
|
||||||
|
bool IsMustOverride(Modifiers m) |
||||||
|
{ |
||||||
|
return m.Contains(Modifier.Abstract); |
||||||
|
} |
||||||
|
|
||||||
|
TypeReferenceExpression GetTypeReferenceExpression(Expression expr, List<TypeReference> genericTypes) |
||||||
|
{ |
||||||
|
TypeReferenceExpression tre = expr as TypeReferenceExpression; |
||||||
|
if (tre != null) { |
||||||
|
return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes)); |
||||||
|
} |
||||||
|
StringBuilder b = new StringBuilder(); |
||||||
|
if (!WriteFullTypeName(b, expr)) { |
||||||
|
// there is some TypeReferenceExpression hidden in the expression
|
||||||
|
while (expr is FieldReferenceExpression) { |
||||||
|
expr = ((FieldReferenceExpression)expr).TargetObject; |
||||||
|
} |
||||||
|
tre = expr as TypeReferenceExpression; |
||||||
|
if (tre != null) { |
||||||
|
TypeReference typeRef = tre.TypeReference; |
||||||
|
if (typeRef.GenericTypes.Count == 0) { |
||||||
|
typeRef = typeRef.Clone(); |
||||||
|
typeRef.Type += "." + b.ToString(); |
||||||
|
typeRef.GenericTypes.AddRange(genericTypes); |
||||||
|
} else { |
||||||
|
typeRef = new InnerClassTypeReference(typeRef, b.ToString(), genericTypes); |
||||||
|
} |
||||||
|
return new TypeReferenceExpression(typeRef); |
||||||
|
} |
||||||
|
} |
||||||
|
return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes)); |
||||||
|
} |
||||||
|
|
||||||
|
/* Writes the type name represented through the expression into the string builder. */ |
||||||
|
/* Returns true when the expression was converted successfully, returns false when */ |
||||||
|
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */ |
||||||
|
bool WriteFullTypeName(StringBuilder b, Expression expr) |
||||||
|
{ |
||||||
|
FieldReferenceExpression fre = expr as FieldReferenceExpression; |
||||||
|
if (fre != null) { |
||||||
|
bool result = WriteFullTypeName(b, fre.TargetObject); |
||||||
|
if (b.Length > 0) b.Append('.'); |
||||||
|
b.Append(fre.FieldName); |
||||||
|
return result; |
||||||
|
} else if (expr is IdentifierExpression) { |
||||||
|
b.Append(((IdentifierExpression)expr).Identifier); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
True, if lookahead is a local attribute target specifier, |
||||||
|
i.e. one of "event", "return", "field", "method", |
||||||
|
"module", "param", "property", or "type" |
||||||
|
*/ |
||||||
|
bool IsLocalAttrTarget() { |
||||||
|
// TODO
|
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue