Skip to content
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

Enable multiline string support in tree-sitter gammar #524

Merged
merged 4 commits into from
Aug 21, 2024
Merged
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
13 changes: 13 additions & 0 deletions dsc/examples/multiline.dsc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
resources:
- name: test multi-line
type: Test/Echo
properties:
output: |
This is a
'multi-line'
string.
- name: test single-quote escaping
type: Test/Echo
properties:
output: "[concat('This is a single-quote: ', '''')]"
25 changes: 25 additions & 0 deletions dsc/examples/winps_script.dsc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
metadata:
Microsoft.DSC:
securityContext: Elevated
resources:
- type: Microsoft.Windows/WindowsPowerShell
name: Run WinPS script
properties:
resources:
- name: Run script
type: PSDesiredStateConfiguration/Script
properties:
GetScript: |
$text = @"
get
"@
# Returning result must be this type of hashtable
@{Result=$text}
TestScript: |
# TestScript must return a boolean
$true
SetScript: |
$text = @"
set
"@
13 changes: 13 additions & 0 deletions dsc/tests/dsc_expressions.tests.ps1
Original file line number Diff line number Diff line change
@@ -63,4 +63,17 @@ resources:
$LASTEXITCODE | Should -Be 2
$out | Should -BeLike "*ERROR*"
}

It 'Multi-line string literals work' {
$yamlPath = "$PSScriptRoot/../examples/multiline.dsc.yaml"
$out = dsc config get -p $yamlPath | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.results[0].result.actualState.output | Should -BeExactly @"
This is a
'multi-line'
string.
"@.Replace("`r", "")
$out.results[1].result.actualState.output | Should -BeExactly "This is a single-quote: '"
}
}
3 changes: 2 additions & 1 deletion dsc_lib/src/parser/functions.rs
Original file line number Diff line number Diff line change
@@ -97,7 +97,8 @@ fn convert_args_node(statement_bytes: &[u8], args: &Option<Node>) -> Result<Opti
match arg.kind() {
"string" => {
let value = arg.utf8_text(statement_bytes)?;
result.push(FunctionArg::Value(Value::String(value.to_string())));
// Resolve escaped single quotes
result.push(FunctionArg::Value(Value::String(value.to_string().replace("''", "'"))));
},
"number" => {
let value = arg.utf8_text(statement_bytes)?;
2 changes: 1 addition & 1 deletion tree-sitter-dscexpression/build.ps1
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ if ($UpdatePackages) {
npm cache clean --force
npm logout
vsts-npm-auth -config .npmrc -F -V
npm install --force --verbose
npm install --force --verbose --registry https://pkgs.dev.azure.com/mseng/_packaging/OneESD-DevOps/npm/registry/
}

Invoke-NativeCommand 'npx tree-sitter generate --build'
8 changes: 5 additions & 3 deletions tree-sitter-dscexpression/grammar.js
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ const PREC = {
module.exports = grammar({
name: 'dscexpression',

extras: $ => ['\n', ' '],

rules: {
statement: $ => choice(
$.escapedStringLiteral,
@@ -16,16 +18,16 @@ module.exports = grammar({
escapedStringLiteral: $ => token(prec(PREC.ESCAPEDSTRING, seq('[[', /.*?/))),
_expressionString: $ => prec(PREC.EXPRESSIONSTRING, seq('[', $.expression, ']')),
expression: $ => seq(field('function', $.function), optional(field('accessor',$.accessor))),
stringLiteral: $ => token(prec(PREC.STRINGLITERAL, /[^\[].*?/)),
stringLiteral: $ => token(prec(PREC.STRINGLITERAL, /[^\[](.|\n)*?/)),

function: $ => seq(field('name', $.functionName), '(', field('args', optional($.arguments)), ')'),
functionName: $ => /[a-z][a-zA-Z0-9]*/,
arguments: $ => seq($._argument, repeat(seq(',', $._argument))),
_argument: $ => choice($.expression, $._quotedString, $.number, $.boolean),

_quotedString: $ => seq('\'', $.string, '\''),
// ARM strings are allowed to contain single-quote characters
string: $ => /[^']*/,
// ARM strings are not allowed to contain single-quote characters unless escaped
string: $ => /([^']|''|\n)*/,
number: $ => /-?\d+/,
boolean: $ => choice('true', 'false'),

4 changes: 2 additions & 2 deletions tree-sitter-dscexpression/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions tree-sitter-dscexpression/test/corpus/invalid_expressions.txt
Original file line number Diff line number Diff line change
@@ -198,3 +198,19 @@ Expression with index accessor outside
(number))))
(ERROR
(number)))

=====
String with un-escaped single-quote
=====
[myFunction('argString'test'value')]
---

(statement
(expression
(function
(functionName)
(arguments
(string))
(ERROR
(functionName)
(functionName)))))
47 changes: 47 additions & 0 deletions tree-sitter-dscexpression/test/corpus/valid_expressions.txt
Original file line number Diff line number Diff line change
@@ -274,3 +274,50 @@ Array index with function and nested dot-notation with index
(memberName)))))
(index
(number)))))

=====
Multi-line expression
=====
[myFunction(
'argString',
1,
-1,
true
)]
---

(statement
(expression
(function
(functionName)
(arguments
(string)
(number)
(number)
(boolean)))))

=====
Multi-line literal string
=====
This
is
a
multiline
string
---

(statement
(stringLiteral))

=====
Escaped single-quotes
=====
[myFunction('this ''is'' a string')]
---

(statement
(expression
(function
(functionName)
(arguments
(string)))))