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

MatchReport: rework internal data structure of matches. #51

Merged
merged 8 commits into from Feb 20, 2019

Conversation

Projects
None yet
3 participants
@jessitron
Copy link
Contributor

jessitron commented Feb 11, 2019

Previously, PatternMatch was both an external interface and an internal match-constructing one.
This gave it multiple purposes; it had match-related information, and also structural information useful to people using microgrammars.

In this rework, the structure built up internally during the match process contains one consistent tree. This is then converted into the PatternMatch structure for backwards compatibility.

But it can also convert into a ParseTree (which duck-types to a TreeNode). the ParseTree corresponds directly to the input file, so I can use this in the GUI to show how microgrammars match. Then I can change the conversion of microgrammars into TreeNode, which will change how path expressions work with them -- it'll have more detail, and still include all the user-defined terms.

Here is a printout of a ParseTree for @ChangeControlled @Donkey("24", name = "Eeyore")

┬ Concat [@ChangeControlled @Donkey("24", name = "Eeyore")]
└─┬ annotations [@ChangeControlled @Donkey("24", name = "Eeyore")]
  └─┬ Rep [@ChangeControlled @Donkey("24", name = "Eeyore")]
    ├─┬ Repetition [@ChangeControlled ]
    │ └─┬ Concat [@ChangeControlled ]
    │   ├─┬ _at [@]
    │   │ └── Literal [@]
    │   ├─┬ name [ChangeControlled]
    │   │ └── Regex [ChangeControlled]
    │   ├── Whitespace [ ]
    │   └─┬ _content []
    │     └── Optional []
    └─┬ Repetition [@Donkey("24", name = "Eeyore")]
      └─┬ Concat [@Donkey("24", name = "Eeyore")]
        ├─┬ _at [@]
        │ └── Literal [@]
        ├─┬ name [Donkey]
        │ └── Regex [Donkey]
        └─┬ _content [("24", name = "Eeyore")]
          └─┬ Optional [("24", name = "Eeyore")]
            └─┬ Concat [("24", name = "Eeyore")]
              ├─┬ _lp [(]
              │ └── Literal [(]
              ├─┬ block ["24", name = "Eeyore"]
              │ └── CBlock ["24", name = "Eeyore"]
              └─┬ _rp [)]
                └── Literal [)]

while the ValueStructure for that is:

{
  "annotations": [
    {
      "name": "ChangeControlled",
      "content": ""
    },
    {
      "name": "Donkey",
      "content": "\"24\", name = \"Eeyore\""
    }
  ]
}

the ValueStructure is also available from the MatchReport; it contains the user-defined terms only. We can deprecate PatternMatch in favor of this. (although I haven't yet changed the update infrastructure to get an updateable ValueStructure)

You can also get a full explanation of the match, which includes failed matches. For instance,
here is the explanation report for the successful match above. It includes failed reports inside of Opt, and at the end of the Rep.

┬ ☻Concat [@ChangeControlled @Donkey("24", name = "Eeyore")]
└─┬ ☻annotations [@ChangeControlled @Donkey("24", name = "Eeyore")]
  └─┬ ☻Rep [@ChangeControlled @Donkey("24", name = "Eeyore")]
    ├─┬ ☻Repetition [@ChangeControlled ]
    │ └─┬ ☻Concat [@ChangeControlled ]
    │   ├─┬ ☻_at [@]
    │   │ └── ☻Literal [@]
    │   ├─┬ ☻name [ChangeControlled]
    │   │ └── ☻Regex Matched RegExp: /^[a-zA-Z_$][a-zA-Z0-9_$]*/
    │   ├── ☻Whitespace [ ]
    │   └─┬ ☻_content []
    │     └─┬ ☻Optional Did not match, but that's OK; it's optional.
    │       └─┬ ☹Concat Failed at step '_lp'
    │         └── ☹Literal Did not match literal [(]: saw [@]
    ├─┬ ☻Repetition [@Donkey("24", name = "Eeyore")]
    │ └─┬ ☻Concat [@Donkey("24", name = "Eeyore")]
    │   ├─┬ ☻_at [@]
    │   │ └── ☻Literal [@]
    │   ├─┬ ☻name [Donkey]
    │   │ └── ☻Regex Matched RegExp: /^[a-zA-Z_$][a-zA-Z0-9_$]*/
    │   └─┬ ☻_content [("24", name = "Eeyore")]
    │     └─┬ ☻Optional [("24", name = "Eeyore")]
    │       └─┬ ☻Concat [("24", name = "Eeyore")]
    │         ├─┬ ☻_lp [(]
    │         │ └── ☻Literal [(]
    │         ├─┬ ☻block ["24", name = "Eeyore"]
    │         │ └── ☻CBlock ["24", name = "Eeyore"]
    │         └─┬ ☻_rp [)]
    │           └── ☻Literal [)]
    └─┬ ☹Repetition Looks like this is the end of the repetition
      └─┬ ☹Concat Failed at step '_at'
        └── ☹Literal Did not match literal [@]: saw []

If I alter the string to ``@ChangeControlled @donkey["24", name = "Eeyore")` (open paren is now a square brace) so that it doesn't match, I can see an explanation of the failure. Here, it didn't consume everything we expected, which was because it found [ instead of (

┬ ☹ExactMatch Not all input was consumed: Left over ["24", name = "Eeyore...]
├─┬ ☻Concat [@ChangeControlled @Donkey]
│ └─┬ ☻annotations [@ChangeControlled @Donkey]
│   └─┬ ☻Rep [@ChangeControlled @Donkey]
│     ├─┬ ☻Repetition [@ChangeControlled ]
│     │ └─┬ ☻Concat [@ChangeControlled ]
│     │   ├─┬ ☻_at [@]
│     │   │ └── ☻Literal [@]
│     │   ├─┬ ☻name [ChangeControlled]
│     │   │ └── ☻Regex Matched RegExp: /^[a-zA-Z_$][a-zA-Z0-9_$]*/
│     │   ├── ☻Whitespace [ ]
│     │   └─┬ ☻_content []
│     │     └─┬ ☻Optional Did not match, but that's OK; it's optional.
│     │       └─┬ ☹Concat Failed at step '_lp'
│     │         └── ☹Literal Did not match literal [(]: saw [@]
│     ├─┬ ☻Repetition [@Donkey]
│     │ └─┬ ☻Concat [@Donkey]
│     │   ├─┬ ☻_at [@]
│     │   │ └── ☻Literal [@]
│     │   ├─┬ ☻name [Donkey]
│     │   │ └── ☻Regex Matched RegExp: /^[a-zA-Z_$][a-zA-Z0-9_$]*/
│     │   └─┬ ☻_content []
│     │     └─┬ ☻Optional Did not match, but that's OK; it's optional.
│     │       └─┬ ☹Concat Failed at step '_lp'
│     │         └── ☹Literal Did not match literal [(]: saw [[]
│     └─┬ ☹Repetition Looks like this is the end of the repetition
│       └─┬ ☹Concat Failed at step '_at'
│         └── ☹Literal Did not match literal [@]: saw [[]
└── ☹EndOfInput Expected end of input. Saw: "24", name = "Eeyore...

Currently the MatchReport is only available externally through exactMatchReport. Later I'll extend its availability, so that PatternMatch is not the only structure available outside. ValueStructure and ParseTree are preferable.

@jessitron jessitron requested a review from johnsonr Feb 11, 2019

Rework internal structure to MatchReport.
Now you can get a PatternMatch if you really need one
but ValueStructure and ParseTree are better
and ExplanationTree is great for "why didn't it match?"

@jessitron jessitron force-pushed the MatchReport2 branch from 337baa4 to 75e9e35 Feb 11, 2019

atomist-bot and others added some commits Feb 11, 2019

Autofix: TypeScript imports
[atomist:generated] [atomist:autofix=typescript_imports]
Autofix: tslint
[atomist:generated] [atomist:autofix=tslint]
Autofix: tslint
[atomist:generated] [atomist:autofix=tslint]

@johnsonr johnsonr merged commit c89e0f9 into master Feb 20, 2019

1 of 2 checks passed

sdm/atomist/atomist-sdm Atomist Software Delivery Machine goals in progress
Details
license/cla Contributor License Agreement is signed.
Details

@johnsonr johnsonr deleted the MatchReport2 branch Feb 20, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.