Skip to content

Commit

Permalink
feat: better expression function parsing and other improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Mar 18, 2022
1 parent f240b7e commit 188b88a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
1╭─ tag a = function (x) { console.log("y") } b
│ │ │ │ │ ╰─ attrName
│ │ │ │ ╰─ attrValue.value "function (x) { console.log(\"y\") }"
│ │ │ ╰─ attrValue "= function (x) { console.log(\"y\") }"
│ │ ╰─ attrName
╰─ ╰─ tagName "tag"
2╭─ tag a = (x) => { console.log("y") } b
│ │ │ │ │ ╰─ attrName
│ │ │ │ ╰─ attrValue.value "(x) => { console.log(\"y\") }"
│ │ │ ╰─ attrValue "= (x) => { console.log(\"y\") }"
│ │ ╰─ attrName
│ ├─ closeTag(tag)
│ ├─ openTagEnd(tag)
╰─ ╰─ tagName "tag"
3╭─ tag a = x => { console.log("y") } b
│ │ │ │ │ ╰─ attrName
│ │ │ │ ╰─ attrValue.value "x => { console.log(\"y\") }"
│ │ │ ╰─ attrValue "= x => { console.log(\"y\") }"
│ │ ╰─ attrName
│ ├─ closeTag(tag)
│ ├─ openTagEnd(tag)
╰─ ╰─ tagName "tag"
4╭─ tag a = async x => { console.log("y") } b
│ │ │ │ │ ╰─ attrName
│ │ │ │ ╰─ attrValue.value "async x => { console.log(\"y\") }"
│ │ │ ╰─ attrValue "= async x => { console.log(\"y\") }"
│ │ ╰─ attrName
│ ├─ closeTag(tag)
│ ├─ openTagEnd(tag)
╰─ ╰─ tagName "tag"
5╭─ tag a = async function (x) { console.log("y") } b
│ │ │ │ │ │├─ closeTag(tag)
│ │ │ │ │ │╰─ openTagEnd(tag)
│ │ │ │ │ ╰─ attrName
│ │ │ │ ╰─ attrValue.value "async function (x) { console.log(\"y\") }"
│ │ │ ╰─ attrValue "= async function (x) { console.log(\"y\") }"
│ │ ╰─ attrName
│ ├─ closeTag(tag)
│ ├─ openTagEnd(tag)
╰─ ╰─ tagName "tag"
5 changes: 5 additions & 0 deletions src/__tests__/fixtures/attr-complex-functions/input.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tag a = function (x) { console.log("y") } b
tag a = (x) => { console.log("y") } b
tag a = x => { console.log("y") } b
tag a = async x => { console.log("y") } b
tag a = async function (x) { console.log("y") } b
83 changes: 6 additions & 77 deletions src/states/EXPRESSION.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,65 +223,12 @@ export const EXPRESSION: StateDefinition<ExpressionMeta> = {
};

function buildOperatorPattern(isConcise: boolean) {
const unary = ["typeof", "new", "void"];
const operators = [
//Multiplicative Operators
"*",
"/",
"%",

//Additive Operators
"+",
"-",

//Bitwise Shift Operators
"<<",
">>",
">>>",

//Relational Operators
"<",
"<=",
">=",

// Readable Operators
// NOTE: These become reserved words and cannot be used as attribute names
"instanceof",
"in",

// Equality Operators
"==",
"!=",
"===",
"!==",

// Binary Bitwise Operators
"&",
"^",
"|",

// Binary Logical Operators
"&&",
"||",

// Ternary Operator
"?",
":",

// Special
// In concise mode we can support >, and in html mode we can support [
isConcise ? ">" : "[",
];
const lookAheadPattern = `\\s*(${operators
.sort(byLength)
.map(escapeOperator)
.join("|")})\\s*(?!-)`;
const lookBehindPattern = `(?<=[^-+](?:${operators
.concat(unary)
.sort(byLength)
.map(escapeOperator)
.join("|")}))`;

const binary = `[*%<&^|?:]|=[=<>]|/[^*/>]|\\.(?=\\s)|\\bin(?:stanceof)(?=\\s+[^=/,;:>])`;
const unary = `!|a(?:sync|wait)|class|function|new|typeof|void`;
const lookAheadPattern = `\\s*(?:${binary}|\\+|${
isConcise ? "-[^-]" : "-"
}${`|>${isConcise ? "" : "[>=]"}`})\\s*|\\s+(?=[${isConcise ? "" : "["}{(])`;
const lookBehindPattern = `(?<=${unary}|${binary}|[^-]-|[^+]\\+)`;
return new RegExp(`${lookAheadPattern}|${lookBehindPattern}`, "y");
}

Expand Down Expand Up @@ -319,21 +266,3 @@ function canCharCodeBeFollowedByDivision(code: number) {
code === CODE.CLOSE_CURLY_BRACE
);
}

function escapeOperator(str: string) {
if (/^[A-Z]+$/i.test(str)) {
return "\\b" + escapeNonAlphaNumeric(str) + "(?=\\s+[^=/,;:>])";
}
if (str === "/") {
return "\\/(?:\\b|\\s)"; //make sure this isn't a comment
}
return escapeNonAlphaNumeric(str);
}

function escapeNonAlphaNumeric(str: string) {
return str.replace(/([^\w\d])/g, "\\$1");
}

function byLength(a: string, b: string) {
return b.length - a.length;
}

0 comments on commit 188b88a

Please sign in to comment.