protected override void ParseClassMember( TokenStream tokens, FileScope fileScope, ClassDefinition classDef, IList <FunctionDefinition> methodsOut, IList <FieldDefinition> fieldsOut, IList <PropertyDefinition> propertiesOutIgnored) { AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); ModifierCollection modifiers = ModifierCollection.Parse(tokens); if (tokens.IsNext(this.parser.Keywords.FUNCTION)) { methodsOut.Add(this.ParseFunction(tokens, classDef, fileScope, modifiers, annotations)); } else if (tokens.IsNext(this.parser.Keywords.CONSTRUCTOR)) { if (modifiers.HasStatic) { if (classDef.StaticConstructor != null) { throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed."); } classDef.StaticConstructor = this.ParseConstructor(tokens, classDef, modifiers, annotations); } else { if (classDef.Constructor != null) { throw this.parser.GenerateParseError( ErrorMessages.CLASS_CANNOT_HAVE_MULTIPLE_CONSTRUCTORS, tokens.Pop()); } classDef.Constructor = this.ParseConstructor(tokens, classDef, modifiers, annotations); } } else if (tokens.IsNext(this.parser.Keywords.FIELD)) { fieldsOut.Add(this.ParseField(tokens, classDef, modifiers, annotations)); } else if (tokens.IsNext(this.parser.Keywords.CLASS)) { throw new ParserException(tokens.Pop(), "Nested classes are not currently supported."); } else { tokens.PopExpected("}"); } TODO.CheckForUnusedAnnotations(); }
internal virtual TopLevelEntity Parse( TokenStream tokens, TopLevelEntity owner, FileScope fileScope) { AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); ModifierCollection modifiers = ModifierCollection.Parse(tokens); string value = tokens.PeekValue(); if (value == this.parser.Keywords.IMPORT) { throw this.parser.GenerateParseError( ErrorMessages.ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE, tokens.Pop()); } // The returns are inline, so you'll have to refactor or put the check inside each parse call. // Or maybe a try/finally. TODO.CheckForUnusedAnnotations(); if (value == this.parser.Keywords.NAMESPACE) { return(this.ParseNamespace(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CONST) { return(this.ParseConst(tokens, owner, fileScope, modifiers, annotations)); } if (value == this.parser.Keywords.FUNCTION) { return(this.ParseFunction(tokens, owner, fileScope, modifiers, annotations)); } if (value == this.parser.Keywords.CLASS) { return(this.ParseClassDefinition(tokens, owner, fileScope, modifiers, annotations)); } if (value == this.parser.Keywords.ENUM) { return(this.ParseEnumDefinition(tokens, owner, fileScope, modifiers, annotations)); } if (value == this.parser.Keywords.CONSTRUCTOR && owner is ClassDefinition) { return(this.ParseConstructor(tokens, (ClassDefinition)owner, modifiers, annotations)); } FunctionDefinition nullableFunctionDef = this.MaybeParseFunctionDefinition(tokens, owner, fileScope, annotations, modifiers); if (nullableFunctionDef != null) { return(nullableFunctionDef); } Token token = tokens.Peek(); throw ParserException.ThrowException( this.parser.CurrentLocale, ErrorMessages.UNEXPECTED_TOKEN_NO_SPECIFIC_EXPECTATIONS, token, token.Value); }
private ClassDefinition ParseClassDefinition(TokenStream tokens, TopLevelConstruct owner, Token staticToken, Token finalToken, FileScope fileScope, AnnotationCollection classAnnotations) { Token classToken = tokens.PopExpected(this.parser.Keywords.CLASS); Token classNameToken = tokens.Pop(); this.parser.VerifyIdentifier(classNameToken); List <Token> baseClassTokens = new List <Token>(); List <string> baseClassStrings = new List <string>(); if (tokens.PopIfPresent(":")) { if (baseClassTokens.Count > 0) { tokens.PopExpected(","); } Token baseClassToken = tokens.Pop(); string baseClassName = baseClassToken.Value; this.parser.VerifyIdentifier(baseClassToken); while (tokens.PopIfPresent(".")) { Token baseClassTokenNext = tokens.Pop(); this.parser.VerifyIdentifier(baseClassTokenNext); baseClassName += "." + baseClassTokenNext.Value; } baseClassTokens.Add(baseClassToken); baseClassStrings.Add(baseClassName); } ClassDefinition cd = new ClassDefinition( classToken, classNameToken, baseClassTokens, baseClassStrings, owner, parser.CurrentLibrary, staticToken, finalToken, fileScope, classAnnotations); tokens.PopExpected("{"); List <FunctionDefinition> methods = new List <FunctionDefinition>(); List <FieldDeclaration> fields = new List <FieldDeclaration>(); ConstructorDefinition constructorDef = null; ConstructorDefinition staticConstructorDef = null; while (!tokens.PopIfPresent("}")) { AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); if (tokens.IsNext(this.parser.Keywords.FUNCTION) || tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.FUNCTION)) { methods.Add(this.parser.ExecutableParser.ParseFunction(tokens, cd, fileScope, annotations)); } else if (tokens.IsNext(this.parser.Keywords.CONSTRUCTOR)) { if (constructorDef != null) { throw this.parser.GenerateParseError( ErrorMessages.CLASS_CANNOT_HAVE_MULTIPLE_CONSTRUCTORS, tokens.Pop()); } constructorDef = this.parser.ExecutableParser.ParseConstructor(tokens, cd, annotations); } else if (tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.CONSTRUCTOR)) { tokens.Pop(); // static token if (staticConstructorDef != null) { throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed."); } staticConstructorDef = this.parser.ExecutableParser.ParseConstructor(tokens, cd, annotations); } else if (tokens.IsNext(this.parser.Keywords.FIELD) || tokens.AreNext(this.parser.Keywords.STATIC, this.parser.Keywords.FIELD)) { fields.Add(this.parser.ExecutableParser.ParseField(tokens, cd, annotations)); } else { tokens.PopExpected("}"); } TODO.CheckForUnusedAnnotations(); } cd.Methods = methods.ToArray(); cd.Constructor = constructorDef; cd.StaticConstructor = staticConstructorDef; cd.Fields = fields.ToArray(); return(cd); }
public TopLevelConstruct ParseTopLevel( TokenStream tokens, TopLevelConstruct owner, FileScope fileScope) { AnnotationCollection annotations = annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); string value = tokens.PeekValue(); // The returns are inline, so you'll have to refactor or put the check inside each parse call. // Or maybe a try/finally. TODO.CheckForUnusedAnnotations(); Token staticToken = null; Token finalToken = null; while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL) { if (value == this.parser.Keywords.STATIC && staticToken == null) { staticToken = tokens.Pop(); value = tokens.PeekValue(); } if (value == this.parser.Keywords.FINAL && finalToken == null) { finalToken = tokens.Pop(); value = tokens.PeekValue(); } } if (staticToken != null || finalToken != null) { if (value != this.parser.Keywords.CLASS) { if (staticToken != null) { throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.ONLY_CLASSES_METHODS_FIELDS_MAY_BE_STATIC, staticToken); } else { throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.ONLY_CLASSES_MAY_BE_FINAL, finalToken); } } if (staticToken != null && finalToken != null) { throw ParserException.ThrowException(this.parser.CurrentLocale, ErrorMessages.CLASSES_CANNOT_BE_STATIC_AND_FINAL_SIMULTANEOUSLY, staticToken); } } if (value == parser.Keywords.IMPORT) { Token importToken = tokens.PopExpected(parser.Keywords.IMPORT); List <string> importPathBuilder = new List <string>(); while (!tokens.PopIfPresent(";")) { if (importPathBuilder.Count > 0) { tokens.PopExpected("."); } Token pathToken = tokens.Pop(); parser.VerifyIdentifier(pathToken); importPathBuilder.Add(pathToken.Value); } string importPath = string.Join(".", importPathBuilder); return(new ImportStatement(importToken, importPath, parser.CurrentLibrary, fileScope)); } if (value == this.parser.Keywords.NAMESPACE) { return(this.ParseNamespace(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CONST) { return(this.ParseConst(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.FUNCTION) { return(this.ParseFunction(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CLASS) { return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken, fileScope, annotations)); } if (value == this.parser.Keywords.ENUM) { return(this.ParseEnumDefinition(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CONSTRUCTOR) { return(this.ParseConstructor(tokens, owner, annotations)); } Token token = tokens.Peek(); throw ParserException.ThrowException( this.parser.CurrentLocale, ErrorMessages.UNEXPECTED_TOKEN_NO_SPECIFIC_EXPECTATIONS, token, token.Value); }
public TopLevelConstruct ParseTopLevel( TokenStream tokens, TopLevelConstruct owner, FileScope fileScope) { AnnotationCollection annotations = annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); string value = tokens.PeekValue(); // The returns are inline, so you'll have to refactor or put the check inside each parse call. // Or maybe a try/finally. TODO.CheckForUnusedAnnotations(); Token staticToken = null; Token finalToken = null; while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL) { if (value == this.parser.Keywords.STATIC && staticToken == null) { staticToken = tokens.Pop(); value = tokens.PeekValue(); } if (value == this.parser.Keywords.FINAL && finalToken == null) { finalToken = tokens.Pop(); value = tokens.PeekValue(); } } if (staticToken != null || finalToken != null) { if (value != this.parser.Keywords.CLASS) { if (staticToken != null) { throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static"); } else { throw new ParserException(finalToken, "Only classes may be marked as final."); } } if (staticToken != null && finalToken != null) { throw new ParserException(staticToken, "Classes cannot be both static and final."); } } if (value == parser.Keywords.IMPORT) { Token importToken = tokens.PopExpected(parser.Keywords.IMPORT); List <string> importPathBuilder = new List <string>(); while (!tokens.PopIfPresent(";")) { if (importPathBuilder.Count > 0) { tokens.PopExpected("."); } Token pathToken = tokens.Pop(); parser.VerifyIdentifier(pathToken); importPathBuilder.Add(pathToken.Value); } string importPath = string.Join(".", importPathBuilder); return(new ImportStatement(importToken, importPath, parser.CurrentLibrary, fileScope)); } if (value == this.parser.Keywords.NAMESPACE) { return(this.ParseNamespace(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CONST) { return(this.ParseConst(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.FUNCTION) { return(this.ParseFunction(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CLASS) { return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken, fileScope, annotations)); } if (value == this.parser.Keywords.ENUM) { return(this.ParseEnumDefinition(tokens, owner, fileScope, annotations)); } if (value == this.parser.Keywords.CONSTRUCTOR) { return(this.ParseConstructor(tokens, owner, annotations)); } throw new ParserException(tokens.Peek(), "Unrecognized token."); }
protected override void ParseClassMember( TokenStream tokens, FileScope fileScope, ClassDefinition classDef, IList <FunctionDefinition> methodsOut, IList <FieldDefinition> fieldsOut, IList <PropertyDefinition> propertiesOut) { AnnotationCollection annotations = this.parser.AnnotationParser.ParseAnnotations(tokens); ModifierCollection modifiers = ModifierCollection.Parse(tokens); if (tokens.IsNext(this.parser.Keywords.CONSTRUCTOR)) { if (modifiers.HasStatic) { if (classDef.StaticConstructor != null) { throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed."); } classDef.StaticConstructor = this.ParseConstructor(tokens, classDef, modifiers, annotations); } else { if (classDef.Constructor != null) { throw this.parser.GenerateParseError( ErrorMessages.CLASS_CANNOT_HAVE_MULTIPLE_CONSTRUCTORS, tokens.Pop()); } classDef.Constructor = this.ParseConstructor(tokens, classDef, modifiers, annotations); } } else if (tokens.IsNext(this.parser.Keywords.CLASS)) { throw new ParserException(tokens.Pop(), "Nested classes are not currently supported."); } else { // Parsing the type and then throwing it away is a little wasteful, but feels less weird than parsing // the type here and passing it into ParseFunction()/ParseField(). ParseX() should ParseX from the start. TokenStream.StreamState fieldOrFunctionStart = tokens.RecordState(); AType fieldOrFunctionType = this.parser.TypeParser.TryParse(tokens); Token tokenAfterName = fieldOrFunctionType != null?tokens.PeekAhead(1) : null; tokens.RestoreState(fieldOrFunctionStart); if (tokenAfterName == null) { tokens.PopExpected("}"); // intentionally induce error } switch (tokenAfterName.Value) { case "=": case ";": fieldsOut.Add(this.ParseField(tokens, classDef, modifiers, annotations)); break; case "(": methodsOut.Add(this.ParseFunction(tokens, classDef, fileScope, modifiers, annotations)); break; case "{": if (!this.parser.IsCSharpCompat) { // TODO(acrylic-convert): properties should be implemented in Acrylic, just not yet. tokens.PopExpected("}"); // intentionally induce error } propertiesOut.Add(this.ParseProperty(tokens, classDef, fileScope, modifiers, annotations)); break; default: tokens.PopExpected("}"); // intentionally induce error break; } } TODO.CheckForUnusedAnnotations(); }