internal new static SObject Parse(ScriptProcessor processor, string code) { code = code.Trim(); if (Regex.IsMatch(code, REGEX_CLASS_SIGNATURE, RegexOptions.Singleline)) { var signature = code.Remove(code.IndexOf("{")).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); var extends = ""; var identifier = ""; var isAbstract = false; // Read extends: if (signature.Contains(CLASS_SIGNATURE_EXTENDS)) { var extendsIndex = signature.IndexOf(CLASS_SIGNATURE_EXTENDS); if (extendsIndex + 1 == signature.Count) // when extends is the last element in the signature, throw error: { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_EXTENDS_MISSING); } extends = signature[extendsIndex + 1]; // The extended class name is after the "extends" keyword. signature.RemoveAt(extendsIndex); // Remove at the extends index twice, to remove the "extends" keyword and the identifier of the extended class. signature.RemoveAt(extendsIndex); } // Read abstract: if (signature.Contains(CLASS_SIGNATURE_ABSTRACT)) { isAbstract = true; signature.Remove(CLASS_SIGNATURE_ABSTRACT); } if (signature.Count != 2) // The signature must only have "class" and the identifier left. { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_CLASS_SIGNATURE); } // Read class name: identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_IDENTIFIER_MISSING); } // Create instance: var prototype = new Prototype(identifier) { IsAbstract = isAbstract }; // Handle extends: if (extends.Length > 0) { if (isAbstract) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_TYPE_ABSTRACT_NO_EXTENDS); } var extendedPrototype = processor.Context.GetPrototype(extends); if (extendedPrototype == null) { processor.ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_NO_PROTOTYPE, extends); } prototype.Extends = extendedPrototype; } else { // Set default prototype: prototype.Extends = processor.Context.GetPrototype("Object"); } var body = code.Remove(0, code.IndexOf("{") + 1); body = body.Remove(body.Length - 1, 1).Trim(); var additionalCtorCode = ""; var staticCtorCode = ""; var statements = StatementProcessor.GetStatements(processor, body); for (var i = 0; i < statements.Length; i++) { var statement = statements[i]; if (statement.StatementType == StatementType.Var) { var parsed = ParseVarStatement(processor, statement); if (parsed.Item1.Identifier == CLASS_METHOD_CTOR) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME); } prototype.AddMember(processor, parsed.Item1); if (parsed.Item2.Length > 0) { if (parsed.Item1.IsStatic) { staticCtorCode += string.Format(FORMAT_VAR_ASSIGNMENT, parsed.Item1.Identifier, parsed.Item2); } else { additionalCtorCode += string.Format(FORMAT_VAR_ASSIGNMENT, parsed.Item1.Identifier, parsed.Item2); } } } else if (statement.StatementType == StatementType.Function) { i++; if (statements.Length > i) { var bodyStatement = statements[i]; var parsed = ParseFunctionStatement(processor, statement, bodyStatement); if (parsed.Identifier == CLASS_METHOD_CTOR) { if (prototype.Constructor != null) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_DUPLICATE_DEFINITION, parsed.Identifier, identifier); } prototype.Constructor = parsed; } else { prototype.AddMember(processor, parsed); } } else { return(processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script")); } } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_INVALID_STATEMENT); } } // Add additional constructor code & static constructor code to prototype: if (staticCtorCode.Length > 0) { prototype._staticConstructor = new SFunction(staticCtorCode, new string[] { }); prototype._staticConstructorProcessor = processor; } if (additionalCtorCode.Length > 0) { if (prototype.Constructor == null) { // Create new ctor if no one has been defined: prototype.Constructor = new PrototypeMember(CLASS_METHOD_CTOR, new SFunction("", new string[] { }), false, true, false, false); } prototype.Constructor.ToFunction().Body = additionalCtorCode + prototype.Constructor.ToFunction().Body; } return(prototype); } else { return(processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_CLASS_SIGNATURE)); } }
internal new static SObject Parse(ScriptProcessor processor, string code) { code = code.Trim(); if (Regex.IsMatch(code, RegexClassSignature, RegexOptions.Singleline)) { var signature = code.Remove(code.IndexOf("{", StringComparison.Ordinal)).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); var extends = ""; var isAbstract = false; // Read extends: if (signature.Contains(ClassSignatureExtends)) { var extendsIndex = signature.IndexOf(ClassSignatureExtends); if (extendsIndex + 1 == signature.Count) // when extends is the last element in the signature, throw error: { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassExtendsMissing); } extends = signature[extendsIndex + 1]; // The extended class name is after the "extends" keyword. signature.RemoveAt(extendsIndex); // Remove at the extends index twice, to remove the "extends" keyword and the identifier of the extended class. signature.RemoveAt(extendsIndex); } // Read abstract: if (signature.Contains(ClassSignatureAbstract)) { isAbstract = true; signature.Remove(ClassSignatureAbstract); } if (signature.Count != 2) // The signature must only have "class" and the identifier left. { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxInvalidClassSignature); } // Read class name: var identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassIdentifierMissing); } // Create instance: var prototype = new Prototype(identifier) { IsAbstract = isAbstract }; // Handle extends: if (extends.Length > 0) { if (isAbstract) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageTypeAbstractNoExtends); } var extendedPrototype = processor.Context.GetPrototype(extends); if (extendedPrototype == null) { processor.ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MessageReferenceNoPrototype, extends); } prototype.Extends = extendedPrototype; } else { // Set default prototype: prototype.Extends = processor.Context.GetPrototype("Object"); } var body = code.Remove(0, code.IndexOf("{", StringComparison.Ordinal) + 1); body = body.Remove(body.Length - 1, 1).Trim(); var additionalCtorCode = ""; var staticCtorCode = ""; var statements = StatementProcessor.GetStatements(processor, body); for (var i = 0; i < statements.Length; i++) { var statement = statements[i]; if (statement.StatementType == StatementType.Var) { var parsed = ParseVarStatement(processor, statement); if (parsed.Item1.Identifier == ClassMethodCtor) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingVarName); } prototype.AddMember(processor, parsed.Item1); if (parsed.Item2.Length > 0) { if (parsed.Item1.IsStatic) { staticCtorCode += string.Format(FormatVarAssignment, parsed.Item1.Identifier, parsed.Item2); } else { additionalCtorCode += string.Format(FormatVarAssignment, parsed.Item1.Identifier, parsed.Item2); } } } else if (statement.StatementType == StatementType.Function) { i++; if (statements.Length > i) { var bodyStatement = statements[i]; var parsed = ParseFunctionStatement(processor, statement, bodyStatement); if (parsed.Identifier == ClassMethodCtor) { if (prototype.Constructor != null) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassDuplicateDefinition, parsed.Identifier, identifier); } prototype.Constructor = parsed; } else { prototype.AddMember(processor, parsed); } } else { return(processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxExpectedExpression, "end of script")); } } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassInvalidStatement); } } // Add additional constructor code & static constructor code to prototype: if (staticCtorCode.Length > 0) { prototype._staticConstructor = new SFunction(staticCtorCode, new string[] { }); prototype._staticConstructorProcessor = processor; } if (additionalCtorCode.Length > 0) { if (prototype.Constructor == null) { // Create new ctor if no one has been defined: prototype.Constructor = new PrototypeMember(ClassMethodCtor, new SFunction("", new string[] { }), false, true, false, false); } prototype.Constructor.ToFunction().Body = additionalCtorCode + prototype.Constructor.ToFunction().Body; } return(prototype); } else { return(processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxInvalidClassSignature)); } }