Skip to content

AstVisitor rework #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jan 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ dotnet_naming_style.end_in_async_style.required_prefix =
dotnet_naming_style.end_in_async_style.required_suffix = Async

# dotnet_naming_rule.<namingRuleTitle>.severity = <value>
dotnet_naming_rule.async_methods_end_in_async.severity = warning
dotnet_naming_rule.async_methods_end_in_async.severity = suggestion

# Remove unnecessary import https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
dotnet_diagnostic.IDE0005.severity = warning
101 changes: 55 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The parser from this library is used in [GraphQL for .NET](https://github.com/gr

Preview versions of this package are available on [GitHub Packages](https://github.com/orgs/graphql-dotnet/packages?repo_name=parser).

## Lexer
## 1. Lexer

Generates token based on input text. Lexer takes advantage of `ReadOnlyMemory<char>` and in most cases
does not allocate memory on the managed heap at all.
Expand All @@ -38,7 +38,7 @@ var token = Lexer.Lex("\"str\"");
Lex method always returns the first token it finds. In this case case the result would look like following.
![lexer example](assets/lexer-example.png)

## Parser
## 2. Parser

Parses provided GraphQL expression into AST (abstract syntax tree). Parser also takes advantage of
`ReadOnlyMemory<char>` but still allocates memory for AST.
Expand All @@ -61,51 +61,60 @@ By default `ParserOptions.Ignore` is `IgnoreOptions.IgnoreComments` to improve p
If you don't need information about tokens locations in the source document, then use `IgnoreOptions.IgnoreCommentsAndLocations`.
This will maximize the saving of memory allocated in the managed heap for AST.

### Example of json representation of the resulting AST
## 3. INodeVisitor

```json
`INodeVisitor` provides API to traverse AST of the parsed GraphQL document.
Default implementation of this interface is `DefaultNodeVisitor` that
traverses all AST nodes of the provided one. You can inherit from it and
implement your own AST processing algorithm.

For printing SDL from AST, you can use `SDLWriter<TContext>` visitor.
This is a highly optimized visitor for asynchronous non-blocking SDL output
into provided `TextWriter`. In the majority of cases it does not allocate
memory in the managed heap at all.

You can also find a `StructureWriter<TContext>` visitor that prints AST
into the provided `TextWriter` as a hierarchy of node types. It can be useful
when debugging for better understanding the AST structure.
Consider GraphQL document

```graphql
query a { name age }
```

After `StructureWriter` processing the output text will be

```
Document
OperationDefinition
Name [a]
SelectionSet
Field
Name [name]
Field
Name [age]
```

### Usage

```c#
public class Context : IWriteContext
{
"Definitions": [{
"Directives": [],
"Kind": 2,
"Name": null,
"Operation": 0,
"SelectionSet": {
"Kind": 5,
"Selections": [{
"Alias": null,
"Arguments": [],
"Directives": [],
"Kind": 6,
"Name": {
"Kind": 0,
"Value": "field",
"Location": {
"End": 50,
"Start": 31
}
},
"SelectionSet": null,
"Location": {
"End": 50,
"Start": 31
}
}],
"Location": {
"End": 50,
"Start": 13
}
},
"VariableDefinitions": null,
"Location": {
"End": 50,
"Start": 13
}
}],
"Kind": 1,
"Location": {
"End": 50,
"Start": 13
}
public TextWriter Writer { get; set; } = new StringWriter();

public Stack<AST.ASTNode> Parents { get; set; } = new Stack<AST.ASTNode>();

public CancellationToken CancellationToken { get; set; }
}

public static void Parse(string text)
{
var document = Parser.Parse(text);

var context = new Context();
var visitor = new SDLWriter<Context>()
await visitor.Visit(document, context);
var rendered = context.Writer.ToString();
Console.WriteLine(rendered);
}
```
245 changes: 200 additions & 45 deletions src/GraphQLParser.ApiTests/GraphQLParser.approved.txt

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/GraphQLParser.Tests/Files/CommentsOnAlias.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query q
{
#alias comment
a
#colon comment
:
#field comment
name
}
Loading