Commit 053b05ac authored by Leon Arnott's avatar Leon Arnott
Browse files

Altered the compiler so that custom macros are parsed better, eliminating a syntax highlighter bug.

This removes a kludge necessary to slice out the trailing : in custom macro calls, which was formerly left as a text token.
parent 86c8851202fa
window.storyFormat({"name":"Harlowe","version":"3.2.0","author":"Leon Arnott","description":"The default story format for Twine 2. Consult its <a href='https://twine2.neocities.org/' target='_blank' rel='noopener noreferrer'>documentation</a>.","image":"icon.svg","url":"http://twinery.org/","license":"Zlib","proofing":false,"source":"","setup":""});
\ No newline at end of file
window.storyFormat({"name":"Harlowe","version":"3.2.0","author":"Leon Arnott","description":"The default story format for Twine 2. Now with an editor toolbar! Consult its <a href='https://twine2.neocities.org/' target='_blank' rel='noopener noreferrer'>documentation</a>.","image":"icon.svg","url":"http://twinery.org/","license":"Zlib","proofing":false,"source":"","setup":""});
\ No newline at end of file
......@@ -376,6 +376,11 @@
existant Harlowe macros.
*/
case "macroName": {
const firstGlyph = currentBranch[i].text[0];
if (firstGlyph === "_" || firstGlyph === "$") {
name += " harlowe-3-customMacro harlowe-3-" + (firstGlyph === "_" ? "tempV" : "v") + "ariable";
break;
}
const macroName = insensitiveName(currentBranch[i].text.slice(0,-1));
if (!validMacros.hasOwnProperty(macroName)) {
name += " harlowe-3-error";
......
......@@ -147,6 +147,9 @@
if (name === undefined) {
return `This macro call is incomplete or erroneously written. Macro calls should consist of \`(\`, the name (which is case-insensitive and dash-insensitive), \`:\`, zero or more expressions separated by commas, then \`)\`, in that order.`;
}
if (name[0] === "_" || name[0] === "$") {
return `This is a <b>call to a custom macro stored in the ${name} variable</b>. Custom macros are created with the \`(macro:)\` macro, and must be stored in variables in order to be used.`;
}
const defs = ShortDefs.Macro[insensitiveName(name)];
if (!defs) {
return `This is a call to a nonexistent or misspelled macro. This will cause an error.`;
......
......@@ -471,9 +471,15 @@
}),
},
variable: { fn: textTokenFn("name") },
variable: {
cannotFollow: ['macroFront'],
fn: textTokenFn("name")
},
tempVariable: { fn: textTokenFn("name") },
tempVariable: {
cannotFollow: ['macroFront'],
fn: textTokenFn("name")
},
}), {
/*
Plain unappended hooks are allowed in expression position as well as
......
......@@ -359,6 +359,8 @@
#coding 2
*/
variable = "\\$(" + validPropertyName + ")",
tempVariable = "_(" + validPropertyName + ")",
property = "'s" + mws + "(" + validPropertyName + ")",
......@@ -392,10 +394,10 @@
belongingItProperty = "(" + validPropertyName + ")" + mws + "of" + mws + "it" + wb,
belongingItOperator = "of" + wb + mws + "it" + wb,
macro = {
opener: "\\(",
name: "(" + either(anyLetter + "+", variable) + "):" + notBefore('\\/'),
name: "(" + either("\\$", "_") + "?" + anyLetter + "+):" + notBefore('\\/'),
closer: "\\)",
},
......@@ -412,7 +414,6 @@
hookTagFront = "\\|(" + anyLetter + "+)(>|\\))",
hookTagBack = "(<|\\()(" + anyLetter + "+)\\|",
tempVariable = "_(" + validPropertyName + ")" + wb,
number = '\\b(\\d+(?:\\.\\d+)?(?:[eE][+\\-]?\\d+)?)' + notBefore("m?s") + wb
;
......
......@@ -776,13 +776,18 @@ define(['utils'], ({impossible}) => {
The first child token in a macro is always the method name.
*/
const macroNameToken = token.children[0];
const variableCall = macroNameToken.type.endsWith("ariable");
const variableCall = macroNameToken.text[0] === "$" || macroNameToken.text[0] === "_";
if(macroNameToken.type !== "macroName" && !variableCall) {
impossible('Compiler.compile', 'macro token had no macroName child token');
}
midString = 'Macros.run' + (variableCall ? 'Custom' : '') + '('
+ (variableCall
? compile(macroNameToken)
/*
Transmute the macro name, which contains a variable, into a VarRef.
*/
? "VarRef" + dotCreate + (macroNameToken.text[0] === "_" ? "section.stackTop.tempV" : "State.v") + "ariables,"
+ stringify(macroNameToken.text.trim().slice(1,-1))
+ ").get()"
: '"' + token.name + '"'
)
/*
......@@ -802,15 +807,7 @@ define(['utils'], ({impossible}) => {
(That, of course, being the comma - (macro: 1,2,3) vs [1,2,3].)
This is currently true, but it is nonetheless a fairly bold assumption.
*/
+ compile(token.children.slice(
1
/*
There's an #awkward issue here: when lexing a custom macro, the variable is consumed,
but the trailing ":" isn't – it simply becomes loose text. So, that token (which is the
first token after this one) must be sliced off.
*/
+ variableCall
),
+ compile(token.children.slice(1),
/*
To allow destructuring patterns to work, macros in destructuring position should
compile all of their contained VarRefs to TypedVars.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment