Skip to content

Commit

Permalink
Add parser vis (#334)
Browse files Browse the repository at this point in the history
  • Loading branch information
haneslinger authored Sep 18, 2024
1 parent 39087f9 commit 849e672
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 25 deletions.
23 changes: 23 additions & 0 deletions buildingmotif-app/package-lock.json

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

1 change: 1 addition & 0 deletions buildingmotif-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@angular/platform-browser-dynamic": "^14.3.0",
"@angular/router": "^14.3.0",
"@ctrl/ngx-codemirror": "^5.1.1",
"@mui/icons-material": "^5.15.21",
"blockly": "^11.0.0",
"codemirror": "^5.65.8",
"rxjs": "~7.5.0",
Expand Down
4 changes: 3 additions & 1 deletion buildingmotif-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ import {MatStepperModule} from '@angular/material/stepper';
import { ShapeValidationComponent } from './shape-validation/shape-validation.component';
import {MatExpansionModule} from '@angular/material/expansion';
import { PointlabelParserComponent } from './pointlabel-parser/pointlabel-parser.component';
import {MatGridListModule} from '@angular/material/grid-list';
import {MatGridListModule} from '@angular/material/grid-list';
import { ParserVisComponent } from './parser-vis/parser-vis.component';

@NgModule({
declarations: [
Expand All @@ -59,6 +60,7 @@ import {MatGridListModule} from '@angular/material/grid-list';
ModelValidateComponent,
ShapeValidationComponent,
PointlabelParserComponent,
ParserVisComponent,
],
imports: [
BrowserModule,
Expand Down
11 changes: 11 additions & 0 deletions buildingmotif-app/src/app/parser-vis/parser-vis.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.my-parser-vis {
display: flex;
flex-direction: row;
}

.parser-vis {
display: flex;
flex-direction: column;
margin : .5rem;
justify-content: center;
}
67 changes: 67 additions & 0 deletions buildingmotif-app/src/app/parser-vis/parser-vis.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<ul *ngIf="parser.args" class="my-parser-vis">
<ng-container *ngFor="let child of parser.args.parsers" [ngTemplateOutlet]="treeNode"
[ngTemplateOutletContext]="{ $implicit: child }">
</ng-container>
</ul>

<ng-template #substring_n let-data>
<div class="parser-vis">
<div>{{data.args.type_name}}</div>
<mat-icon style="color: #a55b80;" matSuffix>square</mat-icon>
</div>
</ng-template>

<ng-template #stringUrl let-data>
<div class="parser-vis">
<div>{{data.args.type_name}}</div>
<mat-icon style="color: #5ba5a5;" matSuffix>square</mat-icon>
</div>
</ng-template>

<ng-template #rest let-data>
<div class="parser-vis">
<div>{{data.args.type_name}}</div>
<mat-icon style="color: #a55b5b;" matSuffix>square</mat-icon>
</div>
</ng-template>

<ng-template #stringToken let-data>
<div class="parser-vis">
<div>{{data.args.s}}</div>
<mat-icon style="color: #a5a55b;" matSuffix>square</mat-icon>
</div>
</ng-template>

<ng-template #treeNode let-data>
<ng-container *ngIf="data.uiParser == 'choice'">
<div class="parser-vis">
<ng-container *ngFor="let child of data.args.parsers" [ngTemplateOutlet]="treeNode"
[ngTemplateOutletContext]="{ $implicit: child }">
</ng-container>
</div>
</ng-container>

<ng-container *ngIf="data.uiParser == 'sequence-internal'">
<div style="display: flex; flex-direction: row; justify-content: start;">
<ng-container *ngFor="let child of data.args.parsers" [ngTemplateOutlet]="treeNode"
[ngTemplateOutletContext]="{ $implicit: child }">
</ng-container>
</div>
</ng-container>

<ng-container *ngIf="data.uiParser == 'substring_n'" [ngTemplateOutlet]="substring_n"
[ngTemplateOutletContext]="{ $implicit: data }">
</ng-container>

<ng-container *ngIf="data.uiParser == 'rest'" [ngTemplateOutlet]="rest"
[ngTemplateOutletContext]="{ $implicit: data }">
</ng-container>

<ng-container *ngIf="data.uiParser == 'string-url'" [ngTemplateOutlet]="stringUrl"
[ngTemplateOutletContext]="{ $implicit: data }">
</ng-container>

<ng-container *ngIf="data.uiParser == 'string-token'" [ngTemplateOutlet]="stringToken"
[ngTemplateOutletContext]="{ $implicit: data }">
</ng-container>
</ng-template>
23 changes: 23 additions & 0 deletions buildingmotif-app/src/app/parser-vis/parser-vis.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ParserVisComponent } from './parser-vis.component';

describe('ParserVisComponent', () => {
let component: ParserVisComponent;
let fixture: ComponentFixture<ParserVisComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ParserVisComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(ParserVisComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
16 changes: 16 additions & 0 deletions buildingmotif-app/src/app/parser-vis/parser-vis.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, OnInit, Input} from '@angular/core';

@Component({
selector: 'app-parser-vis',
templateUrl: './parser-vis.component.html',
styleUrls: ['./parser-vis.component.css']
})
export class ParserVisComponent implements OnInit {
@Input() parser: any | undefined;

constructor() { }

ngOnInit(): void {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ svg {
ngx-codemirror {
height: 100%;
width: 100%;
font-size: 24px;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
<app-parser-vis [parser]="parser"></app-parser-vis>

<div class="container">
<div class="pointlabels">
<!-- Unparsed -->
<ngx-codemirror #codemirror [options]="codeMirrorOptions"
[formControl]="pointLabelsFormControl"></ngx-codemirror>
<button mat-raised-button color="primary" (click)="parse()">Parse</button>
<div *ngIf="results.length === 0">
<ngx-codemirror #codemirror [options]="codeMirrorOptions" [formControl]="pointLabelsFormControl"></ngx-codemirror>
<button mat-raised-button color="primary" (click)="parse()">Parse</button>
</div>
<button *ngIf="results.length !== 0" mat-raised-button color="primary" (click)="clearResults()">Enter New Points</button>

<!-- Parsed -->
<mat-list>
<mat-card *ngFor="let r of results">
<mat-card-title>
<span *ngFor="let t of r.tokens">
<a *ngIf="t.token == 'Delimiter'" title="{{t.token}}" style="color:red"
(mouseover)="onHover(t)">{{t.value}}</a>
<a *ngIf="t.token == 'Identifier'" title="{{t.token}}" style="color:blue"
(mouseover)="onHover(t)">{{t.value}}</a>
<a *ngIf="t.token == 'Constant'" title="{{t.token}}" style="color:green"
(mouseover)="onHover(t)">{{t.value}}</a>
<a *ngIf="t.token !== 'Delimiter' && t.token !== 'Identifier' && t.token !== 'Constant'" title="{{t.token}}"
style="color: purple" (mouseover)="onHover(t)">{{t.value}}</a>
<span title="{{t.token}}" [ngStyle]="{'background-color': color_by_type[type_by_id[t.id]]}"
style="color: white; margin: 0rem 0.1rem; text-align: center;" (mouseover)="onHover(t)">{{t.value}}
</span>
</span>
</mat-card-title>
<mat-card-subtitle *ngIf="r._errors">
Expand All @@ -27,6 +26,7 @@
</mat-list>
</div>

<!-- Parser -->
<div class="parser">
<div id="blocklyDiv"></div>
<xml id="toolbox" style="display: none">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class PointlabelParserComponent implements OnInit {
// program: IProgram;
pointLabelsFormControl: FormControl = new FormControl('[]'); // graph as in UI
results: TokenizePointLabel[] = [];
parser: any = [];
codeMirrorOptions: any = {
// theme: 'material',
mode: 'application/ld+json',
Expand All @@ -43,12 +44,19 @@ export class PointlabelParserComponent implements OnInit {
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
autoCloseBrackets: true,
matchBrackets: true,
lint: true
lint: true,
fontSize: 30
};

constructor(private PointlabelParserService: PointlabelParserService,) {
type_by_id: {[id: string]: string} = {}
color_by_type: {[type: string]: string} = {
"substring_n": "#a55b80",
"string-url": "#5ba5a5",
"rest": "#a55b5b",
"string-token": "#a5a55b",
}

constructor(private PointlabelParserService: PointlabelParserService,) {}

ngOnInit(): void {
this.workspace = Blockly.inject('blocklyDiv', {
toolbox: document.getElementById('toolbox'),
Expand All @@ -61,8 +69,17 @@ export class PointlabelParserComponent implements OnInit {
const pointLabels: string | null = localStorage.getItem('pointLabels')
if (pointLabels) this.pointLabelsFormControl.setValue(JSON.parse(pointLabels))

this.workspace.addChangeListener(() => {
const state = Blockly.serialization.workspaces.save(this.workspace);
this.parser = this.block_to_json(state.blocks.blocks[0])
})
}

clearResults(){
this.results = [];
}


file: any;
fileChanged(e: any) {
this.file = e.target.files[0];
Expand Down Expand Up @@ -97,29 +114,28 @@ export class PointlabelParserComponent implements OnInit {
});
}
fileReader.readAsText(this.file);



}


onHover(token: Token) {
this.workspace.highlightBlock(token.id)
}

block_to_json(block: any): any {
block_to_json(block: any, external=false): any {
const res: any = {
uiParser: external? undefined: block.type,
parser: block.type.split("-")[0],
args: { id: block.id }
}
this.type_by_id[block.id] = block.type;

// set non nesting args
Object.assign(res["args"], block.fields)

// set nesting args
if (block.inputs) {
const parers = Object.keys(block.inputs).reduce((acc, key) => {
acc[key] = this.block_list_to_json(block.inputs[key].block)
acc[key] = this.block_list_to_json(block.inputs[key].block, external)
return acc
}, {} as any)
Object.assign(res["args"], parers)
Expand All @@ -128,10 +144,10 @@ export class PointlabelParserComponent implements OnInit {
return res
}

block_list_to_json(block: any): any {
block_list_to_json(block: any, external=false): any {
let res: any = []
do {
res = [...res, this.block_to_json(block)]
res = [...res, this.block_to_json(block, external)]
block = block.next?.block;
} while (block);

Expand All @@ -143,11 +159,12 @@ export class PointlabelParserComponent implements OnInit {
localStorage.setItem('state', JSON.stringify(state))
localStorage.setItem('pointLabels', JSON.stringify(this.pointLabelsFormControl.value))

const parser = this.block_to_json(state.blocks.blocks[0])
this.type_by_id = {}
const my_parser = this.block_to_json(state.blocks.blocks[0], true)

this.PointlabelParserService.parse(
JSON.parse(this.pointLabelsFormControl.value),
parser
my_parser
)
.subscribe({
next: (data: TokenizePointLabel[]) => {
Expand All @@ -157,5 +174,4 @@ export class PointlabelParserComponent implements OnInit {
}, // error path
});
}

}

0 comments on commit 849e672

Please sign in to comment.