cenotelie / hime

Apache License 2.0
27 stars 4 forks source link

Visitor generation #51

Closed woutersl closed 6 years ago

woutersl commented 6 years ago

Original report by Goomba (Bitbucket: 5a6bdc01c10afd5fcdd933bf, GitHub: raizam).


Hello! I needed to walk the AST tree using a generated IVisitor interface, so I added in the SDK a method to do so, here is the code (if interested) to be added somewhere in the generated namespace. It adds an IVisitor interface and an extension method Visit(IVisitor v) to ParseResult.

#!c#

        private void GenerateVisitor(StreamWriter stream)
        {
            stream.WriteLine("\t\t/// <summary>");
            stream.WriteLine("\t\t/// Visitor interface");
            stream.WriteLine("\t\t/// </summary>");
            stream.WriteLine("\t\tpublic interface IVisitor");
            stream.WriteLine("\t\t{");
            foreach (Variable var in variables)
            {
                if (var.Name.StartsWith(Grammar.PREFIX_GENERATED_VARIABLE))
                    continue;

                stream.WriteLine("\t\t\tvoid On{0}(ASTNode node);", Helper.ToUpperCamelCase(var.Name));
            }
            foreach (Virtual var in virtuals)
            {
                stream.WriteLine("\t\t\tvoid OnVirtual{0}(ASTNode node);", Helper.ToUpperCamelCase(var.Name));
            }
            stream.WriteLine("\t\t}");

            stream.WriteLine("\tpublic static class ParserHelper{");

            stream.WriteLine("\t\t/// <summary>");
            stream.WriteLine("\t\t/// Walk the AST using a visitor");
            stream.WriteLine("\t\t/// </summary>");
            stream.WriteLine("\t\tpublic static void Visit(this ParseResult result, IVisitor visitor)");
            stream.WriteLine("\t\t{");
            stream.WriteLine("\t\t\tVisitASTNode(result.Root, visitor);");
            stream.WriteLine("\t\t}");

            stream.WriteLine("\t\t/// <summary>");
            stream.WriteLine("\t\t/// Walk the AST using a visitor");
            stream.WriteLine("\t\t/// </summary>");
            stream.WriteLine("\t\tpublic static void VisitASTNode(ASTNode node, IVisitor visitor)");
            stream.WriteLine("\t\t{");

            stream.WriteLine("\t\t\tfor (int i = 0; i < node.Children.Count; i++)");
            stream.WriteLine("\t\t\t\tVisitASTNode(node.Children[i], visitor);");

            stream.WriteLine("\t\t\tswitch(node.Symbol.ID)");
            stream.WriteLine("\t\t\t{");
            foreach (Variable var in variables)
            {
                if (var.Name.StartsWith(Grammar.PREFIX_GENERATED_VARIABLE))
                    continue;

                   stream.WriteLine("\t\t\t\tcase 0x{1}: visitor.On{0}(node); break;", Helper.ToUpperCamelCase(var.Name), var.ID.ToString("X4"));
            }
            foreach (Virtual var in virtuals)
            {
                stream.WriteLine("\t\t\t\tcase 0x{1}: visitor.OnVirtual{0}(node); break;", Helper.ToUpperCamelCase(var.Name), var.ID.ToString("X4"));
            }
            stream.WriteLine("\t\t\t}");

            stream.WriteLine("\t\t}");

            stream.WriteLine("\t}");
        }
woutersl commented 6 years ago

Original comment by Goomba (Bitbucket: 5a6bdc01c10afd5fcdd933bf, GitHub: raizam).


I'm currently looking at the runtime library, feeling a little stuck.

I want to apply a Drop action to a terminal ASTNode "LABEL", while assigning to its parent its Value/TextPosition/Span.

OR apply a Promote action to the terminal ASTNode, and rename its symbol with the name of the parent its replacing

woutersl commented 6 years ago

Original comment by Laurent Wouters (Bitbucket: 557058:675792b6-d731-4823-9f7d-c6dfcb2df2b5, ).


Hello,

Thank you for your input. I will take it in consideration.

As to your question, if I understand correctly, you would like to replace a parent node with one of its children, except you want to retain the symbol (identifier and name) of the parent node, for example:

A (X Y="y" Z)

would yield

A="x" (X Z)

If my understanding is correct, there unfortunately cannot be achieved for two reasons. First, the promote action promotes the complete data of the node (the symbol, the text value, etc.). The reason is works likes this is due to the second reason : In the above case, a variable symbol is attached to the parent node and there is no way to attach a text value to a AST node with a variable. The way data is attached to an AST is a single value encoding the type of data, which can be either a variable, a virtual or a token. In the case of a token, the symbol the user can retrieved on the node corresponds to the terminal of the token and the textual value to that of the token. From this, it is impossible to represent a node with a variable symbol and a textual value, which would be the result of the case above.

I hope this explanation is clear !

I don't know what is your intended use case, but have you considered introducing virtual symbols? They can be useful as AST markers when you need to convey more information to the program that will walk through the AST.

woutersl commented 6 years ago

Original comment by Goomba (Bitbucket: 5a6bdc01c10afd5fcdd933bf, GitHub: raizam).


I did realize it's not possible while looking deeply into the code, but it's okay, this will just make my parser a little more verbose.

For the visitor I have removed the iteration part, which is from chids to parents, this order is very application specific, and I ended up parsing parents to childs.

I'd like to thank you for this library, this is very well done, the code is hard to understand but is very performant.

woutersl commented 6 years ago

Original comment by Alexey Smirnov (Bitbucket: 5b4cb1f71fd8f72ca71b68ba, GitHub: RamyAlexis).


Any news with this? I am interested too.

woutersl commented 6 years ago

Original comment by Goomba (Bitbucket: 5a6bdc01c10afd5fcdd933bf, GitHub: raizam).


The code is right above if needed

woutersl commented 6 years ago

Original comment by Laurent Wouters (Bitbucket: 557058:675792b6-d731-4823-9f7d-c6dfcb2df2b5, ).


Sorry for the late reply, this feature is going to be integrated within the SDK, with some adaptations and a port for the Java and Rust code generator. This should be available in the next release.

woutersl commented 6 years ago

Original comment by Laurent Wouters (Bitbucket: 557058:675792b6-d731-4823-9f7d-c6dfcb2df2b5, ).


Work is ongoing.

woutersl commented 6 years ago

Original comment by Laurent Wouters (Bitbucket: 557058:675792b6-d731-4823-9f7d-c6dfcb2df2b5, ).


[fix] Fixed issue #51 Visitor generation