void AccessorDepthApply(string tag, AbstractObjectKind kind, bool applyAccessors = false) { string Name = tag.Replace(kind.ToString() + " ", string.Empty); //Create the collection entry for the AbstractSyntaxKind, adding it to the global node and making it the current deepest var tmp = new AbstractSyntaxCollection() { Name = Name.Trim(), ObjectKind = kind, Parent = DeepestNode }; if (applyAccessors) { tmp.SyntaxObjects = Accessors.ToList(); } DeepestNode.Children.Add(tmp); DeepestNode = tmp; collectionHeirarchy.Push(Name); collectionHeirarchyKind.Push(kind); //Specify the kind of object we're in }
private void RecursePrint(AbstractSyntaxCollection collection) { string tabs = ""; depth++; for (int d = 0; d < depth - 1; d++) { tabs += "\t"; } for (int i = 0; i < collection.Children.Count; i++) { builder.Append(tabs + collection.Children[i].ObjectKind + " : " + collection.Children[i].Name); for (int x = 0; x < collection.Children[i].SyntaxObjects.Count; x++) { builder.Append(", " + collection.Children[i].SyntaxObjects[x].instruction + " : " + collection.Children[i].SyntaxObjects[x].Value); } builder.AppendLine(); RecursePrint(collection.Children[i]); } depth--; }
public AbstractSyntaxTree Parse() { char?currentChar = scanner.GetNextCharacter(); while (currentChar != null) { if (currentChar == '<') { //This trick allows us to not worry about the statements having the '<' in them if (++depthCount == 1) //This means we have entered a valid tag { //Save the position so we can later extract the substring startPosition = scanner.Position + 1; } } else if (currentChar == '>') { //We expect this to go down to zero for each valid tag if (--depthCount == 0) { //Get the tag from the start position to here string tag = scanner.Source.Substring(startPosition, scanner.Position - startPosition); #region Import if (tag.StartsWith("Import ")) { //Parse the import information syntaxTree.Imports.Add(new Import() { Item = tag.Replace("Import ", string.Empty).Split(':')[0], BaseLibrary = tag.Replace("Import ", string.Empty).Split(':')[1] }); } #endregion #region Uses Accessors else if (tag.StartsWith("Namespace") || tag.StartsWith("Class") || tag.StartsWith("Interface") || tag.StartsWith("Enum ") || tag.StartsWith("Struct ") || tag.StartsWith("Delegate ") || tag.StartsWith("Constraint ") || tag.StartsWith("Function ") || tag.StartsWith("Variable ") || tag.StartsWith("Type ")) //This handles tags which can legally have accessors before them { if (collectionHeirarchyKind.Count > 0 && collectionHeirarchyKind.Peek() == AbstractObjectKind.Function && Accessors.Count > 0) { //Throw exception, accessors are not allowed here } //Things inside functions can not have accessors if (Accessors.Count == 0 && collectionHeirarchyKind.Count > 0) //Default to private for anything which requires an accessor but hasn't been given one { Accessors.Add(new SyntaxObject() { instruction = Instruction.Accessor, Value = "private" }); } #region Namespace if (tag.StartsWith("Namespace ")) { AccessorDepthApply(tag, AbstractObjectKind.Namespace, true); } #endregion #region Class else if (tag.StartsWith("Class ")) { AccessorDepthApply(tag, AbstractObjectKind.Class, true); } #endregion #region Interface else if (tag.StartsWith("Interface ")) { AccessorDepthApply(tag, AbstractObjectKind.Interface, true); } #endregion #region Enum else if (tag.StartsWith("Enum ")) { AccessorDepthApply(tag, AbstractObjectKind.Enum, true); } #endregion #region Struct else if (tag.StartsWith("Struct ")) { AccessorDepthApply(tag, AbstractObjectKind.Struct, true); } #endregion #region Delegate else if (tag.StartsWith("Delegate ")) { AccessorDepthApply(tag, AbstractObjectKind.Delegate, true); } #endregion #region Constraint else if (tag.StartsWith("Constraint ")) { AccessorDepthApply(tag, AbstractObjectKind.Constraint, true); } #endregion #region Function else if (tag.StartsWith("Function ")) { AccessorDepthApply(tag, AbstractObjectKind.Function, true); } #endregion #region Variable else if (tag.StartsWith("Variable ")) { string varName = tag.Replace("Variable ", string.Empty); DeepestNode.Children.Add(new AbstractSyntaxCollection() { Parent = DeepestNode, ObjectKind = AbstractObjectKind.Variable, Name = varName, SyntaxObjects = Accessors.ToList() }); //TODO figure out how to deal with separating variables from userdefined types and from function calls } else if (tag.StartsWith("Type ")) { string typeName = tag.Replace("Type ", string.Empty); DeepestNode.Children.Add(new AbstractSyntaxCollection() { Parent = DeepestNode, ObjectKind = AbstractObjectKind.Type, Name = typeName, SyntaxObjects = Accessors.ToList() }); } #endregion Accessors.Clear(); //All accessor's should have been applied so clear out the list } #endregion #region Accessor else if (tag.StartsWith("Accessor ")) { //Parse the accessor and add it to the accessor list, to be pulled out by the next valid group string accessor = tag.Replace("Accessor ", string.Empty); Accessors.Add(new SyntaxObject() { instruction = Instruction.Accessor, Value = accessor }); } #endregion #region No Accessors else if (Accessors.Count == 0) //If any accessors are set, these AbstractSyntaxKinds are not legal { //If accessors were placed in an illegal place, throw an exception if (tag.StartsWith("/Class")) { DepthUnApply(AbstractObjectKind.Class); } else if (tag.StartsWith("/Namespace")) { DepthUnApply(AbstractObjectKind.Namespace); } else if (tag.StartsWith("/Interface")) { DepthUnApply(AbstractObjectKind.Interface); } else if (tag.StartsWith("/Function")) { DepthUnApply(AbstractObjectKind.Function); } else if (tag.StartsWith("/Enum")) { DepthUnApply(AbstractObjectKind.Enum); } else if (tag.StartsWith("/Struct")) { DepthUnApply(AbstractObjectKind.Struct); } #region Operators else if (tag.StartsWith("Operator ")) { //TODO Generate extra nodes for +=, -=, *=, /=, %=, !=, ^=, |=, &= DeepestNode.Children.Add(new AbstractSyntaxCollection() { ObjectKind = AbstractObjectKind.Operator, Name = tag.Replace("Operator ", string.Empty).Replace("'", string.Empty), Parent = DeepestNode }); } #endregion #region EnumMember else if (tag.StartsWith("EnumMember")) { DeepestNode.Children.Add(new AbstractSyntaxCollection() { ObjectKind = AbstractObjectKind.EnumMember, Name = tag.Replace("EnumMember ", string.Empty), Parent = DeepestNode }); } #endregion #region Brackets else if (tag.StartsWith("OpeningBracket")) { AccessorDepthApply(tag, AbstractObjectKind.None); } else if (tag.StartsWith("ClosingBracket")) { DepthUnApply(AbstractObjectKind.None); } #endregion #region End Statement else if (tag.StartsWith("EndStatement")) { if (collectionHeirarchyKind.Peek() == AbstractObjectKind.Constraint || collectionHeirarchyKind.Peek() == AbstractObjectKind.Delegate) { DeepestNode = DeepestNode.Parent; collectionHeirarchy.Pop(); collectionHeirarchyKind.Pop(); } else { DeepestNode.Children.Add(new AbstractSyntaxCollection() { Parent = DeepestNode, Name = "EndStatement", ObjectKind = AbstractObjectKind.EndStatement }); } } #endregion #region String else if (tag.StartsWith("String ")) { DeepestNode.Children.Add(new AbstractSyntaxCollection() { ObjectKind = AbstractObjectKind.String, Name = tag.Replace("String ", string.Empty), Parent = DeepestNode }); } #endregion #region Integer Constant else if (tag.StartsWith("Integer ")) { DeepestNode.Children.Add(new AbstractSyntaxCollection() { ObjectKind = AbstractObjectKind.Integer, Name = tag.Replace("Integer ", string.Empty), Parent = DeepestNode }); } #endregion #region Attribute else if (tag.StartsWith("Attribute ")) { DeepestNode.Children.Add(new AbstractSyntaxCollection() { Parent = DeepestNode, Name = tag.Replace("Attribute ", string.Empty), ObjectKind = AbstractObjectKind.Attribute }); PreviousNode = DeepestNode.Children.Last(); } #endregion #region Keyword else if (tag.StartsWith("Keyword ")) { DeepestNode.Children.Add(new AbstractSyntaxCollection() { Parent = DeepestNode, Name = tag.Replace("Keyword ", string.Empty), ObjectKind = AbstractObjectKind.Keyword }); PreviousNode = DeepestNode.Children.Last(); } #endregion } #endregion #region OpeningTag else if (tag.StartsWith("OpeningTag")) { } #endregion } } currentChar = scanner.GetNextCharacter(); } syntaxTree.Nodes.Add(DeepestNode); //TODO we might want to check to make sure that the heirarchy is empty to make sure the global root is set return(SimplifyTree(syntaxTree)); }
private AbstractSyntaxCollection CorrectTree(AbstractSyntaxCollection collection) { if (collection.Children.Count > 0) { //TODO Parse variables and separate them from function calls #region Attribute Folding if (collection.ObjectKind == AbstractObjectKind.Function || collection.ObjectKind == AbstractObjectKind.Class) //Correct statements which should only be in a function { //Folds attributes into the owner's metadata int index = collection.Parent.Children.IndexOf(collection); if (index >= 1 && collection.Parent.Children[index - 1].ObjectKind == AbstractObjectKind.Attribute) { while (index > 0 && collection.Parent.Children[index - 1].ObjectKind == AbstractObjectKind.Attribute) { collection.SyntaxObjects.Add(new SyntaxObject() { instruction = Instruction.Attribute, Value = collection.Parent.Children[index - 1].Name }); collection.Parent.Children.RemoveAt(index - 1); index--; } } } #endregion #region Enum Member IDs else if (collection.ObjectKind == AbstractObjectKind.Enum) { int id = 0; //Parses the IDs of the enum members and sets them as SyntaxObjectMetadata for (int i = 0; i < collection.Children.Count; i++) { if (collection.Children[i].Name.Contains('=')) { string[] tmpID = collection.Children[i].Name.Split('='); collection.Children[i].Name = tmpID[0]; collection.Children[i].SyntaxObjects.Add(new SyntaxObject() { instruction = Instruction.EnumMemberValue, Value = tmpID[1] }); int tmp2 = int.Parse(tmpID[1]); if (tmp2 >= id) { id = tmp2 + 1; } } else { collection.Children[i].SyntaxObjects.Add(new SyntaxObject() { instruction = Instruction.EnumMemberValue, Value = (id++).ToString() }); } } } #endregion } else { if (collection.ObjectKind == AbstractObjectKind.Variable) //Correct statements which should only be in a function { #region Type Folding //Folds attributes into the owner's metadata int index = collection.Parent.Children.IndexOf(collection); if (index >= 1 && (collection.Parent.Children[index - 1].ObjectKind == AbstractObjectKind.Type || collection.Parent.Children[index - 1].ObjectKind == AbstractObjectKind.Variable)) { collection.Parent.Children[index - 1].Parent = collection; collection.Parent.Children[index - 1].ObjectKind = AbstractObjectKind.Type; //Everything here is definitely a type collection.Children.Add(collection.Parent.Children[index - 1]); collection.Parent.Children.RemoveAt(index - 1); } #endregion #region Command Completion index = collection.Parent.Children.IndexOf(collection); if (index >= 0 && index + 1 < collection.Parent.Children.Count && collection.Parent.ObjectKind != AbstractObjectKind.Variable && collection.Parent.Children[index + 1].ObjectKind == AbstractObjectKind.Operator && collection.Parent.Children[index + 1].Name == "=") { while (index + 1 < collection.Parent.Children.Count && collection.Parent.Children[index + 1].ObjectKind != AbstractObjectKind.EndStatement) { collection.Parent.Children[index + 1].Parent = collection; collection.Children.Add(collection.Parent.Children[index + 1]); collection.Parent.Children.RemoveAt(index + 1); } } #endregion #region Access Operator index = collection.Parent.Children.IndexOf(collection); if (index >= 0 && index + 1 < collection.Parent.Children.Count && collection.Parent.Children[index + 1].ObjectKind == AbstractObjectKind.Operator && collection.Parent.Children[index + 1].Name == ".") { while (index + 1 < collection.Parent.Children.Count && collection.Parent.Children[index + 1].ObjectKind != AbstractObjectKind.EndStatement) { collection.Parent.Children[index + 1].Parent = collection; collection.Children.Add(collection.Parent.Children[index + 1]); collection.Parent.Children.RemoveAt(index + 1); } } #endregion #region Function Call Identification //Folds attributes into the owner's metadata index = collection.Parent.Children.IndexOf(collection); if (index >= 0 && index + 1 < collection.Parent.Children.Count && collection.Parent.Children[index + 1].ObjectKind == AbstractObjectKind.None && collection.Parent.Children[index + 1].Name == "OpeningBracket") { collection.Parent.Children[index + 1].Parent = collection; collection.Parent.Children[index].ObjectKind = AbstractObjectKind.FunctionCall; //Everything here is definitely a function call collection.Children.Add(collection.Parent.Children[index + 1]); collection.Parent.Children.RemoveAt(index + 1); } #endregion } } #region Recursor for (int i = 0; i < collection.Children.Count; i++) { var tmp = CorrectTree(collection.Children[i]); //Correct all subnodes first } #endregion return(collection); }