David Catuhe 6 rokov pred
rodič
commit
c244289601

+ 11 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineAndOperator.ts

@@ -0,0 +1,11 @@
+import { ShaderDefineExpression } from '../shaderDefineExpression';
+
+/** @hidden */
+export class ShaderDefineAndOperator extends ShaderDefineExpression {
+    public leftOperand: ShaderDefineExpression;
+    public rightOperand: ShaderDefineExpression;
+
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return this.leftOperand.isTrue(preprocessors) && this.rightOperand.isTrue(preprocessors);
+    }
+}

+ 7 - 12
src/Engines/Processors/shaderCodeArithmeticTestNode.ts

@@ -1,13 +1,12 @@
-import { ShaderCodeNode } from './shaderCodeNode';
+import { ShaderDefineExpression } from '../shaderDefineExpression';
 
 /** @hidden */
-export class ShaderCodeArithmeticTestNode extends ShaderCodeNode {
-    define: string;
-    operand: string;
-    testValue: string;
-    child: ShaderCodeNode;
+export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+    public constructor(public define: string, public operand: string, public testValue: string) {
+        super();
+    }
 
-    isValid(preprocessors: { [key: string]: string }) {
+    public isTrue(preprocessors: { [key: string]: string }) {
         let value = preprocessors[this.define];
 
         if (value === undefined) {
@@ -24,10 +23,6 @@ export class ShaderCodeArithmeticTestNode extends ShaderCodeNode {
                 break;
         }
 
-        if (condition) {
-            return true;
-        }
-
-        return false;
+        return condition;
     }
 }

+ 19 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator.ts

@@ -0,0 +1,19 @@
+import { ShaderDefineExpression } from "../shaderDefineExpression";
+
+/** @hidden */
+export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+
+    public constructor(public define: string, public not: boolean = false) {
+        super();
+    }
+
+    public isTrue(preprocessors: { [key: string]: string }) {
+        let condition = preprocessors[this.define] !== undefined;
+
+        if (this.not) {
+            condition = !condition;
+        }
+
+        return condition;
+    }
+}

+ 11 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineOrOperator.ts

@@ -0,0 +1,11 @@
+import { ShaderDefineExpression } from '../shaderDefineExpression';
+
+/** @hidden */
+export class ShaderDefineOrOperator extends ShaderDefineExpression {
+    public leftOperand: ShaderDefineExpression;
+    public rightOperand: ShaderDefineExpression;
+
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return this.leftOperand.isTrue(preprocessors) || this.rightOperand.isTrue(preprocessors);
+    }
+}

+ 6 - 0
src/Engines/Processors/Expressions/shaderDefineExpression.ts

@@ -0,0 +1,6 @@
+/** @hidden */
+export class ShaderDefineExpression {
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return true;
+    }
+}

+ 1 - 1
src/Engines/Processors/index.ts

@@ -1,4 +1,4 @@
 export * from "./shaderCodeNode";
-export * from "./shaderCodeArithmeticTestNode";
+export * from "./Expressions/Operators/shaderDefineArithmeticOperator";
 export * from "./shaderCodeCursor";
 export * from "./shaderProcessor";

+ 7 - 6
src/Engines/Processors/shaderCodeConditionNode.ts

@@ -2,14 +2,15 @@ import { ShaderCodeNode } from './shaderCodeNode';
 
 /** @hidden */
 export class ShaderCodeConditionNode extends ShaderCodeNode {
-    if: ShaderCodeNode;
-    else: ShaderCodeNode;
-
     process(preprocessors: { [key: string]: string }) {
-        if (this.if.isValid(preprocessors)) {
-            return this.if.process(preprocessors);
+        for (var index = 0; index < this.children.length; index++) {
+            let node = this.children[index];
+
+            if (node.isValid(preprocessors)) {
+                return node.process(preprocessors);
+            }
         }
 
-        return this.else.process(preprocessors);
+        return "";
     }
 }

+ 2 - 6
src/Engines/Processors/shaderCodeCursor.ts

@@ -1,17 +1,13 @@
-import { ShaderCodeNode } from './shaderCodeNode';
-
 /** @hidden */
 export class ShaderCodeCursor {
     lines: string[];
     lineIndex: number;
-    currentNode?: ShaderCodeNode;
-    parentNode?: ShaderCodeNode;
 
     get currentLine(): string {
         return this.lines[this.lineIndex].trim();
     }
 
-    get eof(): boolean {
-        return this.lineIndex >= this.lines.length;
+    get canRead(): boolean {
+        return this.lineIndex < this.lines.length - 1;
     }
 }

+ 0 - 10
src/Engines/Processors/shaderCodeDefineTestNode.ts

@@ -1,10 +0,0 @@
-import { ShaderCodeNode } from './shaderCodeNode';
-
-/** @hidden */
-export class ShaderCodeDefineTestNode extends ShaderCodeNode {
-    define: string;
-
-    isValid(preprocessors: { [key: string]: string }) {
-        return preprocessors[this.define] !== undefined;
-    }
-}

+ 5 - 1
src/Engines/Processors/shaderCodeNode.ts

@@ -9,8 +9,12 @@ export class ShaderCodeNode {
     }
 
     process(preprocessors: { [key: string]: string }): string {
+        if (!this.isValid(preprocessors)) {
+            return "";
+        }
+
         let result = "";
-        if (this.isValid(preprocessors)) {
+        if (this.line) {
             result += this.line + "\r\n";
         }
 

+ 11 - 0
src/Engines/Processors/shaderCodeTestNode.ts

@@ -0,0 +1,11 @@
+import { ShaderCodeNode } from './shaderCodeNode';
+import { ShaderDefineExpression } from './Expressions/shaderDefineExpression';
+
+/** @hidden */
+export class ShaderCodeTestNode extends ShaderCodeNode {
+    public testExpression: ShaderDefineExpression;
+
+    public isValid(preprocessors: { [key: string]: string }) {
+        return this.testExpression.isTrue(preprocessors);
+    }
+}

+ 145 - 59
src/Engines/Processors/shaderProcessor.ts

@@ -1,9 +1,13 @@
 import { Tools } from '../../Misc/tools';
 import { ShaderCodeNode } from './shaderCodeNode';
 import { ShaderCodeCursor } from './shaderCodeCursor';
-import { ShaderCodeArithmeticTestNode } from './shaderCodeArithmeticTestNode';
-import { ShaderCodeDefineTestNode } from './shaderCodeDefineTestNode';
-import { Nullable } from '../../types';
+import { ShaderCodeConditionNode } from './shaderCodeConditionNode';
+import { ShaderCodeTestNode } from './shaderCodeTestNode';
+import { ShaderDefineIsDefinedOperator } from './Expressions/Operators/shaderDefineIsDefinedOperator';
+import { ShaderDefineOrOperator } from './Expressions/Operators/shaderDefineOrOperator';
+import { ShaderDefineAndOperator } from './Expressions/Operators/shaderDefineAndOperator';
+import { ShaderDefineExpression } from './Expressions/shaderDefineExpression';
+import { ShaderDefineArithmeticOperator } from './Expressions/Operators/shaderDefineArithmeticOperator';
 
 /** @hidden */
 interface ProcessingOptions {
@@ -44,76 +48,158 @@ export class ShaderProcessor {
         return source;
     }
 
-    private static _EvaluatePreProcessors(sourceCode: string, preprocessors: { [key: string]: string }): string {
-        const rootNode = new ShaderCodeNode();
-        let cursor = new ShaderCodeCursor();
+    private static _ExtractOperation(expression: string) {
+        let regex = /defined\((.+)\)/;
 
-        cursor.lineIndex = 0;
-        cursor.currentNode = rootNode;
-        cursor.lines = sourceCode.split("\n");
+        let match = regex.exec(expression);
 
-        // Decompose
-        while (!cursor.eof) {
+        if (match && match.length) {
+            return new ShaderDefineIsDefinedOperator(match[1], expression[0] === "!");
+        }
+
+        let indexOperator = expression.indexOf("==");
+        let operator = "";
+
+        if (indexOperator === -1) {
+            indexOperator = expression.indexOf(">");
+
+            if (indexOperator === -1) {
+                indexOperator = expression.indexOf("<");
+
+                if (indexOperator !== -1) {
+                    operator = "<";
+                }
+            } else {
+                operator = ">";
+            }
+        } else {
+            operator = "==";
+        }
+
+        let define = expression.substring(0, indexOperator);
+        let value = expression.substring(indexOperator + operator.length);
+
+        return new ShaderDefineArithmeticOperator(define, operator, value);
+    }
+
+    private static _BuildSubExpression(expression: string): ShaderDefineExpression {
+        let indexOr = expression.indexOf("||");
+        if (indexOr === -1) {
+            let indexAnd = expression.indexOf("&&");
+            if (indexAnd > -1) {
+                let andOperator = new ShaderDefineAndOperator();
+                let leftPart = expression.substring(0, indexAnd);
+                let rightPart = expression.substring(indexAnd);
+
+                andOperator.leftOperand = this._BuildSubExpression(leftPart);
+                andOperator.rightOperand = this._BuildSubExpression(rightPart);
+
+                return andOperator;
+            } else {
+                return this._ExtractOperation(expression);
+            }
+        } else {
+            let orOperator = new ShaderDefineOrOperator();
+            let leftPart = expression.substring(0, indexOr);
+            let rightPart = expression.substring(indexOr);
+
+            orOperator.leftOperand = this._BuildSubExpression(leftPart);
+            orOperator.rightOperand = this._BuildSubExpression(rightPart);
+
+            return orOperator;
+        }
+    }
+
+    private static _BuildExpression(line: string, start: number): ShaderCodeTestNode {
+        let node = new ShaderCodeTestNode();
+        let command = line.substring(0, start);
+        let expression = line.substring(start).trim();
+
+        if (command === "#ifdef") {
+            node.testExpression = new ShaderDefineIsDefinedOperator(expression);
+        } else if (command === "#ifndef") {
+            node.testExpression = new ShaderDefineIsDefinedOperator(expression, true);
+        } else {
+            node.testExpression = this._BuildSubExpression(expression);
+        }
+
+        return node;
+    }
+
+    private static _MoveCursorWithinIf(cursor: ShaderCodeCursor, rootNode: ShaderCodeConditionNode, ifNode: ShaderCodeNode) {
+        let line = cursor.currentLine;
+        while (this._MoveCursor(cursor, ifNode)) {
+            line = cursor.currentLine;
+            let first5 = line.substring(0, 5).toLowerCase();
+
+            if (first5 === "#else") {
+                let elseNode = new ShaderCodeNode();
+                rootNode.children.push(ifNode);
+                this._MoveCursor(cursor, elseNode);
+                return;
+            } else if (first5 === "#elif") {
+                console.log(line);
+                let elifNode = this._BuildExpression(line, 5);
+
+                rootNode.children.push(elifNode);
+                ifNode = elifNode;
+            }
+        }
+    }
+
+    private static _MoveCursor(cursor: ShaderCodeCursor, rootNode: ShaderCodeNode): boolean {
+        while (cursor.canRead) {
+            cursor.lineIndex++;
             let line = cursor.currentLine;
             if (line[0] === "#" && line[1] !== "d") {
                 let first6 = line.substring(0, 6).toLowerCase();
+                let first5 = line.substring(0, 5).toLowerCase();
                 if (first6 === "#ifdef") {
-                    let newNode = new ShaderCodeDefineTestNode();
-                    newNode.define = line.substring(6).trim();
-                    newNode.parent = cursor.parentNode;
-                    newNode.child = new ShaderCodeNode();
-
-                    cursor.parentNode = newNode;
-                    if (cursor.currentNode) {
-                        cursor.currentNode.next = newNode;
-                    }
-                    cursor.currentNode = newNode.child;
-                } else if (line.substring(0, 5).toLowerCase() === "#else") {
-                    let ifNode = cursor.parentNode as ShaderCodeDefineTestNode;
-                    cursor.parentNode = cursor.parentNode!.parent;
-
-                    let newNode = new ShaderCodeDefineTestNode();
-                    newNode.define = ifNode.define;
-                    newNode.not = true;
-                    newNode.parent = cursor.parentNode;
-                    newNode.child = new ShaderCodeNode();
-
-                    cursor.parentNode = newNode;
-                    if (cursor.currentNode) {
-                        cursor.currentNode.next = newNode;
-                    }
-                    cursor.currentNode = newNode.child;
-                    cursor.currentNode = cursor.parentNode;
-                    cursor.parentNode = cursor.parentNode!.parent;
+                    let newRootNode = new ShaderCodeConditionNode();
+                    rootNode.children.push(newRootNode);
+
+                    let ifNode = this._BuildExpression(line, 6);
+                    newRootNode.children.push(ifNode);
+                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                } else if (first5 === "#else") {
+                    return true;
+                } else if (first5 === "#elif") {
+                    return true;
                 } else if (first6 === "#endif") {
+                    return false;
                 } else if (line.substring(0, 3).toLowerCase() === "#if") {
-                    let newNode = new ShaderCodeArithmeticTestNode();
-                    let regex = /(.+)(.)(.+)/;
-                    let matches = regex.exec(line.substring(3).trim())!;
-                    newNode.define = matches[1];
-                    newNode.operand = matches[2];
-                    newNode.testValue = matches[3];
-                    newNode.parent = cursor.parentNode;
-                    newNode.child = new ShaderCodeNode();
-
-                    cursor.parentNode = newNode;
-                    if (cursor.currentNode) {
-                        cursor.currentNode.next = newNode;
-                    }
-                    cursor.currentNode = newNode.child;
+                    let newRootNode = new ShaderCodeConditionNode();
+                    let ifNode = this._BuildExpression(line, 3);
+                    rootNode.children.push(newRootNode);
+
+                    newRootNode.children.push(ifNode);
+                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                } else if (line.substring(0, 7).toLowerCase() === "#ifndef") {
+                    let newRootNode = new ShaderCodeConditionNode();
+                    rootNode.children.push(newRootNode);
+
+                    let ifNode = this._BuildExpression(line, 7);
+                    newRootNode.children.push(ifNode);
+                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
                 }
             } else {
                 let newNode = new ShaderCodeNode();
                 newNode.line = line;
-
-                if (cursor.currentNode) {
-                    cursor.currentNode.next = newNode;
-                }
-                cursor.currentNode = newNode;
+                rootNode.children.push(newNode);
             }
-
-            cursor.lineIndex++;
         }
+        return false;
+    }
+
+    private static _EvaluatePreProcessors(sourceCode: string, preprocessors: { [key: string]: string }): string {
+        const rootNode = new ShaderCodeNode();
+        let cursor = new ShaderCodeCursor();
+
+        cursor.lineIndex = -1;
+        cursor.lines = sourceCode.split("\n");
+
+        // Decompose
+        this._MoveCursor(cursor, rootNode);
 
         // Recompose
         return rootNode.process(preprocessors);