Last active
September 2, 2016 05:58
-
-
Save yumura/6fc37462b004df40b6d898d9368ba579 to your computer and use it in GitHub Desktop.
Convert-FromPOMP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$here = Split-Path -Parent $MyInvocation.MyCommand.Path | |
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Converter.Tests.", ".") | |
$ConvertFromPomp = "$here\$sut" | |
Set-StrictMode -Version Latest | |
Describe "No Conversion" { | |
It Table { | |
$inJson = '{"Array":[{}]}' | |
$inPomp = @" | |
[[Array]]: | |
[Array.] | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Array { | |
$inJson = '{"Array":[[]]}' | |
$inPomp = @" | |
[[Array]]: | |
[[Array.]] | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It KeyValue { | |
$inJson = '{"key":"value"}' | |
$inPomp = "key: = value" | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Value { | |
$inJson = '{"Array":["value"]}' | |
$inPomp = @" | |
[[Array]]: | |
value | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
} | |
Describe Conversion { | |
It Null { | |
$inJson = '{"null":null}' | |
$inPomp = "null : null = null" | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Bool { | |
$inJson = '{"key1":true,"key2":false}' | |
$inPomp = @" | |
key1 : bool = true | |
key2 : bool = false | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Nullable { | |
$inJson = '{"key1":true,"key2":false,"key3":null}' | |
$inPomp = @" | |
key1 : bool? = true | |
key2 : bool? = false | |
key3 : bool? = null | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Default { | |
$inJson = '{"num":42}' | |
$inPomp = "num : int = 42" | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
} | |
Describe ConversionError { | |
It Table { | |
$message = "ConvertFrom-Pomp (2行目) : 要素の変換に失敗しました。" | |
$inPomp = @" | |
[[Array]]: hashtable # 空文字以外変換器とし受け付けない | |
[Array.] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (2行目) : 要素の変換に失敗しました。" | |
$inPomp = @" | |
[[Array]]: array # 空文字以外変換器とし受け付けない | |
[[Array.]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Null { | |
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。" | |
$inPomp = "key : null = 'null' # クオートのない null 以外受け付けない" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Bool { | |
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。" | |
$inPomp = "key : bool = 'true' # クオートのない true, false 以外受け付けない" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Nullable { | |
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。" | |
$inPomp = "key : bool? = 'true' # 変換に失敗しても null と評価されることはない" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Default { | |
$message = "ConvertFrom-Pomp (1行目) : 要素の変換に失敗しました。" | |
$inPomp = "key : int = 10:00:00" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$here = Split-Path -Parent $MyInvocation.MyCommand.Path | |
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Error.Tests.", ".") | |
$ConvertFromPomp = "$here\$sut" | |
Set-StrictMode -Version Latest | |
Describe UndefinitionParent { | |
It Table { | |
$message = "ConvertFrom-Pomp (1行目) : パスに未定義の親要素が指定されています。" | |
$inPomp = "[Parent.Child]" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (1行目) : パスに未定義の親要素が指定されています。" | |
$inPomp = "[[Parent.Child]]" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
# It KeyValue {} | |
# It Value {} | |
} | |
Describe RedefinitionParent { | |
It Table { | |
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの親要素が指定されています。" | |
$inPomp = @" | |
Parent = Definition | |
[Parent.Child] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの親要素が指定されています。" | |
$inPomp = @" | |
Parent = Definition | |
[[Parent.Child]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
# It KeyValue {} | |
# It Value {} | |
} | |
# Describe ValueIsNotParent {} | |
Describe RedefinitionPath { | |
It Table { | |
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。" | |
$inPomp = @" | |
Path = Definition | |
[Path] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。" | |
$inPomp = @" | |
Path = Definition | |
[[Path]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It KeyValue { | |
$message = "ConvertFrom-Pomp (2行目) : パスに定義済みの要素が指定されています。" | |
$inPomp = @" | |
Path = Definition | |
Path = Definition | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
# It Value {} | |
} | |
Describe NamedChild { | |
It Table { | |
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。" | |
$inPomp = @" | |
[[Parent]] | |
[Parent.Child] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。" | |
$inPomp = @" | |
[[Parent]] | |
[[Parent.Child]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It KeyValue { | |
$message = "ConvertFrom-Pomp (2行目) : 配列の子要素に名前付きのパスが指定されています。" | |
$inPomp = @" | |
[[Parent]] | |
Child = Error | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
# It Value {} | |
} | |
Describe UnnamedChild { | |
It Root { | |
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。" | |
$inPomp = @" | |
[''] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Table { | |
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。" | |
$inPomp = @" | |
[Parent] | |
[Parent.] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。" | |
$inPomp = @" | |
[Parent] | |
[[Parent.]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It KeyValue { | |
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。" | |
$inPomp = @" | |
[Parent] | |
'' = Error | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Value { | |
$message = "ConvertFrom-Pomp (2行目) : テーブルの子要素に名無しのパスが指定されています。" | |
$inPomp = @" | |
[Parent] | |
Value | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
} | |
Describe HeteroArray { | |
It Table { | |
$message = "ConvertFrom-Pomp (3行目) : 配列に異なるタイプの子要素が格納されています。" | |
$inPomp = @" | |
[[Parent]] | |
Child | |
[Parent.] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It Array { | |
$message = "ConvertFrom-Pomp (3行目) : 配列に異なるタイプの子要素が格納されています。" | |
$inPomp = @" | |
[[Parent]] | |
Child | |
[[Parent.]] | |
"@ | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
# It KeyValue {} | |
# It Value {} | |
} | |
Describe Unmatch { | |
It '[' { | |
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。" | |
$inPomp = "Broken]" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It ']' { | |
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。" | |
$inPomp = "[Broken" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It '[[' { | |
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。" | |
$inPomp = "Broken]]" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
It ']]' { | |
$message = "ConvertFrom-Pomp (1行目) : 解析不能な文です。" | |
$inPomp = "[[Broken" | |
try {$inPomp | & $ConvertFromPomp | & {throw 'NG'}} | |
catch {$_ | Should Be $message} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CmdletBinding()] | |
Param ([Parameter(ValueFromPipeline=$true)] [string]$String) | |
Begin | |
{ | |
# format | |
# ====== | |
$Script:MsgFormat = 'ConvertFrom-Pomp ({0}行目) : {1}' | |
# regex | |
# ===== | |
# primitive | |
$comment = '(#.*)' | |
$s = '([ \t]*)' | |
$id = '([a-zA-Z0-9?_-]+)' | |
$noneQ = '(\w([^\s#]*\w)?)' | |
$singleQ = "('([^']|'')*')" | |
$doubleQ = '("(\\*[^"\\]|\\(\\\\)*")*")' | |
# token | |
$Script:Key = "(|${id}|${singleQ}|${doubleQ})" | |
$Script:Value = "((?<None>${noneQ})|(?<Single>${singleQ})|(?<Double>${doubleQ}))" | |
$Script:Path = "(${key}(${s}\.${s}${key})*)" | |
$Script:Comment = "^${s}{0}${s}${comment}?$" | |
# helper function | |
# =============== | |
filter Get-POMP-LineRegex | |
{ | |
# functions | |
filter func ($Name, $Pattern, $ScriptBlock) | |
{ | |
@{ | |
Name = $Name | |
Pattern = [regex]($Script:Comment -f $Pattern) | |
ScriptBlock = $ScriptBlock | |
Message = "${Name}として解析します。" | |
} | |
} | |
@( | |
func Skip '' {param($State, $MatchGroups)} | |
func Table "\[${s}(?<Path>${Script:Path})${s}\]" { | |
param($MatchGroups) | |
# Child | |
$childPath = Convert-POMP-Path $MatchGroups['Path'].Value | |
$childName = Convert-POMP-Name $childPath | |
$child = @{ | |
Type = 'Table' | |
Value = New-Object PSCustomObject | |
Open = $true | |
LastName = Get-POMP-LastName $childPath | |
} | |
# Pearent | |
$parentPath = Get-POMP-ParentPath $childPath | |
$parentName = Convert-POMP-Name $parentPath | |
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent} | |
$parent = $Script:State.Name[$parentName] | |
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent} | |
# Pearent Type | |
switch ($parent.Type) | |
{ | |
Table { | |
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath} | |
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild} | |
$parent.Value | Add-Member $child.LastName $child.Value | |
} | |
Array { | |
if ($child.LastName -ne '') {Throw-POMP-Error NamedChild} | |
if ($Script:State.Name.Contains($childName)) | |
{ | |
$sibling = $Script:State.Name[$childName] | |
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath} | |
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray} | |
} | |
if ($parent.Converter -ne '') {Throw-POMP-Error ConversionError} | |
[void]$parent.Value.Add($child.Value) | |
} | |
Value {Throw-POMP-Error ValueIsNotParent} | |
default {throw '未定義型'} | |
} | |
Close-POMP-Path $childPath | |
$Script:State.Name[$childName] = $child | |
$Script:State.Current = $childPath | |
} | |
func Array "\[\[${s}(?<Path>${Script:Path})${s}\]\](${s}:${s}(?<Converter>${Script:Key}))?" { | |
param($MatchGroups) | |
# Path | |
$childPath = Convert-POMP-Path $MatchGroups['Path'].Value | |
$childName = Convert-POMP-Name $childPath | |
$child = @{ | |
Type = 'Array' | |
Value = New-Object 'System.Collections.ArrayList' | |
Open = $true | |
LastName = Get-POMP-LastName $childPath | |
Converter = Convert-POMP-String $MatchGroups['Converter'].Value | |
} | |
# Pearent | |
$parentPath = Get-POMP-ParentPath $childPath | |
$parentName = Convert-POMP-Name $parentPath | |
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent} | |
$parent = $Script:State.Name[$parentName] | |
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent} | |
# Pearent Type | |
switch ($parent.Type) | |
{ | |
Table { | |
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath} | |
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild} | |
$parent.Value | Add-Member $child.LastName $child.Value | |
} | |
Array { | |
if ($child.LastName -ne '') {Throw-POMP-Error NamedChild} | |
if ($Script:State.Name.Contains($childName)) | |
{ | |
$sibling = $Script:State.Name[$childName] | |
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath} | |
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray} | |
} | |
if ($parent.Converter -ne '') {Throw-POMP-Error ConversionError} | |
[void]$parent.Value.Add($child.Value) | |
} | |
Value {Throw-POMP-Error ValueIsNotParent} | |
default {throw '未定義型'} | |
} | |
Close-POMP-Path $childPath | |
$Script:State.Name[$childName] = $child | |
$Script:State.Current = $childPath | |
} | |
func KeyValue "(?<Key>${Script:Key})${s}(:${s}(?<Converter>${Script:Key}))?${s}=${s}(?<Value>${Script:Value})" { | |
param($MatchGroups) | |
# Path | |
$LastName = Convert-POMP-String $MatchGroups['Key'].Value | |
$childPath = Get-POMP-ChildPath $Script:State.Current $LastName | |
$childName = Convert-POMP-Name $childPath | |
$child = @{ | |
Type = 'Value' | |
Value = Convert-POMP-String $MatchGroups['Value'].Value | |
Open = $false | |
LastName = $LastName | |
Converter = Convert-POMP-String $MatchGroups['Converter'].Value | |
} | |
$child.ValueType = 'None', 'Single', 'Double' | ?{$MatchGroups[$_].Success} | Select-Object -First 1 | |
# Pearent | |
$parentPath = Get-POMP-ParentPath $childPath | |
$parentName = Convert-POMP-Name $parentPath | |
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent} | |
$parent = $Script:State.Name[$parentName] | |
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent} | |
# Pearent Type | |
switch ($parent.Type) | |
{ | |
Table { | |
if ($Script:State.Name.Contains($childName)) {Throw-POMP-Error RedefinitionPath} | |
if ($child.LastName -eq '') {Throw-POMP-Error UnnamedChild} | |
$success, $child.Value = Invoke-POMP-Converter $child.Converter $child.Value $child.ValueType | |
if (-not $success) {Throw-POMP-Error ConversionError} | |
$parent.Value | Add-Member $child.LastName $child.Value | |
} | |
Array {Throw-POMP-Error NamedChild} | |
Value {Throw-POMP-Error ValueIsNotParent} | |
default {throw '未定義型'} | |
} | |
Close-POMP-Path $childPath | |
$Script:State.Name[$childName] = $child | |
} | |
func Value "(?<Value>${Script:Value})" { | |
param($MatchGroups) | |
# Path | |
$LastName = '' | |
$childPath = Get-POMP-ChildPath $Script:State.Current $LastName | |
$childName = Convert-POMP-Name $childPath | |
$child = @{ | |
Type = 'Value' | |
Value = Convert-POMP-String $MatchGroups['Value'].Value | |
Open = $true | |
LastName = $LastName | |
} | |
$child.ValueType = 'None', 'Single', 'Double' | ?{$MatchGroups[$_].Success} | Select-Object -First 1 | |
# Pearent | |
$parentPath = Get-POMP-ParentPath $childPath | |
$parentName = Convert-POMP-Name $parentPath | |
if (-not ($Script:State.Name.Contains($parentName))) {Throw-POMP-Error UndefinitionParent} | |
$parent = $Script:State.Name[$parentName] | |
if (-not ($parent.Open)) {Throw-POMP-Error RedefinitionParent} | |
# Pearent Type | |
switch ($parent.Type) | |
{ | |
Table {Throw-POMP-Error UnnamedChild} | |
Array { | |
if ($Script:State.Name.Contains($childName)) | |
{ | |
$sibling = $Script:State.Name[$childName] | |
if (-not $sibling.Open) {Throw-POMP-Error RedefinitionPath} | |
if ($sibling.Type -ne $child.Type) {Throw-POMP-Error HeteroArray} | |
} | |
$success, $child.Value = Invoke-POMP-Converter $parent.Converter $child.Value $child.ValueType | |
if (-not $success) {Throw-POMP-Error ConversionError} | |
[void]$parent.Value.Add($child.Value) | |
} | |
Value {Throw-POMP-Error ValueIsNotParent} | |
default {throw '未定義型'} | |
} | |
Close-POMP-Path $childPath | |
$Script:State.Name[$childName] = $child | |
} | |
) | |
} | |
filter Close-POMP-Path ([System.Collections.Generic.List[string]]$Path) | |
{ | |
$oldPath = $Script:State.Current | |
$closePath = Copy-POMP-Path $oldPath | |
$i = 0 | |
$len = [Math]::Min($oldPath.Count, $Path.Count) | |
while ($i -lt $len -and $oldPath[$i] -eq $Path[$i]){$i++} | |
for($j = $oldPath.Count - 1; $j -ge $i; $j--) | |
{ | |
$close = $Script:State.Name[(Convert-POMP-Name $closePath)] | |
$close.Open = $false | |
$closePath.RemoveAt($j) | |
} | |
} | |
filter Convert-POMP-Name | |
([System.Collections.Generic.List[string]]$Path) | |
{($Path | %{[regex]::Escape($_)}) -join "`t"} | |
filter Convert-POMP-Path ([string] $String) | |
{ | |
$loop = $true | |
$str = $String | |
$list = New-Object 'System.Collections.Generic.List[string]' | |
$list.Add('Root') | |
while ($loop) | |
{ | |
switch -regex ($str) | |
{ | |
# stop | |
"^${Script:Key}$" { | |
$list.Add((Convert-POMP-String $str)) | |
$loop = $false | |
} | |
# split | |
"^(?<Head>${Script:key})${s}\.${s}(?<Tail>.*)$" { | |
$list.Add((Convert-POMP-String $Matches.Head)) | |
$str = $Matches.Tail | |
} | |
} | |
} | |
,$list | |
} | |
filter Convert-POMP-String ([string] $String) | |
{ | |
switch -regex ($String) | |
{ | |
'^"(?<In>.*)"$' {[regex]::Unescape($Matches.In)} | |
"^'(?<In>.*)'$" {$Matches.In -replace "''", "'"} | |
default {$String} | |
} | |
} | |
filter Copy-POMP-Path ([System.Collections.Generic.List[string]]$Path) | |
{ | |
$list = New-Object 'System.Collections.Generic.List[string]' | |
foreach ($str in $Path) {$list.Add($str)} | |
,$list | |
} | |
filter Get-POMP-ChildPath ([System.Collections.Generic.List[string]]$Path, $LastName) | |
{ | |
$list = New-Object 'System.Collections.Generic.List[string]' | |
foreach ($str in $Path) {$list.Add($str)} | |
$list.Add($LastName) | |
,$list | |
} | |
filter Get-POMP-LastName | |
([System.Collections.Generic.List[string]]$Path) | |
{$Path[$Path.Count - 1]} | |
filter Get-POMP-ParentPath ([System.Collections.Generic.List[string]]$Path) | |
{ | |
$list = New-Object 'System.Collections.Generic.List[string]' | |
for ($i = 0; $i -lt $Path.Count - 1; $i++) {$list.Add($Path[$i])} | |
,$list | |
} | |
filter Invoke-POMP-Converter ([String]$Converter, [String]$InputObject, [String]$Type) | |
{ | |
switch ($Converter) | |
{ | |
'' {return $true, $InputObject} | |
{$_.EndsWith('?')} { | |
$success, $value = Invoke-POMP-Converter Null $InputObject $Type | |
if ($success) {return $true, $value} | |
return Invoke-POMP-Converter ($_ -replace '\?$', '') $InputObject $Type | |
} | |
Null {return ($Type -eq 'None' -and $InputObject -eq 'Null'), $null} | |
Bool { | |
if ($Type -eq 'None') | |
{ | |
switch ($InputObject) | |
{ | |
true {return $true, $true } | |
false {return $true, $false} | |
} | |
} | |
} | |
default { | |
$return = $InputObject -as $Converter | |
if ($null -ne $return) {return $true, $return} | |
} | |
} | |
$false, $null | |
} | |
filter Throw-POMP-Error([string]$MessageID) | |
{ | |
$Message = switch ($MessageID) | |
{ | |
UndefinitionParent {'パスに未定義の親要素が指定されています。'} | |
RedefinitionParent {'パスに定義済みの親要素が指定されています。'} | |
RedefinitionPath {'パスに定義済みの要素が指定されています。'} | |
NamedChild {'配列の子要素に名前付きのパスが指定されています。'} | |
UnnamedChild {'テーブルの子要素に名無しのパスが指定されています。'} | |
HeteroArray {'配列に異なるタイプの子要素が格納されています。'} | |
Unmatch {'解析不能な文です。'} | |
ConversionError {'要素の変換に失敗しました。'} | |
default {"'${MessageID}'エラーが発生しました。"} | |
} | |
throw ($Script:MsgFormat -f $Script:State.LineNumber, $Message) | |
} | |
# Get Line RegEx | |
# ============== | |
$lineRegex = Get-POMP-LineRegex | |
# Get Root | |
# ============= | |
$dummyPath = Convert-POMP-Path Dummy | |
$rootPath = Get-POMP-ParentPath $dummyPath | |
$rootName = Convert-POMP-Name $rootPath | |
} | |
Process | |
{ | |
# Begin | |
$root = @{ | |
Type = 'Table' | |
Value = New-Object PSCustomObject | |
Open = $true | |
} | |
$Script:State = @{ | |
LineNumber = 1 | |
Name = @{$rootName = $root} | |
Current = Copy-POMP-Path $rootPath | |
} | |
# Process | |
foreach ($str in $String -split "`r`n|`r|`n") | |
{ | |
$success = $false | |
foreach ($fanc in $lineRegex) | |
{ | |
$lineMatch = $fanc.Pattern.Match($str) | |
if (-not $lineMatch.Success) {continue} | |
Write-Verbose ($Script:MsgFormat -f $Script:State.LineNumber, $fanc.Message) | |
& $fanc.ScriptBlock $lineMatch.Groups | |
$State.LineNumber++ | |
$success = $true | |
break | |
} | |
if (-not $success) {Throw-POMP-Error Unmatch} | |
} | |
# End | |
Close-POMP-Path (New-Object 'System.Collections.Generic.List[string]') | |
,$Script:State.Name[$rootName].Value | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$here = Split-Path -Parent $MyInvocation.MyCommand.Path | |
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".") | |
$ConvertFromPomp = "$here\$sut" | |
Set-StrictMode -Version Latest | |
Describe Skip { | |
It Skip { | |
$inJson = '{ }' | |
$inPomp = @" | |
# ハッシュ以降は、 | |
# コメントとして扱われ、 | |
# スペース、 | |
`t # タブ、 | |
# 空行は無視される | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Table { | |
$inJson = '{"Table":{}}' | |
$inPomp = '[Table] # Comment' | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Array { | |
$inJson = '{"Array":[]}' | |
$inPomp = '[[Array]] # Comment' | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It KeyValue { | |
$inJson = '{"Table":{"Key":"Value"}}' | |
$inPomp = @" | |
[Table] | |
Key = Value # Coment | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Value { | |
$inJson = '{"Array":["Value"]}' | |
$inPomp = @" | |
[[Array]] | |
Value # Coment | |
"@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
} | |
Describe Table { | |
It Table { | |
$inJson = '{"L":{"L":{},"R":{}},"R":{"L":{},"R":{}}}' | |
$inPomp = @' | |
[L] | |
[L.L] | |
[L.R] | |
[R] | |
[R.L] | |
[R.R] | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
It Array { | |
$inJson = '{"Table":{"Array":[{"Array":[]}]}}' | |
$inPomp = @' | |
[Table] | |
[[Table.Array]] | |
[Table.Array.] | |
[[Table.Array..Array]] | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10 | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10 | |
$outPomp | Should Be $outJson | |
} | |
It KeyValue { | |
$inJson = '{"Table":{"Key1":"Value","Key2":"Value","Key3":"Value"}}' | |
$inPomp = @' | |
[Table] | |
'Key1' = Value | |
'Key2' = Value | |
'Key3' = Value | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10 | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10 | |
$outPomp | Should Be $outJson | |
} | |
# It Value {} | |
} | |
Describe Array { | |
It Table { | |
$inJson = '{"Array":[{"Array":[{}]}]}' | |
$inPomp = @' | |
[[Array]] | |
[Array.] | |
[[Array..Array]] | |
[Array..Array.] | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10 | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10 | |
$outPomp | Should Be $outJson | |
} | |
It Array { | |
$inJson = '{"L":[[],[]],"R":[[],[]]}' | |
$inPomp = @' | |
[[L]] | |
[[L.]] | |
[[L.]] | |
[[R]] | |
[[R.]] | |
[[R.]] | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress | |
$outPomp | Should Be $outJson | |
} | |
# It KeyValue {} | |
It Value { | |
$inJson = '{"Array":["Value","Value","Value"]}' | |
$inPomp = @' | |
[[Array]] | |
Value | |
Value | |
Value | |
'@ | |
$outJson = $inJson | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10 | |
$outPomp = $inPomp | & $ConvertFromPomp | ConvertTo-Json -Compress -Depth 10 | |
$outPomp | Should Be $outJson | |
} | |
} | |
Describe DoubleQuarto { | |
It Empty { | |
$string = '' | |
$inPomp = 'String = ""' | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It EscapeDoubleQuarto { | |
$string = '"' | |
$inPomp = 'String = "\""' | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It Escapes { | |
$string = " `0 `a `b `f `n `r `t `v `` `\ " | |
$inPomp = 'String = " \0 \a \b \f \n \r \t \v \` \\ "' | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It Japanese { | |
$string = "常用漢字、ひらがな、カタカナ" | |
$inPomp = 'String = "常用漢字、ひらがな、カタカナ"' | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
} | |
Describe SingleQuarto { | |
It Empty { | |
$string = "" | |
$inPomp = "String = ''" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It EscapeSingleQuarto { | |
$string = "'" | |
$inPomp = "String = ''''" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It UnEscape { | |
$string = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
$inPomp = @' | |
String = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
'@ | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It Japanese { | |
$string = '常用漢字、ひらがな、カタカナ' | |
$inPomp = "String = '常用漢字、ひらがな、カタカナ'" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
} | |
Describe SingleQuarto { | |
It Empty { | |
$string = "" | |
$inPomp = "String = ''" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It EscapeSingleQuarto { | |
$string = "'" | |
$inPomp = "String = ''''" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It UnEscape { | |
$string = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
$inPomp = @' | |
String = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
'@ | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It Japanese { | |
$string = '常用漢字、ひらがな、カタカナ' | |
$inPomp = "String = '常用漢字、ひらがな、カタカナ'" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
} | |
Describe NoneQuarto { | |
# It Empty {} | |
# It EscapeNoneQuarto {} | |
It UnEscape { | |
$string = 'Begin:\0,\a,\b,\f,\n,\r,\t,\v,\`,\\:End' | |
$inPomp = "String = {0}" -f 'Begin:\0,\a,\b,\f,\n,\r,\t,\v,\`,\\:End' | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
It Japanese { | |
$string = '常用漢字、ひらがな、カタカナ' | |
$inPomp = "String = 常用漢字、ひらがな、カタカナ" | |
$inPomp | & $ConvertFromPomp | Select-Object -ExpandProperty String | Should Be $string | |
} | |
} | |
Describe Path { | |
It Space { | |
$inPomp = @" | |
[ Space`t] | |
[ Space`t`t. ' Space\t'`t] | |
[ Space`t`t. ' Space\t'`t. " Space\t\t"`t] | |
Path = OK | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.Space.' Space\t'." Space`t`t".Path | Should Be OK | |
} | |
It Dot { | |
$inPomp = @" | |
['.'] | |
['.'.".."] | |
Path = OK | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.'.'.'..'.Path | Should Be OK | |
} | |
It Escape { | |
$unescape = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
$escape = " `0 `a `b `f `n `r `t `v `` `\ " | |
$inPomp = @" | |
['${unescape}'] # unescape | |
['${unescape}'."${unescape}"] # escape | |
Path = OK | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.$unescape.$escape.Path | Should Be OK | |
} | |
It Japanese { | |
$inPomp = @" | |
['常用漢字'] | |
['常用漢字'."ひらがな_カタカナ"] | |
Path = OK | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.常用漢字.ひらがな_カタカナ.Path | Should Be OK | |
} | |
} | |
Describe Key { | |
It Space { | |
$inPomp = @" | |
Space1 `t = OK1 | |
' Space2\t'`t = OK2 | |
" Space3\t"`t = OK3 | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.Space1 | Should Be OK1 | |
$outPomp.' Space2\t' | Should Be OK2 | |
$outPomp." Space3`t" | Should Be OK3 | |
} | |
It NoneQuarto { | |
$inPomp = @" | |
abc-xyz_ABC-XYZ_01-89? = OK | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.'abc-xyz_ABC-XYZ_01-89?' | Should Be OK | |
} | |
It Escape { | |
$unescape = ' \0 \a \b \f \n \r \t \v \` \\ ' | |
$escape = " `0 `a `b `f `n `r `t `v `` `\ " | |
$inPomp = @" | |
'${unescape}' = unescape | |
"${unescape}" = escape | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.$unescape | Should Be unescape | |
$outPomp.$escape | Should Be escape | |
} | |
It Japanese { | |
$inPomp = @" | |
'常用漢字' = OK1 | |
"ひらがな" = OK2 | |
"カタカナ" = OK3 | |
"@ | |
$outPomp = $inPomp | & $ConvertFromPomp | |
$outPomp.常用漢字 | Should Be OK1 | |
$outPomp.ひらがな | Should Be OK2 | |
$outPomp.カタカナ | Should Be OK3 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment