// TODO: C# 7: put proper Tuple handling in place. private static Tuple <PrototypeMember, string> ParseVarStatement(ScriptProcessor processor, ScriptStatement statement) { var code = statement.Code; var signature = code.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); string identifier; var assignment = ""; var isReadOnly = false; var isStatic = false; // Read static: if (signature.Contains(VAR_SIGNATURE_STATIC)) { isStatic = true; signature.Remove(VAR_SIGNATURE_STATIC); } // Read readonly: if (signature.Contains(VAR_SIGNATURE_READONLY)) { isReadOnly = true; signature.Remove(VAR_SIGNATURE_READONLY); } if (signature[0] != "var" || signature.Count < 2) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_INVALID_VAR_DECLARATION); } identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME); } if (signature.Count > 2) { if (signature[2].StartsWith("=")) { assignment = code.Remove(0, code.IndexOf("=") + 1).Trim(); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_INVALID_VAR_DECLARATION); } } var member = new PrototypeMember(identifier, processor.Undefined, isStatic, isReadOnly, false, false); return(new Tuple <PrototypeMember, string>(member, assignment)); }
// TODO: C# 7: put proper Tuple handling in place. private static Tuple <PrototypeMember, string> ParseVarStatement(ScriptProcessor processor, ScriptStatement statement) { var code = statement.Code; var signature = code.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); var assignment = ""; var isReadOnly = false; var isStatic = false; // Read static: if (signature.Contains(VarSignatureStatic)) { isStatic = true; signature.Remove(VarSignatureStatic); } // Read readonly: if (signature.Contains(VarSignatureReadonly)) { isReadOnly = true; signature.Remove(VarSignatureReadonly); } if (signature[0] != "var" || signature.Count < 2) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassInvalidVarDeclaration); } var identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingVarName); } if (signature.Count > 2) { if (signature[2].StartsWith("=")) { assignment = code.Remove(0, code.IndexOf("=", StringComparison.Ordinal) + 1).Trim(); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassInvalidVarDeclaration); } } var member = new PrototypeMember(identifier, processor.Undefined, isStatic, isReadOnly, false, false); return(new Tuple <PrototypeMember, string>(member, assignment)); }
/// <summary> /// Initializes an instance with a script code signature and body. /// </summary> /// <param name="processor"></param> /// <param name="sourceCode">The source code, format: <code>function (params) { code }</code></param> public SFunction(ScriptProcessor processor, string sourceCode) { sourceCode = sourceCode.Trim(); var paramCode = sourceCode.Remove(0, "function".Length).Trim().Remove(0, 1); //Removes "function", then any spaces between "function" and "(", then removes "(". paramCode = paramCode.Remove(paramCode.IndexOf(")", StringComparison.Ordinal)); _parameters = paramCode.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray(); var allIdentifiersValid = true; var i = 0; while (i < _parameters.Length - 1 && allIdentifiersValid) { if (!ScriptProcessor.IsValidIdentifier(_parameters[i])) { allIdentifiersValid = false; } i++; } if (!allIdentifiersValid) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingFormalParameter); } else { if (!sourceCode.Contains("{") || !sourceCode.EndsWith("}")) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingFunctionBody); } else { Body = sourceCode.Remove(sourceCode.Length - 1, 1).Remove(0, sourceCode.IndexOf("{", StringComparison.Ordinal) + 1).Trim(); } } }
/// <summary> /// Initializes an instance with a script code signature and body. /// </summary> /// <param name="sourceCode">The source code, format: <code>function (params) { code }</code></param> public SFunction(ScriptProcessor processor, string sourceCode) { sourceCode = sourceCode.Trim(); var paramCode = sourceCode.Remove(0, "function".Length).Trim().Remove(0, 1); //Removes "function", then any spaces between "function" and "(", then removes "(". paramCode = paramCode.Remove(paramCode.IndexOf(")")); _parameters = paramCode.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray(); var allIdentifiersValid = true; var i = 0; while (i < _parameters.Length - 1 && allIdentifiersValid) { if (!ScriptProcessor.IsValidIdentifier(_parameters[i])) { allIdentifiersValid = false; } i++; } if (!allIdentifiersValid) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FORMAL_PARAMETER); } else { if (!sourceCode.Contains("{") || !sourceCode.EndsWith("}")) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FUNCTION_BODY); } else { Body = sourceCode.Remove(sourceCode.Length - 1, 1).Remove(0, sourceCode.IndexOf("{") + 1).Trim(); } } }
/// <summary> /// Parses an anonymous object. /// </summary> internal static SProtoObject Parse(ScriptProcessor processor, string source) { var prototype = new Prototype(LITERAL_OBJECT); source = source.Trim(); // Format: { member1 : content1, member2 : content2 } // Remove "{" and "}": source = source.Remove(source.Length - 1, 1).Remove(0, 1).Trim(); if (source.Length == 0) { return(prototype.CreateInstance(processor, null, false)); } var index = 0; var identifier = ""; var content = ""; SObject contentObj = null; while (index < source.Length) { var nextSeperatorIndex = source.IndexOf(",", index); if (nextSeperatorIndex == -1) { nextSeperatorIndex = source.Length; } else { //Let's find the correct ",": nextSeperatorIndex = index; var depth = 0; StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(source, nextSeperatorIndex, true); var foundSeperator = false; while (!foundSeperator && nextSeperatorIndex < source.Length) { var t = source[nextSeperatorIndex]; escaper.CheckStartAt(nextSeperatorIndex); if (!escaper.IsString) { if (t == '{' || t == '[' || t == '(') { depth++; } else if (t == '}' || t == ']' || t == ')') { depth--; } else if (t == ',' && depth == 0) { foundSeperator = true; nextSeperatorIndex--; // it adds one to the index at the end of the while loop, but we need the index where we stopped searching, so we subtract 1 here to accommodate for that. } } nextSeperatorIndex++; } } var member = source.Substring(index, nextSeperatorIndex - index); if (member.Contains(":")) { identifier = member.Remove(member.IndexOf(":")).Trim(); content = member.Remove(0, member.IndexOf(":") + 1); contentObj = processor.ExecuteStatement(new ScriptStatement(content)); } else { identifier = member.Trim(); contentObj = processor.Undefined; } if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME); } prototype.AddMember(processor, new PrototypeMember(identifier, contentObj)); index = nextSeperatorIndex + 1; } return(prototype.CreateInstance(processor, null, false)); }
private static PrototypeMember ParseFunctionStatement(ScriptProcessor processor, ScriptStatement headerStatement, ScriptStatement bodyStatement) { var header = headerStatement.Code; var signature = header.Remove(header.IndexOf("(")).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); string identifier; var isStatic = false; var isIndexerGet = false; var isIndexerSet = false; var functionType = FunctionUsageType.Default; var significantCount = 0; // Read static: if (signature.Contains(FUNCTION_SIGNATURE_STATIC)) { isStatic = true; signature.Remove(FUNCTION_SIGNATURE_STATIC); } // Read indexer: if (signature.Contains(FUNCTION_SIGNATURE_INDEXER)) { significantCount++; var indexerIndex = signature.IndexOf(FUNCTION_SIGNATURE_INDEXER); if (indexerIndex + 1 == signature.Count) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_FUNCTION_INDEXER_EXPECTED_TYPE); } var indexerType = signature[indexerIndex + 1]; if (indexerType == FUNCTION_SIGNATURE_GET) { isIndexerGet = true; signature.RemoveAt(indexerIndex + 1); } else if (indexerType == FUNCTION_SIGNATURE_SET) { isIndexerSet = true; signature.RemoveAt(indexerIndex + 1); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_FUNCTION_INDEXER_INVALID_TYPE, indexerType); } signature.Remove(FUNCTION_SIGNATURE_INDEXER); } // Read property: if (signature.Contains(FUNCTION_SIGNATURE_PROPERTY)) { significantCount++; var propertyIndex = signature.IndexOf(FUNCTION_SIGNATURE_PROPERTY); if (propertyIndex + 1 == signature.Count) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_FUNCTION_PROPERTY_EXPECTED_TYPE); } var propertyType = signature[propertyIndex + 1]; if (propertyType == FUNCTION_SIGNATURE_GET) { functionType = FunctionUsageType.PropertyGetter; signature.RemoveAt(propertyIndex + 1); } else if (propertyType == FUNCTION_SIGNATURE_SET) { functionType = FunctionUsageType.PropertySetter; signature.RemoveAt(propertyIndex + 1); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_FUNCTION_PROPERTY_INVALID_TYPE, propertyType); } signature.Remove(FUNCTION_SIGNATURE_PROPERTY); } // Only one (or none) significant signature types can be added to a signature. if (significantCount > 1) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_INCOMPATIBLE_SIGNATURE); } if (signature.Count != 2) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_CLASS_INVALID_FUNCTION_SIGNATURE); } identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME); } // After the valid identifier check is done, we add the getter/setter prefix. It wouldn't pass the test. if (functionType == FunctionUsageType.PropertyGetter) { identifier = PROPERTY_GET_PREFIX + identifier; } if (functionType == FunctionUsageType.PropertySetter) { identifier = PROPERTY_SET_PREFIX + identifier; } var function = new SFunction(processor, signature[0] + " " + header.Remove(0, header.IndexOf("(")) + bodyStatement.Code) { FunctionUsage = functionType }; return(new PrototypeMember(identifier, function, isStatic, false, isIndexerGet, isIndexerSet)); }
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)); } }
private static PrototypeMember ParseFunctionStatement(ScriptProcessor processor, ScriptStatement headerStatement, ScriptStatement bodyStatement) { var header = headerStatement.Code; var signature = header.Remove(header.IndexOf("(", StringComparison.Ordinal)).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); var isStatic = false; var isIndexerGet = false; var isIndexerSet = false; var functionType = FunctionUsageType.Default; var significantCount = 0; // Read static: if (signature.Contains(FunctionSignatureStatic)) { isStatic = true; signature.Remove(FunctionSignatureStatic); } // Read indexer: if (signature.Contains(FunctionSignatureIndexer)) { significantCount++; var indexerIndex = signature.IndexOf(FunctionSignatureIndexer); if (indexerIndex + 1 == signature.Count) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassFunctionIndexerExpectedType); } var indexerType = signature[indexerIndex + 1]; if (indexerType == FunctionSignatureGet) { isIndexerGet = true; signature.RemoveAt(indexerIndex + 1); } else if (indexerType == FunctionSignatureSet) { isIndexerSet = true; signature.RemoveAt(indexerIndex + 1); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassFunctionIndexerInvalidType, indexerType); } signature.Remove(FunctionSignatureIndexer); } // Read property: if (signature.Contains(FunctionSignatureProperty)) { significantCount++; var propertyIndex = signature.IndexOf(FunctionSignatureProperty); if (propertyIndex + 1 == signature.Count) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassFunctionPropertyExpectedType); } var propertyType = signature[propertyIndex + 1]; if (propertyType == FunctionSignatureGet) { functionType = FunctionUsageType.PropertyGetter; signature.RemoveAt(propertyIndex + 1); } else if (propertyType == FunctionSignatureSet) { functionType = FunctionUsageType.PropertySetter; signature.RemoveAt(propertyIndex + 1); } else { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassFunctionPropertyInvalidType, propertyType); } signature.Remove(FunctionSignatureProperty); } // Only one (or none) significant signature types can be added to a signature. if (significantCount > 1) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassIncompatibleSignature); } if (signature.Count != 2) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxClassInvalidFunctionSignature); } var identifier = signature[1]; if (!ScriptProcessor.IsValidIdentifier(identifier)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingVarName); } // After the valid identifier check is done, we add the getter/setter prefix. It wouldn't pass the test. if (functionType == FunctionUsageType.PropertyGetter) { identifier = PropertyGetPrefix + identifier; } if (functionType == FunctionUsageType.PropertySetter) { identifier = PropertySetPrefix + identifier; } var function = new SFunction(processor, signature[0] + " " + header.Remove(0, header.IndexOf("(", StringComparison.Ordinal)) + bodyStatement.Code) { FunctionUsage = functionType }; return(new PrototypeMember(identifier, function, isStatic, false, isIndexerGet, isIndexerSet)); }
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)); } }
public static SObject AddMember(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { // Parameter #1: (String)Name of the new member // [Parameter #2: Default value of the new member ] / Undefined // [Parameter #3: Signature config of the new member] / instance member, no special settings if (parameters.Length == 0) { return(processor.Undefined); } Prototype prototype; if (IsPrototype(instance.GetType())) { prototype = (Prototype)instance; } else { // The instance will be a prototype instance, so get its prototype from there: var protoObj = (SProtoObject)instance; prototype = protoObj.Prototype; } var memberAsString = parameters[0] as SString; var memberName = memberAsString != null ? memberAsString.Value : parameters[0].ToString(processor).Value; var defaultValue = processor.Undefined; if (parameters.Length > 1) { defaultValue = parameters[1]; } var isReadOnly = false; var isStatic = false; var isIndexerGet = false; var isIndexerSet = false; if (parameters.Length > 2) { var signature = parameters[2]; var array = signature as SArray; if (array != null) { foreach (var arrayMember in array.ArrayMembers) { var arrayMemberAsString = arrayMember as SString; if (arrayMemberAsString == null) { continue; } var signatureMember = arrayMemberAsString.Value; switch (signatureMember) { case "readOnly": isReadOnly = true; break; case "static": isStatic = true; break; case "indexerGet": isIndexerGet = true; break; case "indexerSet": isIndexerSet = true; break; } } } } if ((isIndexerSet || isIndexerGet) && !(defaultValue is SFunction)) { processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MessageTypeGetterSetterNotAFunction); } if (!ScriptProcessor.IsValidIdentifier(memberName)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MessageSyntaxMissingVarName); } prototype.AddMember(processor, new PrototypeMember(memberName, defaultValue, isStatic, isReadOnly, isIndexerGet, isIndexerSet)); return(processor.Undefined); }
public static SObject AddMember(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) { // Parameter #1: (String)Name of the new member // [Parameter #2: Default value of the new member ] / Undefined // [Parameter #3: Signature config of the new member] / instance member, no special settings if (parameters.Length == 0) { return(processor.Undefined); } Prototype prototype; if (IsPrototype(instance.GetType())) { prototype = (Prototype)instance; } else { // The instance will be a prototype instance, so get its prototype from there: var protoObj = (SProtoObject)instance; prototype = protoObj.Prototype; } string memberName; if (parameters[0] is SString) { memberName = ((SString)parameters[0]).Value; } else { memberName = parameters[0].ToString(processor).Value; } var defaultValue = processor.Undefined; if (parameters.Length > 1) { defaultValue = parameters[1]; } var isReadOnly = false; var isStatic = false; var isIndexerGet = false; var isIndexerSet = false; if (parameters.Length > 2) { var signature = parameters[2]; if (signature is SArray) { foreach (var arrayMember in ((SArray)signature).ArrayMembers) { if (arrayMember is SString) { var signatureMember = ((SString)arrayMember).Value; switch (signatureMember) { case "readOnly": isReadOnly = true; break; case "static": isStatic = true; break; case "indexerGet": isIndexerGet = true; break; case "indexerSet": isIndexerSet = true; break; } } } } } if ((isIndexerSet || isIndexerGet) && !(defaultValue is SFunction)) { processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_GETTER_SETTER_NOT_A_FUNCTION); } if (!ScriptProcessor.IsValidIdentifier(memberName)) { processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_VAR_NAME); } prototype.AddMember(processor, new PrototypeMember(memberName, defaultValue, isStatic, isReadOnly, isIndexerGet, isIndexerSet)); return(processor.Undefined); }