📄 parser.cs
字号:
ThrowError(E_UnexpectedToken(t));
}
t = m_lexer.PeekNextToken();
} // end member decl list
ReadExpectedToken(Token.Type.cRCurly);
MethodDecl [] arMethods = MethodDeclFromArray(alMethods);
FieldDecl [] arFields = FieldDeclFromArray(alFields);
PropertyDecl [] arProperties = PropertyDeclFromArray(alProperties);
EventDecl [] arEvents = (EventDecl[]) alEvents.ToArray(typeof(EventDecl));
TypeDeclBase[] arNestedTypes = new TypeDeclBase[alNestedTypes.Count];
for(int i = 0; i < alNestedTypes.Count; i++)
arNestedTypes[i] = (TypeDeclBase) alNestedTypes[i];
return new ClassDecl(
stClassName,
arBase,
arMethods,
arProperties,
arFields,
arEvents,
arNestedTypes,
modsClass,
fIsClass
);
}
#region Array conversions
//-----------------------------------------------------------------------------
// Helpes to convert from ArrayLists to normal arrays
// Have to do this until mscorlib works the bugs out of its array conversion
// stuff.
//-----------------------------------------------------------------------------
protected ParamVarDecl[] ParamVarDeclFromArray(ArrayList alParams)
{
ParamVarDecl[] v = new ParamVarDecl[alParams.Count];
for(int i = 0; i < alParams.Count; i++)
v[i] = (ParamVarDecl) alParams[i];
return v;
}
protected LocalVarDecl[] LocalVarDeclFromArray(ArrayList alParams)
{
LocalVarDecl[] v = new LocalVarDecl[alParams.Count];
for(int i = 0; i < alParams.Count; i++)
v[i] = (LocalVarDecl) alParams[i];
return v;
}
protected FieldDecl[] FieldDeclFromArray(ArrayList alParams)
{
FieldDecl[] v = new FieldDecl[alParams.Count];
for(int i = 0; i < alParams.Count; i++)
v[i] = (FieldDecl) alParams[i];
return v;
}
protected PropertyDecl [] PropertyDeclFromArray(ArrayList alProperties)
{
PropertyDecl [] v = new PropertyDecl[alProperties.Count];
for(int i = 0; i < alProperties.Count; i++)
v[i] = (PropertyDecl) alProperties[i];
return v;
}
protected Statement[] StatementFromArray(ArrayList alParams)
{
Statement[] v = new Statement[alParams.Count];
for(int i = 0; i < alParams.Count; i++)
v[i] = (Statement) alParams[i];
return v;
}
protected MethodDecl[] MethodDeclFromArray(ArrayList alParams)
{
MethodDecl[] v = new MethodDecl[alParams.Count];
for(int i = 0; i < alParams.Count; i++)
v[i] = (MethodDecl) alParams[i];
return v;
}
#endregion
//-----------------------------------------------------------------------------
// Parse a parameter list (including opening & closing parens)
// -> '(' (''|'ref'|'out') typesig id ',' typesig id ',' ... ')'
//-----------------------------------------------------------------------------
// @todo - allow out,ref
protected ParamVarDecl [] ParseParamList()
{
ReadExpectedToken(Token.Type.cLParen);
// Read parameter list. Keep looping until we get the closing ')'
// param-> Typesig id
// paramlist-> <comma separated list of 'param'>
ArrayList alParams = new ArrayList();
Token t = m_lexer.PeekNextToken();
if (t.TokenType == Token.Type.cRParen)
ConsumeNextToken();
bool fUsedParams = false;
while (t.TokenType != Token.Type.cRParen)
{
Debug.Assert(!fUsedParams, "@todo - 'params' only allowed on last thing");
t = m_lexer.PeekNextToken();
// Check for flow modifier
AST.EArgFlow eFlow = EArgFlow.cIn;
if (t.TokenType == Token.Type.cRef)
eFlow = EArgFlow.cRef;
else if (t.TokenType == Token.Type.cOut)
eFlow = EArgFlow.cOut;
// Allow 'params' modifier for a vararg on last parameter
else if (t.TokenType == Token.Type.cParams)
{
fUsedParams = true;
ConsumeNextToken();
t = m_lexer.PeekNextToken();
}
if (eFlow != EArgFlow.cIn) {
ConsumeNextToken();
}
// param-> Typesig id
NonRefTypeSig type = ParseTypeSig();
Identifier stName = ReadExpectedIdentifier();
VarDecl nodeDecl = new ParamVarDecl(stName, type, eFlow);
alParams.Add(nodeDecl);
t = m_lexer.GetNextToken();
CheckError_UnexpectedToken(t, new Token.Type [] { Token.Type.cComma, Token.Type.cRParen } );
}
ParamVarDecl [] arParams = ParamVarDeclFromArray(alParams);
return arParams;
}
//-----------------------------------------------------------------------------
// Partial parse an Indexer decl
//
// ** rules **
// IndexerDecl -> mods type 'this' '[' param_list ']' '{' property_body '}'
//-----------------------------------------------------------------------------
protected PropertyDecl PartialParseIndexerDecl(
Modifiers mods,
TypeSig typeReturn,
Identifier stMemberName
)
{
Debug.Assert(stMemberName.Text == "this");
// @todo - Change name to 'Item'
FileRange f = this.BeginRange();
ReadExpectedToken(Token.Type.cLSquare);
// @todo - For now, we only support one parameter
NonRefTypeSig t = this.ParseTypeSig();
Identifier idParam = this.ReadExpectedIdentifier();
ReadExpectedToken(Token.Type.cRSquare);
BlockStatement stmtGet;
BlockStatement stmtSet;
bool fHasGet;
bool fHasSet;
ParseAccessors(mods.IsAbstract, stMemberName,
out stmtGet, out fHasGet,
out stmtSet, out fHasSet);
PropertyDecl p = new PropertyDecl(
stMemberName, typeReturn,
new ParamVarDecl(idParam, t, EArgFlow.cIn),
stmtGet, fHasGet,
stmtSet, fHasSet,
mods);
p.SetLocation(this.EndRange(f));
return p;
}
//-----------------------------------------------------------------------------
// Partial parse an event
// ** rules **
// EventDecl -> mods 'event' type id ';'
//-----------------------------------------------------------------------------
protected EventDecl PartialParseEventDecl(
Modifiers mods)
{
FileRange f = this.BeginRange();
ReadExpectedToken(Token.Type.cEvent);
NonRefTypeSig t = ParseTypeSig();
Identifier idName = ReadExpectedIdentifier();
ReadExpectedToken(Token.Type.cSemi);
EventDecl node = new EventDecl(idName, t, mods);
node.SetLocation(this.EndRange(f));
return node;
}
//-----------------------------------------------------------------------------
// Partial parse a property decl.
// We've already parsed the modifiers, return type & member name, so
// pass those in as parameters. Start parsing at '{'
// Note that indexers are just properties that take parameters.
//
// ** rules **
// PropertyDecl -> mods type id '{' property_body '}'
//-----------------------------------------------------------------------------
protected PropertyDecl PartialParsePropertyDecl(
Modifiers mods,
TypeSig typeReturn,
Identifier stMemberName
)
{
// Note that properties can be abstract, in which case their bodyStmt is null.
// Also note that both get & set have the same modifiers
FileRange f = this.BeginRange();
BlockStatement stmtGet;
BlockStatement stmtSet;
bool fHasGet;
bool fHasSet;
ParseAccessors(mods.IsAbstract, stMemberName,
out stmtGet, out fHasGet,
out stmtSet, out fHasSet);
PropertyDecl p = new PropertyDecl(
stMemberName, typeReturn,
stmtGet, fHasGet,
stmtSet, fHasSet,
mods);
p.SetLocation(this.EndRange(f));
return p;
}
//-----------------------------------------------------------------------------
// Parse accessors
//
// *** rules ***
// propertyBody -> 'get' block | 'set' block |
// 'get' block 'set' block |
// 'set' block 'get' block
//
// For an abstract property:
// PropertyBody -> 'get' ';' | 'set' ';' |
// 'get' ';' 'set' ';' |
// 'set' ';' 'get' ';'
//-----------------------------------------------------------------------------
protected void ParseAccessors(
bool fIsAbstract,
Identifier stMemberName,
out BlockStatement stmtGet,
out bool fHasGet,
out BlockStatement stmtSet,
out bool fHasSet
)
{
// We've already parsed everything up until, but not including, the '{'
ReadExpectedToken(Token.Type.cLCurly);
stmtGet = null;
stmtSet = null;
fHasGet = false;
fHasSet = false;
Token t = m_lexer.GetNextToken();
// Parse the get/set accesssors
while(t.TokenType != Token.Type.cRCurly)
{
switch(t.TokenType)
{
case Token.Type.cGet:
if (fHasGet)
ThrowError(E_AccessorAlreadyDefined(stMemberName, true));
fHasGet = true;
if (fIsAbstract)
ReadExpectedToken(Token.Type.cSemi);
else
stmtGet = ParseStatementBlock();
break;
case Token.Type.cSet:
if (fHasSet)
ThrowError(E_AccessorAlreadyDefined(stMemberName, false));
fHasSet = true;
if (fIsAbstract)
ReadExpectedToken(Token.Type.cSemi);
else
stmtSet = ParseStatementBlock();
break;
default: // error
//this.ThrowError_UnexpectedToken(t, new Token.Type [] { Token.Type.cGet, Token.Type.cSet } );
ThrowError(E_UnexpectedToken(t, Token.Type.cGet, Token.Type.cSet));
break;
}
t = m_lexer.GetNextToken();
}
// Already consumed the closing '}', so we're done.
// So just do some error checks & create the ast node
if (!fHasGet && !fHasSet)
ThrowError(E_MissingAccessor(stMemberName));
}
//-----------------------------------------------------------------------------
// Parse for overloaded operator
// -> mods type 'operator' op '(' paramlist ')' '{' statementlist '}'
//-----------------------------------------------------------------------------
protected MethodDecl PartialParseOverloadedOp(
Modifiers mods, // must be public & static
TypeSig typeReturn
)
{
/*
Modifiers modsLegal = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static);
if (modsLegal.Flags != mods.Flags)
ThrowError_BadModsOnOps(typeReturn.Location);
*/
if (!mods.IsStatic || !mods.IsPublic)
ThrowError(E_BadModsOnOps(typeReturn.Location));
ReadExpectedToken(Token.Type.cOperator);
// Get the operator
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -