Command-line tool
editMeziantou.Framework.Language.Tool parses a file with the language packages and writes its syntax tree and its diagnostics as JSON. Use it to see how a document is parsed before you write code against its tree, to check a file in a script, or to compare two parses.
The command reference lists every command and its options.
Install the tool
Install it as a global tool:
dotnet tool install --global Meziantou.Framework.Language.ToolDump a file
The syntax command parses --input and writes the JSON to the standard output. The language is detected from the extension of the file:
Meziantou.Framework.Language.Tool syntax --input app.csprojAdd --output to write the JSON to a file instead:
Meziantou.Framework.Language.Tool syntax --input appsettings.json --output tree.jsonWithout --input, the tool reads the standard input. It cannot detect the language then, so set it with --language:
echo '{"a":[1,2]}' | Meziantou.Framework.Language.Tool syntax --language json| Extensions | Language |
|---|---|
.css | CSS |
.ini, .editorconfig, .gitconfig, .npmrc | INI |
.json, .jsonc, .json5, .webmanifest | JSON |
.toml | TOML |
.xml, .xsd, .xsl, .xslt, .svg, .rss, .atom, .config, .csproj, .vbproj, .fsproj, .props, .targets, .nuspec, .resx, .plist, .xaml | XML |
.sh, .bash, .zsh | sh, bash, zsh |
.ps1, .psm1, .psd1 | PowerShell 7 and later (pwsh) |
.bat, .cmd | cmd |
--language overrides the detection. Its values are css, ini, json, toml, xml, the regular expression dialects regex (.NET), regex-dotnet, regex-javascript, regex-pcre, regex-ere and regex-bre, and the shells sh, bash, zsh, powershell, pwsh and cmd. A regular expression is never detected from an extension: set --language to parse one.
Meziantou.Framework.Language.Tool syntax --language regex-pcre --input pattern.txtRead the output
The JSON is written on a single line, with the same shape for every language. This file:
true // yesgives this tree, formatted here for reading:
{
"language": "json",
"root": {
"kind": "JsonDocument",
"type": "JsonDocumentSyntax",
"span": {
"start": 0,
"length": 12
},
"fullSpan": {
"start": 0,
"length": 12
},
"text": "true // yes\n",
"children": [
{
"kind": "JsonTrueLiteral",
"type": "JsonLiteralSyntax",
"span": {
"start": 0,
"length": 4
},
"fullSpan": {
"start": 0,
"length": 12
},
"text": "true // yes\n",
"children": [
{
"kind": "TrueKeyword",
"type": "SyntaxToken",
"text": "true",
"span": {
"start": 0,
"length": 4
},
"fullSpan": {
"start": 0,
"length": 12
},
"trailingTrivia": [
{
"kind": "WhitespaceTrivia",
"text": " ",
"span": {
"start": 4,
"length": 1
}
},
{
"kind": "SingleLineCommentTrivia",
"text": "// yes",
"span": {
"start": 5,
"length": 6
}
},
{
"kind": "EndOfLineTrivia",
"text": "\n",
"span": {
"start": 11,
"length": 1
}
}
]
}
]
},
{
"kind": "EndOfFileToken",
"type": "SyntaxToken",
"text": "",
"span": {
"start": 12,
"length": 0
},
"fullSpan": {
"start": 12,
"length": 0
}
}
]
}
}languageiscss,ini,json,toml,xml,regexorshell, anddialectgives the dialect of a regular expression or a script.- Each node has its
kind, itstype(its class name), itsspanandfullSpan, itstext, and itschildren: its nodes and tokens in the order of the text. A token has thetypeSyntaxToken, and its trivia inleadingTriviaandtrailingTrivia. fullSpancovers the trivia andspandoes not. Thetextof a node is its full text, with its trivia; thetextof a token is its text without its trivia.- Empty collections and default values are left out, and
valueTextappears only when it differs fromtext. - A regular expression adds its
captures, and itspatternOptionswhen an option is in effect.
Keep only what you need
Four options remove parts of the output:
| Option | Removes |
|---|---|
--no-tokens | The tokens of each node, and their trivia |
--no-trivia | The trivia of each token |
--no-text | The text of each node, token and trivia |
--no-spans | The spans of each node, token and trivia |
With --no-tokens --no-spans, the output shows the shape of the tree and the diagnostics. This file has a missing value:
{"port": }Meziantou.Framework.Language.Tool syntax --input MissingValue.json --no-tokens --no-spans{
"language": "json",
"diagnostics": [
{
"id": "JSON0007",
"severity": "Error",
"message": "Expected a JSON value."
}
],
"root": {
"kind": "JsonDocument",
"type": "JsonDocumentSyntax",
"text": "{\"port\": }\n",
"children": [
{
"kind": "JsonObject",
"type": "JsonObjectSyntax",
"text": "{\"port\": }\n",
"children": [
{
"kind": "JsonMember",
"type": "JsonMemberSyntax",
"text": "\"port\": ",
"children": [
{
"kind": "JsonSkippedText",
"type": "JsonSkippedTextSyntax",
"isMissing": true,
"text": ""
}
]
}
]
}
]
}
}The missing value is a node with isMissing, and the diagnostic gives its identifier, severity and message. With the spans, it also gives its span and its lineSpan, with zero-based lines and characters.
Exit code
A document with errors is not a failure: its diagnostics are in the output, and the exit code is 0. The exit code is not 0 only for a usage or input/output problem, such as a missing file or a language that cannot be detected.