📄 parser.cs
字号:
ParserErrorException E_BadParamListOnOps(FileRange location, string stHint)
{
return new ParserErrorException(
Code.cBadParamListOnOps,
location,
"Bad parameter list for overloaded operator:" + stHint);
}
#endregion // Errors
#region Public Methods for IParser
//-----------------------------------------------------------------------------
// Top level function
// Parse a compile-unit (single source file)
// A program may contain multiple source files
//
// ** rules **
// Program -> NamespaceBody
//-----------------------------------------------------------------------------
public NamespaceDecl ParseSourceFile()
{
NamespaceDecl nGlobal = null;
try
{
NamespaceDecl t = null;
FileRange f = BeginRange();
t = ParseNamespaceBody(new Identifier("", null));
ReadExpectedToken(Token.Type.cEOF); // this could throw an exception...
t.SetLocation(EndRange(f));
// Only once we know we can't get any errors do we set nGlobal to non-null
nGlobal = t;
}
// Strip away parser errors. We must have called ThrowError() to throw
// this exception, and so we know it's already been reported.
catch(ParserErrorException)
{
}
// General catch to protect the parsing subsystem
catch(System.Exception e)
{
Blue.Driver.PrintError_InternalError(e, "parse");
}
return nGlobal;
}
#endregion
#region Linenumber tracking
//-----------------------------------------------------------------------------
// Helpers to rack line numbers.
// BeginRange returns a filerange to pass to GetCurRange(). Together these
// provide a FileRange to describe whatever is parsed between Begin & End.
// They can be nested.
//-----------------------------------------------------------------------------
protected FileRange BeginRange()
{
Token t = m_lexer.PeekNextToken();
FileRange f = new FileRange(t.Location.Filename,
t.Location.RowStart, t.Location.ColStart,
-1, -1);
return f;
}
protected FileRange EndRange(FileRange f)
{
// Can't peek at the current token to decide where the end is because
// it may be on another line.
// So we store the last token read and use that.
f.RowEnd = m_tLastRead.Location.RowEnd;
f.ColEnd = m_tLastRead.Location.ColEnd;
return f;
}
private Token m_tLastRead;
#endregion
#region Standard Helpers
//-----------------------------------------------------------------------------
// Helper to consume and throw away a token (useful after we peek at it)
//-----------------------------------------------------------------------------
protected void ConsumeNextToken()
{
m_tLastRead = m_lexer.GetNextToken();
}
//-----------------------------------------------------------------------------
// Helper to read an expected token and throw error if it's not found
//-----------------------------------------------------------------------------
protected Token ReadExpectedToken(Token.Type tExpected)
{
Token tNext = m_lexer.GetNextToken();
if (tNext.TokenType != tExpected)
{
ThrowError(E_UnexpectedToken(tNext, tExpected));
}
m_tLastRead = tNext;
return tNext;
}
//-----------------------------------------------------------------------------
// Helper to read an identifier and return the string
// Will throw an error if we don't have an identifier.
//-----------------------------------------------------------------------------
protected Identifier ReadExpectedIdentifier()
{
Token t = ReadExpectedToken(Token.Type.cId);
return new Identifier(t.Text, t.Location);
}
#endregion
#region Parse Declarations
//-----------------------------------------------------------------------------
// 3 sorts of Types.
//-----------------------------------------------------------------------------
protected enum Genre
{
cInterface,
cClass,
cStruct
}
//-----------------------------------------------------------------------------
// Parse a namespace.
//
// ** rules **
// Namespace -> 'namespace' id.id.id... '{' NamespaceBody '}'
//-----------------------------------------------------------------------------
protected NamespaceDecl ParseNamespace()
{
ReadExpectedToken(Token.Type.cNamespace);
return ParseNamespaceHelper();
}
protected NamespaceDecl ParseNamespaceHelper()
{
Token t;
Identifier i = ReadExpectedIdentifier();
t = m_lexer.PeekNextToken();
if (t.TokenType == Token.Type.cDot)
{
ConsumeNextToken();
NamespaceDecl nInner = ParseNamespaceHelper();
return new NamespaceDecl(i, null, new NamespaceDecl[] { nInner}, null, null);
}
FileRange f = this.BeginRange();
ReadExpectedToken(Token.Type.cLCurly);
NamespaceDecl n = ParseNamespaceBody(i);
ReadExpectedToken(Token.Type.cRCurly);
n.SetLocation(this.EndRange(f));
return n;
}
//-----------------------------------------------------------------------------
// Parse a namespace body (since we're just parsing the body, we have to
// pass in the name).
//
// ** rules **
// NamespaceBody-> (UsingDirectives)? (Namespace | ClassDecl)*
//-----------------------------------------------------------------------------
protected NamespaceDecl ParseNamespaceBody(Identifier idName)
{
UsingDirective[] arUsingNodes = ParseUsingDirectives();
//ArrayList alClasses = new ArrayList();
ArrayList alNestedNamespaces = new ArrayList();
//ArrayList alEnums = new ArrayList();
ArrayList alTypes = new ArrayList();
while(true)
{
Modifiers mods = ParseModifiers();
Token t = m_lexer.PeekNextToken();
switch(t.TokenType)
{
case Token.Type.cClass:
{
ClassDecl nodeClass = ParseClass(mods);
alTypes.Add(nodeClass);
}
break;
case Token.Type.cStruct:
{
ClassDecl nodeStruct = ParseStruct(mods);
alTypes.Add(nodeStruct);
}
break;
case Token.Type.cInterface:
{
ClassDecl nodeClass = ParseInterface(mods);
alTypes.Add(nodeClass);
}
break;
case Token.Type.cNamespace:
{
NamespaceDecl nNested = ParseNamespace();
alNestedNamespaces.Add(nNested);
}
break;
case Token.Type.cEnum:
{
EnumDecl e = ParseEnum(mods);
alTypes.Add(e);
}
break;
case Token.Type.cDelegate:
{
DelegateDecl d = ParseDelegate(mods);
alTypes.Add(d);
}
break;
default:
// Like to break out of the 'while' here, but a 'break' statement
// will just get out of the 'switch', not the while, so use a goto
goto Done;
} // end switch
t = m_lexer.PeekNextToken();
} // end while
Done:
NamespaceDecl [] arNamespaces = (NamespaceDecl []) alNestedNamespaces.ToArray(typeof(NamespaceDecl));
TypeDeclBase [] arTypes = (TypeDeclBase []) alTypes.ToArray(typeof(TypeDeclBase));
return new NamespaceDecl(idName, arUsingNodes, arNamespaces, null, arTypes);
}
//-----------------------------------------------------------------------------
// Parse and return an array of using declarations
// ** rules **
// UsingDirective -> 'using' id:name '=' id_list ';' // for aliasing
// UsingDirective -> 'using' id_list ';' // for namespaces
//-----------------------------------------------------------------------------
protected UsingDirective[] ParseUsingDirectives()
{
Token t;
t = m_lexer.PeekNextToken();
ArrayList a = new ArrayList();
while( t.TokenType == Token.Type.cUsing)
{
ConsumeNextToken();
Exp o = ParseDottedIdList();
UsingDirective node;
FileRange f = this.BeginRange();
t = m_lexer.PeekNextToken();
if (t.TokenType == Token.Type.cAssign)
{
ConsumeNextToken();
// o had better be a single identifier
SimpleObjExp s = o as SimpleObjExp;
Debug.Assert(s != null);
string stAlias = s.Name.Text;
Exp o2 = ParseDottedIdList();
node = new UsingDirective(stAlias, o2);
}
else
{
node = new UsingDirective(o);
}
ReadExpectedToken(Token.Type.cSemi);
Debug.Assert(node != null);
node.SetLocation(this.EndRange(f));
a.Add(node);
t = m_lexer.PeekNextToken();
}
UsingDirective[] arNodes = (UsingDirective[]) a.ToArray(typeof(UsingDirective));
return arNodes;
}
//-----------------------------------------------------------------------------
// Parse delegate declaration
// --> 'delegate' Type:rettype id:name '(' param_list ')' ';'
//-----------------------------------------------------------------------------
protected DelegateDecl ParseDelegate(Modifiers mods)
{
ReadExpectedToken(Token.Type.cDelegate);
TypeSig tRetType = ParseTypeSig();
Identifier idName = ReadExpectedIdentifier();
ParamVarDecl [] arParams = ParseParamList(); // includes '(' ... ')'
ReadExpectedToken(Token.Type.cSemi);
FileRange f = this.BeginRange();
DelegateDecl node = new DelegateDecl(idName, tRetType, arParams, mods);
node.SetLocation(this.EndRange(f));
return node;
}
//-----------------------------------------------------------------------------
// Parse enum declaration
// --> 'enum' id:name '{' enum_decl_list '}'
//-----------------------------------------------------------------------------
protected EnumDecl ParseEnum(Modifiers modsEnums)
{
ReadExpectedToken(Token.Type.cEnum);
Identifier idName = ReadExpectedIdentifier();
FileRange f2 = this.BeginRange();
ReadExpectedToken(Token.Type.cLCurly);
ArrayList a = new ArrayList();
// All enum fields are Static, Public, Literal
// and have fieldtype set to type of the enum
//Modifiers mods = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static);
Modifiers mods = new Modifiers();
mods.SetPublic();
mods.SetStatic();
TypeSig tSig = new SimpleTypeSig(new SimpleObjExp(idName));
Identifier idPrev = null;
Token t = m_lexer.PeekNextToken();
while(t.TokenType != Token.Type.cRCurly)
{
// Parse fields
Identifier id = ReadExpectedIdentifier();
Exp expInit = null;
t = m_lexer.PeekNextToken();
if (t.TokenType == Token.Type.cAssign)
{
ConsumeNextToken();
expInit = ParseExp();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -