ProjectItemCodeDocument ParseIncludeDirective(CodeSegment includeDirective, ProjectItemCodeDocument document) { ThrowUtil.ThrowIfNull(includeDirective); ThrowUtil.ThrowIfNull(document); SmartCodeProjectAHK project = document.Project as SmartCodeProjectAHK; if(project == null) throw new NotSupportedException("Expected an instance of SmartCodeProjectAHK!"); if(_project.StartUpCodeDocument == null) return null; var libRegEx = new Regex(@"<(.*?)>"); // parse include directive var next = includeDirective.NextOmit(TokenHelper.WhiteSpaces); if(next != null) { int len = next.TokenString.Length; if(len > 0) { if(libRegEx.IsMatch(next.TokenString)) { string docName = libRegEx.Match(next.TokenString).Groups[1].Value; // seach local library files var doc = project.LocalLib.FindAllItems<ProjectItemCodeDocument>().ToList() .Find(x => Path.GetFileNameWithoutExtension(x.FilePath).Equals(docName, StringComparison.InvariantCultureIgnoreCase)); if(doc == null && project.StdLib != null) { // seach in standard library files doc = project.StdLib.FindAllItems<ProjectItemCodeDocument>().ToList() .Find(x => x.FilePath != null && Path.GetFileNameWithoutExtension(x.FilePath).Equals(docName, StringComparison.InvariantCultureIgnoreCase)); } if(doc != null) { var directive = new IncludeDirective() { ResolvedFilePath = doc.FilePath, ResolvedCodeDocument = doc }; next.CodeDOMObject = directive; } else { next.ErrorContext = new CodeError() { Description = string.Format("File not found!") }; } return doc; } else { // parse direct/relative path var directive = ParseIncludePath(document, next); var includeFilePath = directive.ResolvedFilePath; var doc = project.CodeDocuments.ToList() .Find(x => x.FilePath.Equals(includeFilePath, StringComparison.InvariantCultureIgnoreCase)); directive.ResolvedCodeDocument = doc; return doc; } } } return null; }
CodeExpression ParseExpression(CodeSegment tokenSegment, out CodeSegment nextToParse, CodeTypeDeclarationEx enclosingType) { CodeExpression expression = null; nextToParse = tokenSegment.Next; if(tokenSegment.Token == Token.Identifier && tokenSegment.Next != null && tokenSegment.Next.Token == Token.LiteralBracketOpen) { bool ismethodDeclaration = false; var closingliteral = tokenSegment.Next.FindClosingBracked(true); if(closingliteral != null) { //ensure that it is not a defect method declaration var bra = closingliteral.NextOmit(whitespacetokenNewLines); if(bra != null && bra.Token == Token.BlockOpen) { // it is a method indeed ismethodDeclaration = true; } } else { RegisterError(_document, tokenSegment.Next, "Missing: )"); } #region Parse for Method Invokes if(!ismethodDeclaration) { CodeTypeDeclarationEx methodContext = null; if(tokenSegment.Previous != null && tokenSegment.Previous.Previous != null && tokenSegment.Previous.Token == Token.MemberInvoke) { var invoker = tokenSegment.Previous.Previous; #region adjust Method Context if(_document.CodeLanguage.SELFREF_CAN_BE_OMITTED) methodContext = enclosingType; if(invoker.CodeDOMObject is CodeBaseReferenceExpression) { foreach(CodeTypeReferenceEx bt in enclosingType.BaseTypes) { var typedeclaration = bt.ResolveTypeDeclarationCache(); if(typedeclaration != null && typedeclaration.IsClass) { methodContext = typedeclaration; break; } } } else if(invoker.CodeDOMObject is CodeThisReferenceExpression) { methodContext = enclosingType; } else if(invoker.Token == Token.Identifier) { invoker.CodeDOMObject = CodeTypeDeclarationDynamic.Default; methodContext = CodeTypeDeclarationDynamic.Default; } #endregion } var invokeExpression = new CodeMethodInvokeExpression(); var methodRef = new CodeMethodReferenceExpressionExAHK(_document, null, tokenSegment.TokenString, methodContext); invokeExpression.Method = methodRef; tokenSegment.CodeDOMObject = methodRef; expression = invokeExpression; } nextToParse = tokenSegment.Next.Next; #endregion } else if(tokenSegment.Token == Token.KeyWord) { #region Parse Keywords if(tokenSegment.TokenString.Equals("new", _document.CodeLanguage.NameComparisation)) { #region NEW parse for new Object Expressions var newObjectInvoke = tokenSegment.NextOmit(whitespacetokenNewLines); if(newObjectInvoke != null && newObjectInvoke.Token == Token.Identifier) { var objectinstangicing = new CodeObjectCreateExpression(); objectinstangicing.CreateType = new CodeTypeReferenceEx(_document, newObjectInvoke.TokenString, enclosingType); tokenSegment.CodeDOMObject = objectinstangicing; newObjectInvoke.CodeDOMObject = objectinstangicing.CreateType; expression = objectinstangicing; nextToParse = newObjectInvoke.Next; } #endregion } else if(tokenSegment.TokenString.Equals("this", _document.CodeLanguage.NameComparisation)) { var thisrefExpression = new CodeThisReferenceExpression(); tokenSegment.CodeDOMObject = thisrefExpression; expression = thisrefExpression; } else if(tokenSegment.TokenString.Equals("base", _document.CodeLanguage.NameComparisation)) { var baserefExpression = new CodeBaseReferenceExpression(); tokenSegment.CodeDOMObject = baserefExpression; expression = baserefExpression; } #endregion } else if(tokenSegment.Token == Token.Identifier && tokenSegment.Previous != null && tokenSegment.Previous.Token == Token.MemberInvoke) { #region Parse MemberInvoke (Dot) Class.Member var context = tokenSegment.Previous.Previous; if(context == null) { //unexpected! var err = "Unexpected Member Invoke!"; RegisterError(_document, tokenSegment, err); RegisterError(_document, tokenSegment.Previous, err); nextToParse = tokenSegment.Next; } else if(context.Token == Token.KeyWord && context.TokenString.Equals("this", _document.CodeLanguage.NameComparisation)) { var propRef = new CodePropertyReferenceExpressionEx(_document, null, tokenSegment.TokenString, enclosingType); tokenSegment.CodeDOMObject = propRef; } else if(context.Token == Token.KeyWord && context.TokenString.Equals("base", _document.CodeLanguage.NameComparisation)) { CodeTypeDeclarationEx typedeclaration = null; foreach(CodeTypeReferenceEx bt in enclosingType.BaseTypes) { typedeclaration = bt.ResolveTypeDeclarationCache(); if(typedeclaration != null && typedeclaration.IsClass) { break; } } var propRef = new CodePropertyReferenceExpressionEx(_document, null, tokenSegment.TokenString, typedeclaration); tokenSegment.CodeDOMObject = propRef; } else if(context.Token == Token.Identifier) { // we currently not supprt real expression parsing, so leave here... context.CodeDOMObject = CodeTypeDeclarationDynamic.Default; var propRef = new CodePropertyReferenceExpressionEx(_document, null, tokenSegment.TokenString, CodeTypeDeclarationDynamic.Default); tokenSegment.CodeDOMObject = propRef; } #region Parse for one hirarchy this/base Property/Field Invokes #endregion #endregion } else if(tokenSegment.Token == Token.TraditionalCommandInvoke) { #region Parse Traditional Command Invoke var members = from m in _languageRoot.Members.Cast<CodeTypeMember>() let methd = m as CodeMemberMethodExAHK where methd != null && methd.IsTraditionalCommand && methd.Name.Equals(tokenSegment.TokenString, StringComparison.InvariantCultureIgnoreCase) select methd; if(members.Any()) { var invokeExpression = new CodeMethodInvokeExpression(); var methodRef = new CodeMethodReferenceExpressionExAHK(_document, members.First()); tokenSegment.CodeDOMObject = methodRef; expression = invokeExpression; } else { RegisterError(_document, tokenSegment, string.Format("Unknown traditional Command '{0}'", tokenSegment.TokenString)); } #endregion } else if(tokenSegment.Token == Token.LiteralString) { if(tokenSegment.TokenString[tokenSegment.TokenString.Length - 1] != '"') { RegisterError(_document, tokenSegment, "Missing string end Quote"); } } if(!(nextToParse != null && nextToParse.LineNumber == tokenSegment.LineNumber)) { nextToParse = null; } return expression; }