From 209e696d9210e67c5942bffcb5252d7ae897559b Mon Sep 17 00:00:00 2001 From: dabbler0 Date: Fri, 18 Mar 2016 18:30:39 -0400 Subject: [PATCH 01/60] Add text paste method --- src/controller.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/controller.coffee b/src/controller.coffee index 0060c184..7b0c9d55 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -865,6 +865,11 @@ class CapturePoint constructor: (rememberedSockets) -> @rememberedSockets = rememberedSockets.map (x) -> x.clone() +Editor::setFocusedText = (value) -> + if @getCursor().type is 'socket' + @populateSocket @getCursor(), value + @redrawMain() + # BASIC BLOCK MOVE SUPPORT # ================================ From 3ac4938d46ea1b09e9adcc38f88ec3bd5d717e64 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Thu, 2 Jun 2016 07:06:07 -0400 Subject: [PATCH 02/60] python mode dropdown menu and block color (WIP) --- src/languages/python.coffee | 143 +++++++++++++++++++++++++++--------- src/treewalk.coffee | 8 +- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index 65b33b2d..7f508b7b 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -10,10 +10,23 @@ treewalk = require '../treewalk.coffee' skulpt = require '../../vendor/skulpt' +PYTHON_KEYWORDS = ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield'] + +PYTHON_BUILTIN = ['type', 'object', 'hashCount', 'none', 'NotImplemented', 'pyCheckArgs', 'pyCheckType', 'checkSequence', 'checkIterable', 'checkCallable', 'checkNumber', 'checkComplex', 'checkInt', 'checkFloat', 'checkString', 'checkClass', 'checkBool', 'checkNone', 'checkFunction', 'func', 'range', 'asnum$', 'assk$', 'asnum$nofloat', 'round', 'len', 'min', 'max', 'any', 'all', 'sum', 'zip', 'abs', 'ord', 'chr', 'int2str_', 'hex', 'oct', 'bin', 'dir', 'repr', 'open', 'isinstance', 'hash', 'getattr', 'setattr', 'raw_input', 'input', 'jseval', 'jsmillis', 'superbi', 'eval_', 'map', 'reduce', 'filter', 'hasattr', 'pow', 'quit', 'issubclass', 'globals', 'divmod', 'format', 'bytearray', 'callable', 'delattr', 'execfile', 'frozenset', 'help', 'iter', 'locals', 'memoryview', 'next_', 'property', 'reload', 'reversed', 'unichr', 'vars', 'xrange', 'apply_', 'buffer', 'coerce', 'intern', 'BaseException', 'Exception', 'StandardError', 'AssertionError', 'AttributeError', 'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'NameError', 'UnboundLocalError', 'OverflowError', 'ParseError', 'RuntimeError', 'SuspensionError', 'SystemExit', 'SyntaxError', 'TokenError', 'TypeError', 'ValueError', 'ZeroDivisionError', 'TimeLimitError', 'IOError', 'NotImplementedError', 'NegativePowerError', 'ExternalError', 'OperationError', 'SystemError', 'method', 'seqtype', 'list', 'interned', 'str', 'tuple', 'dict', 'numtype', 'biginteger', 'int_', 'bool', 'float_', 'nmber', 'lng', 'complex', 'slice', 'slice$start', 'slice$stop', 'slice$step', 'set', 'print', 'module', 'structseq_types', 'make_structseq', 'generator', 'makeGenerator', 'file', 'enumerate', '__import__', 'timSort', 'listSlice', 'sorted'] + +# TODO: how do we add keywords without hardcoding? +PYTHON_RANDOM = ['seed', 'random', 'randint', 'randrange', 'uniform', 'triangular', 'gauss', 'normalvariate', 'lognormvariate', 'expovariate', 'choice', 'shuffle', 'sample'] + +PYTHON_MATH = ['pi', 'e', 'fabs', 'asin', 'acos', 'atan', 'atan2', 'sin', 'cos', 'tan', 'asinh', 'acosh', 'atanh', 'sinh', 'cosh', 'tanh', 'ceil', 'copysign', 'floor', 'sqrt', 'trunc', 'log', 'log10', 'isnan', 'exp', 'pow', 'radians', 'degrees', 'hypot', 'factorial'] + +ES_KEYWORDS = ['init', 'setTempo', 'finish', 'fitMedia', 'makeBeat', 'setEffect', 'selectRandomFile', 'insertMedia', 'analyze', 'analyzeForTime', 'analyzeTrack', 'analyzeTrackForTime', 'dur', 'importImage', 'importFile', 'insertMediaSection', 'makeBeatSlice', 'readInput', 'replaceListElement', 'replaceString', 'reverseList', 'reverseString', 'rhythmEffects', 'shuffleList', 'shuffleString'] + +PYTHON_KEYWORDS = PYTHON_KEYWORDS.concat(PYTHON_BUILTIN, PYTHON_RANDOM, PYTHON_MATH, ES_KEYWORDS) +PYTHON_KEYWORDS = PYTHON_KEYWORDS.filter((v, i) -> return PYTHON_KEYWORDS.indexOf(v) == i) # remove duplicates + # PARSER SECTION parse = (context, text) -> - result = transform skulpt.parser.parse('file.py', text), text.split('\n') - console.log result + result = transform skulpt.parser.parse('file.py', text, context), text.split('\n') return result getBounds = (node, lines) -> @@ -36,12 +49,57 @@ getBounds = (node, lines) -> } return bounds +getFunctionName = (node) -> + if node.type is 'trailer' + # parent should have a subtree containing T_KEYWORD node + siblingNode = node.parent?.children[0]?.children?[0] + else if node.type is 'power' and node.children.some((n) -> n.type is 'trailer') + siblingNode = node.children[0].children?[0] + + if siblingNode?.type is 'T_KEYWORD' + return siblingNode.meta.value + + if node.parent? then getFunctionName(node.parent) + +getArgNum = (node) -> + if node.parent? + if node.type is 'argument' + # parent should have an arglist node containing arg, T_COMMA, arg, T_COMMA, etc. + index = node.parent.children.indexOf(node) + if index > -1 + return Math.floor(index/2) # to skip commas (even indices) + else if node.parent.children.length > 1 + return null + else + return getArgNum(node.parent) + +getDropdown = (opts, node) -> + argNum = getArgNum(node) + funcName = getFunctionName(node) + + if argNum? and funcName? + return opts.functions[funcName]?.dropdown?[argNum] ? null + +getColor = (opts, node) -> + if getArgNum(node) is null + return opts.functions[getFunctionName(node)]?.color ? null + transform = (node, lines, parent = null) -> + type = skulpt.tables.ParseTables.number2symbol[node.type] ? skulpt.Tokenizer.tokenNames[node.type] ? node.type + + if type is 'T_NAME' + if node.value in PYTHON_KEYWORDS + type = 'T_KEYWORD' + result = { - type: skulpt.tables.ParseTables.number2symbol[node.type] ? skulpt.Tokenizer.tokenNames[node.type] ? node.type + type: type bounds: getBounds(node, lines) parent: parent + meta: { + value: node.value ? null + } # language-specific meta-data } + result.children = if node.children? node.children.map ((x) -> transform(x, lines, result)) else [] @@ -49,39 +107,52 @@ transform = (node, lines, parent = null) -> return result # CONFIG SECTION -INDENTS = ['suite'] -SKIPS = [ - 'file_input' - 'parameters' - 'compound_stmt' - 'small_stmt' - 'simple_stmt' - 'trailer' - 'arglist' - 'testlist_comp' -] -PARENS = [ - 'stmt' -] -SOCKET_TOKENS = [ - 'T_NAME', 'T_NUMBER', 'T_STRING' -] -COLORS_FORWARD = { - 'funcdef': 'control' - 'for_stmt': 'control' - 'while_stmt': 'control' - 'if_stmt': 'control' - 'import_stmt': 'command' - 'print_stmt': 'command' - 'expr_stmt': 'command' - 'testlist': 'value' - 'test': 'value' - 'expr': 'value' -} -COLORS_BACKWARD = {} - config = { - INDENTS, SKIPS, PARENS, SOCKET_TOKENS, COLORS_FORWARD, COLORS_BACKWARD, + INDENTS: ['suite'] + SKIPS: [ + 'file_input' + 'parameters' + 'compound_stmt' + 'small_stmt' + 'simple_stmt' + 'trailer' + 'arglist' + 'testlist_comp' + 'with_item' + 'listmaker' + 'list_for' + ] + PARENS : [ + 'stmt' + ] + SOCKET_TOKENS : [ + 'T_NAME', 'T_NUMBER', 'T_STRING' + ] + COLORS_FORWARD : { + 'term': 'value' + 'funcdef': 'control' + 'for_stmt': 'control' + 'while_stmt': 'control' + 'with_stmt': 'control' + 'if_stmt': 'control' + 'try_stmt': 'control' + 'import_stmt': 'command' + 'print_stmt': 'command' + 'expr_stmt': 'command' + 'return_stmt': 'return' + 'testlist': 'value' + 'comparison': 'value' + 'test': 'value' + 'expr': 'value' + } + COLORS_BACKWARD : {} + BLOCK_TOKENS: [], PLAIN_SOCKETS: [], VALUE_TYPES: [], BLOCK_TYPES: [] + DROPDOWN_CB: getDropdown + COLOR_CB: getColor } -module.exports = parser.wrapParser treewalk.createTreewalkParser parse, config +result = treewalk.createTreewalkParser parse, config +result.canParse = (node) -> + return ('stmt' in node.classes) or + ('small_stmt' in node.classes) +module.exports = parser.wrapParser result \ No newline at end of file diff --git a/src/treewalk.coffee b/src/treewalk.coffee index f59227e9..3d30d36e 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -36,7 +36,6 @@ exports.createTreewalkParser = (parse, config, root) -> max = val return best - det: (rule) -> if rule in config.INDENTS then return 'indent' else if rule in config.SKIPS then return 'skip' @@ -90,11 +89,12 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth classes: rules + dropdown: null @addBlock bounds: bounds depth: depth + 1 - color: @getColor rules + color: config.COLOR_CB(@opts, node) ? @getColor rules classes: rules.concat(if context? then @getDropType(context) else 'any-drop') parseContext: (if wrap? then wrap.type else rules[0]) @@ -125,11 +125,12 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth classes: rules + dropdown: null @addBlock bounds: bounds depth: depth + 1 - color: @getColor rules + color: config.COLOR_CB(@opts, node) ? @getColor rules classes: rules.concat(if context? then @getDropType(context) else 'any-drop') parseContext: (if wrap? then wrap.type else rules[0]) @@ -169,6 +170,7 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: node.bounds depth: depth classes: rules + dropdown: config.DROPDOWN_CB?(@opts, node) ? null TreewalkParser.drop = (block, context, pred) -> if context.type is 'socket' From 577f63468b7ca4f28beb7e1c42ed2849ef7223df Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Mon, 6 Jun 2016 02:07:42 -0400 Subject: [PATCH 03/60] function names in modeOptions detected as block name, python mode demo --- example/example-python.coffee | 207 ++++++++++++++++++++++++++++++++++ example/example-python.html | 74 ++++++++++++ src/languages/python.coffee | 17 +-- src/treewalk.coffee | 8 +- 4 files changed, 292 insertions(+), 14 deletions(-) create mode 100644 example/example-python.coffee create mode 100644 example/example-python.html diff --git a/example/example-python.coffee b/example/example-python.coffee new file mode 100644 index 00000000..cfd0f2a8 --- /dev/null +++ b/example/example-python.coffee @@ -0,0 +1,207 @@ +# Droplet config editor +window.expressionContext = { + prefix: 'a = ' +} + +window.dropletConfig = ace.edit 'droplet-config' +dropletConfig.setTheme 'ace/theme/chrome' +dropletConfig.getSession().setMode 'ace/mode/python' + +# dropletConfig.setValue localStorage.getItem('config') ? ''' +dropletConfig.setValue ''' + ({ + "mode": "python", + "modeOptions": { + "functions": { + "myFunction": { + "color": "purple", + "dropdown": [['foo', 'bar'], ['baz', 'qux']] + }, + 'colorTest': { + 'color': 'yellow', + 'dropdown': [null, ['1', '2', '3']] + }, + 'nestedFn': { + 'color': 'pink' + } + } + }, + "palette": [ + { + 'name': 'Input/output', + 'color': 'blue', + 'blocks': [ + { + 'block': "print 'hello'", + }, + { + 'block': "input('Enter a number')", + 'wrapperContext': expressionContext + }, + { + 'block': "raw_input('Enter a string')", + 'wrapperContext': expressionContext + }, + { + 'block': 'myFunction(drop, down)' + }, + { + 'block': 'colorTest(0, 1)' + }, + { + 'block': 'nestedFn(nestedFn(nestedFn))' + } + ] + }, + { + 'name': 'Control flow', + 'color': 'control', + 'blocks': [ + { + 'block': "for i in range(0, 10):\\n print 'hello'", + }, + { + 'block': "if a == b:\\n print 'hello'", + }, + { + 'block': "while a < b:\\n print 'hello'", + } + ] + }, + { + 'name': 'Methods', + 'color': 'purple', + 'blocks': [ + { + 'block': 'import module' + }, + { + 'block': 'from module import something' + }, + { + 'block': "def myMethod(arg):\\n print 'hello'", + }, + { + 'block': "return 'hello'", + }, + { + 'block': "myMethod(arg)", + 'wrapperContext': expressionContext + }, + ] + }, + { + 'name': 'Variables', + 'color': 'red', + 'blocks': [ + { + 'block': 'a = 1' + } + ] + }, + { + 'name': 'Math', + 'color': 'red', + 'blocks': [ + { + 'block': 'a + b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a - b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a * b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a / b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a % b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a ** b', + 'wrapperContext': expressionContext + } + ] + }, + { + 'name': 'Logic', + 'color': 'teal', + 'blocks': [ + { + 'block': 'a == b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a < b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a > b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a and b', + 'wrapperContext': expressionContext + }, + { + 'block': 'a or b', + 'wrapperContext': expressionContext + } + ] + } + ] + }) +''' + +# Droplet itself +createEditor = (options) -> + $('#droplet-editor').html '' + editor = new droplet.Editor $('#droplet-editor')[0], options + + editor.setEditorState localStorage.getItem('blocks') is 'yes' + editor.aceEditor.getSession().setUseWrapMode true + + # Initialize to starting text + editor.setValue localStorage.getItem('text') ? '' + + editor.on 'change', -> + localStorage.setItem 'text', editor.getValue() + + window.editor = editor + +createEditor eval dropletConfig.getValue() + +$('#toggle').on 'click', -> + editor.toggleBlocks() + localStorage.setItem 'blocks', (if editor.currentlyUsingBlocks then 'yes' else 'no') + +# Stuff for testing convenience +$('#update').on 'click', -> + localStorage.setItem 'config', dropletConfig.getValue() + createEditor eval dropletConfig.getValue() + +configCurrentlyOut = localStorage.getItem('configOut') is 'yes' + +updateConfigDrawerState = -> + if configCurrentlyOut + $('#left-panel').css 'left', '0px' + $('#right-panel').css 'left', '525px' + else + $('#left-panel').css 'left', '-500px' + $('#right-panel').css 'left', '25px' + + editor.resize() + + localStorage.setItem 'configOut', (if configCurrentlyOut then 'yes' else 'no') + +$('#close').on 'click', -> + configCurrentlyOut = not configCurrentlyOut + updateConfigDrawerState() + +updateConfigDrawerState() \ No newline at end of file diff --git a/example/example-python.html b/example/example-python.html new file mode 100644 index 00000000..33babd80 --- /dev/null +++ b/example/example-python.html @@ -0,0 +1,74 @@ + + + Droplet Demo + + + + + +
+
+
+ Update +
+
+
+
+
+
+
+
+
+ Toggle +
+
+
+
+ + + + + + + + + + diff --git a/src/languages/python.coffee b/src/languages/python.coffee index 7f508b7b..fbeac278 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -14,15 +14,8 @@ PYTHON_KEYWORDS = ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', ' PYTHON_BUILTIN = ['type', 'object', 'hashCount', 'none', 'NotImplemented', 'pyCheckArgs', 'pyCheckType', 'checkSequence', 'checkIterable', 'checkCallable', 'checkNumber', 'checkComplex', 'checkInt', 'checkFloat', 'checkString', 'checkClass', 'checkBool', 'checkNone', 'checkFunction', 'func', 'range', 'asnum$', 'assk$', 'asnum$nofloat', 'round', 'len', 'min', 'max', 'any', 'all', 'sum', 'zip', 'abs', 'ord', 'chr', 'int2str_', 'hex', 'oct', 'bin', 'dir', 'repr', 'open', 'isinstance', 'hash', 'getattr', 'setattr', 'raw_input', 'input', 'jseval', 'jsmillis', 'superbi', 'eval_', 'map', 'reduce', 'filter', 'hasattr', 'pow', 'quit', 'issubclass', 'globals', 'divmod', 'format', 'bytearray', 'callable', 'delattr', 'execfile', 'frozenset', 'help', 'iter', 'locals', 'memoryview', 'next_', 'property', 'reload', 'reversed', 'unichr', 'vars', 'xrange', 'apply_', 'buffer', 'coerce', 'intern', 'BaseException', 'Exception', 'StandardError', 'AssertionError', 'AttributeError', 'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'NameError', 'UnboundLocalError', 'OverflowError', 'ParseError', 'RuntimeError', 'SuspensionError', 'SystemExit', 'SyntaxError', 'TokenError', 'TypeError', 'ValueError', 'ZeroDivisionError', 'TimeLimitError', 'IOError', 'NotImplementedError', 'NegativePowerError', 'ExternalError', 'OperationError', 'SystemError', 'method', 'seqtype', 'list', 'interned', 'str', 'tuple', 'dict', 'numtype', 'biginteger', 'int_', 'bool', 'float_', 'nmber', 'lng', 'complex', 'slice', 'slice$start', 'slice$stop', 'slice$step', 'set', 'print', 'module', 'structseq_types', 'make_structseq', 'generator', 'makeGenerator', 'file', 'enumerate', '__import__', 'timSort', 'listSlice', 'sorted'] -# TODO: how do we add keywords without hardcoding? -PYTHON_RANDOM = ['seed', 'random', 'randint', 'randrange', 'uniform', 'triangular', 'gauss', 'normalvariate', 'lognormvariate', 'expovariate', 'choice', 'shuffle', 'sample'] - -PYTHON_MATH = ['pi', 'e', 'fabs', 'asin', 'acos', 'atan', 'atan2', 'sin', 'cos', 'tan', 'asinh', 'acosh', 'atanh', 'sinh', 'cosh', 'tanh', 'ceil', 'copysign', 'floor', 'sqrt', 'trunc', 'log', 'log10', 'isnan', 'exp', 'pow', 'radians', 'degrees', 'hypot', 'factorial'] - -ES_KEYWORDS = ['init', 'setTempo', 'finish', 'fitMedia', 'makeBeat', 'setEffect', 'selectRandomFile', 'insertMedia', 'analyze', 'analyzeForTime', 'analyzeTrack', 'analyzeTrackForTime', 'dur', 'importImage', 'importFile', 'insertMediaSection', 'makeBeatSlice', 'readInput', 'replaceListElement', 'replaceString', 'reverseList', 'reverseString', 'rhythmEffects', 'shuffleList', 'shuffleString'] - -PYTHON_KEYWORDS = PYTHON_KEYWORDS.concat(PYTHON_BUILTIN, PYTHON_RANDOM, PYTHON_MATH, ES_KEYWORDS) -PYTHON_KEYWORDS = PYTHON_KEYWORDS.filter((v, i) -> return PYTHON_KEYWORDS.indexOf(v) == i) # remove duplicates +PYTHON_KEYWORDS = PYTHON_KEYWORDS.concat(PYTHON_BUILTIN) +PYTHON_KEYWORDS = PYTHON_KEYWORDS.filter((v, i) -> return PYTHON_KEYWORDS.indexOf(v) == i) # remove possible duplicates # PARSER SECTION parse = (context, text) -> @@ -56,7 +49,7 @@ getFunctionName = (node) -> else if node.type is 'power' and node.children.some((n) -> n.type is 'trailer') siblingNode = node.children[0].children?[0] - if siblingNode?.type is 'T_KEYWORD' + if siblingNode?.type in ['T_KEYWORD', 'T_NAME'] return siblingNode.meta.value if node.parent? then getFunctionName(node.parent) @@ -78,11 +71,11 @@ getDropdown = (opts, node) -> funcName = getFunctionName(node) if argNum? and funcName? - return opts.functions[funcName]?.dropdown?[argNum] ? null + return opts.functions?[funcName]?.dropdown?[argNum] ? null getColor = (opts, node) -> if getArgNum(node) is null - return opts.functions[getFunctionName(node)]?.color ? null + return opts.functions?[getFunctionName(node)]?.color ? null transform = (node, lines, parent = null) -> type = skulpt.tables.ParseTables.number2symbol[node.type] ? skulpt.Tokenizer.tokenNames[node.type] ? node.type diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 3d30d36e..68071f29 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -43,9 +43,13 @@ exports.createTreewalkParser = (parse, config, root) -> else return 'block' detNode: (node) -> if node.blockified then 'block' else @det(node.type) + detToken: (node) -> if node.type? - if node.type in config.SOCKET_TOKENS then 'socket' else 'none' + if node.type in config.SOCKET_TOKENS + # user-defined function names (in modeOptions) are being excluded + if @opts.functions? and node.meta.value in Object.keys(@opts.functions) then 'none' else 'socket' + else 'none' else 'none' getDropType: (context) -> ({ @@ -165,7 +169,7 @@ exports.createTreewalkParser = (parse, config, root) -> for child in node.children @mark child, prefix, depth + 2, false else if context? and @detNode(context) is 'block' - if @detToken(node) is 'socket' + if @detToken(node) is 'socket' # TODO: it doesn't differentiate between function names and arguments @addSocket bounds: node.bounds depth: depth From 43a49affd0414b7d6e3092bbe2743340b77ce8b8 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Mon, 13 Jun 2016 14:09:32 -0400 Subject: [PATCH 04/60] implement handleButton for extending if/elses --- src/languages/python.coffee | 32 +++++++++++++++++++++++++++++++- src/treewalk.coffee | 3 +++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index fbeac278..e8a3ca42 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -76,7 +76,35 @@ getDropdown = (opts, node) -> getColor = (opts, node) -> if getArgNum(node) is null return opts.functions?[getFunctionName(node)]?.color ? null - + +insertButton = (opts, node) -> + if node.type is 'if_stmt' + return {addButton: true} + else + return null + +handelButton = (text, button, oldBlocks) -> + checkElif = (node) -> + res = 'init' + if node.type is 'if_stmt' + node.children?.forEach((c) -> if c.type is 'T_KEYWORD' then res = c.meta.value) + else + node.children?.forEach((c) -> res = checkElif(c)) + return res + + if button is 'add-button' and 'if_stmt' in oldBlocks.classes + node = parse({}, text).children[0] + elif = checkElif(node) + + if elif is 'if' or elif is 'elif' + text += '''\nelse:\n print \'hi\'''' + else if elif is 'else' + text = text.replace('else:', 'elif a == b:') + text += '''\nelse:\n print \'hi\'''' + + return text + + transform = (node, lines, parent = null) -> type = skulpt.tables.ParseTables.number2symbol[node.type] ? skulpt.Tokenizer.tokenNames[node.type] ? node.type @@ -142,6 +170,8 @@ config = { BLOCK_TOKENS: [], PLAIN_SOCKETS: [], VALUE_TYPES: [], BLOCK_TYPES: [] DROPDOWN_CB: getDropdown COLOR_CB: getColor + BUTTON_CB: insertButton + HANDLE_BUTTON_CB: handelButton } result = treewalk.createTreewalkParser parse, config diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 68071f29..8a342c8f 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -101,6 +101,7 @@ exports.createTreewalkParser = (parse, config, root) -> color: config.COLOR_CB(@opts, node) ? @getColor rules classes: rules.concat(if context? then @getDropType(context) else 'any-drop') parseContext: (if wrap? then wrap.type else rules[0]) + buttons: config.BUTTON_CB(@opts, node) ? null when 'parens' # Parens are assumed to wrap the only child that has children @@ -187,4 +188,6 @@ exports.createTreewalkParser = (parse, config, root) -> # Doesn't yet deal with parens TreewalkParser.parens = (leading, trailing, node, context) -> + TreewalkParser.handleButton = config.HANDLE_BUTTON_CB + return TreewalkParser From 36b8dca62d78f7bee4b3d926781e3f94188d3c39 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 15 Jun 2016 20:17:27 -0400 Subject: [PATCH 05/60] fix text-paste with the hiddenInput value not updating --- src/controller.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controller.coffee b/src/controller.coffee index 7b0c9d55..a66e135f 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -868,6 +868,7 @@ class CapturePoint Editor::setFocusedText = (value) -> if @getCursor().type is 'socket' @populateSocket @getCursor(), value + @hiddenInput.value = value @redrawMain() # BASIC BLOCK MOVE SUPPORT From 705aa625290823feca653f9114c3f12351c8a77a Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 6 Jul 2016 10:20:21 -0400 Subject: [PATCH 06/60] C if/elseif/else amalgamation --- src/languages/c.coffee | 20 ++++++++++++++++++-- src/treewalk.coffee | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 0ace4a16..eb300b60 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -44,6 +44,22 @@ RULES = { 'initializerList': 'skip', 'initDeclaratorList': 'skip', + # Special: nested selection statement. Skip iff we are an if statement + # in the else clause of another if statement. + 'selectionStatement': (node) -> + if node.children[0].data.text is 'if' and + # Check to make sure the parent is an if. Actually, + # our immediate parent is a 'statement'; the logical wrapping + # parent is parent.parent + node.parent.type is 'statement' and + node.parent.parent.type is 'selectionStatement' and + node.parent.parent.children[0].data.text is 'if' and + # This last one will only occur if we are the else clause + node.parent is node.parent.parent.children[6] + return 'skip' + else + return 'block' + # Sockets 'Identifier': 'socket', 'StringLiteral': 'socket', @@ -160,11 +176,11 @@ config.SHOULD_SOCKET = (opts, node) -> return true # Check to see whether the thing we are in is a function - if node.parent?.type is 'specialMethodCall' or getMethodName(node.parent.parent.parent)? and + if (node.parent?.type is 'specialMethodCall' or getMethodName(node.parent.parent.parent)? and # Check to see whether we are the first child node.parent.parent is node.parent.parent.parent.children[0] and node.parent is node.parent.parent.children[0] and - node is node.parent.children[0] and + node is node.parent.children[0]) and # Finally, check to see if our name is a known function name node.data.text of opts.knownFunctions diff --git a/src/treewalk.coffee b/src/treewalk.coffee index aa7b6847..01b641a6 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -43,10 +43,10 @@ exports.createTreewalkParser = (parse, config, root) -> return best applyRule: (rule, node) -> + if rule instanceof Function + rule = rule(node) if 'string' is typeof rule return {type: rule} - else if rule instanceof Function - return rule(node) else return rule From d4e5fcfff0afe1cc0c77d88a9a0b31ba024dc0bb Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 6 Jul 2016 14:09:46 -0400 Subject: [PATCH 07/60] Add pipeline for mutation buttons --- src/languages/c.coffee | 5 +++++ src/treewalk.coffee | 12 ++++++++++++ src/view.coffee | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index eb300b60..c5c1947f 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -9,6 +9,8 @@ antlrHelper = require '../antlr.coffee' {fixQuotedString, looseCUnescape, quoteAndCEscape} = helper +ADD_BUTTON = {addButton: true} + RULES = { # Indents 'compoundStatement': { @@ -57,6 +59,9 @@ RULES = { # This last one will only occur if we are the else clause node.parent is node.parent.parent.children[6] return 'skip' + # Otherwise, if we are an if statement, give us a mutation button + else if node.children[0].data.text is 'if' + return {type: 'block', buttons: ADD_BUTTON} else return 'block' diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 01b641a6..3ad1a22e 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -6,6 +6,8 @@ helper = require './helper.coffee' model = require './model.coffee' parser = require './parser.coffee' +EMPTY_OBJECT = {} + exports.createTreewalkParser = (parse, config, root) -> class TreewalkParser extends parser.Parser constructor: (@text, @opts = {}) -> @@ -19,6 +21,10 @@ exports.createTreewalkParser = (parse, config, root) -> else return false + handleButton: -> + if config.handleButton? + config.handleButton.apply @, arguments + parseComment: (text) -> return config.parseComment text @@ -55,6 +61,11 @@ exports.createTreewalkParser = (parse, config, root) -> return @applyRule(config.RULES[node.type], node).type return 'block' + getButtons: (node) -> + if node.type of config.RULES + return @applyRule(config.RULES[node.type], node).buttons ? EMPTY_OBJECT + return EMPTY_OBJECT + detNode: (node) -> if node.blockified then 'block' else @det(node) getColor: (node, rules) -> @@ -121,6 +132,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node, rules classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) + buttons: @getButtons(node) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) when 'parens' diff --git a/src/view.coffee b/src/view.coffee index b288d5ff..f0dee532 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1854,25 +1854,48 @@ exports.View = class View oldStroke = @path.style.strokeColor if style.grayscale + # Change path color if @path.style.fillColor isnt 'none' @path.style.fillColor = avgColor @path.style.fillColor, 0.5, '#888' if @path.style.strokeColor isnt 'none' @path.style.strokeColor = avgColor @path.style.strokeColor, 0.5, '#888' + # Change button color + if @addButtonPath?.active + if @addButtonPath.style.fillColor isnt 'none' + @addButtonPath.style.fillColor = avgColor @addButtonPath.style.fillColor, 0.5, '#888' + if @addButtonPath.style.strokeColor isnt 'none' + @addButtonPath.style.strokeColor = avgColor @addButtonPath.style.strokeColor, 0.5, '#888' + if style.selected + # Change path color if @path.style.fillColor isnt 'none' @path.style.fillColor = avgColor @path.style.fillColor, 0.7, '#00F' if @path.style.strokeColor isnt 'none' @path.style.strokeColor = avgColor @path.style.strokeColor, 0.7, '#00F' + # Change button color + if @addButtonPath?.active + if @addButtonPath.style.fillColor isnt 'none' + @addButtonPath.style.fillColor = avgColor @addButtonPath.style.fillColor, 0.7, '#00F' + if @addButtonPath.style.strokeColor isnt 'none' + @addButtonPath.style.strokeColor = avgColor @addButtonPath.style.strokeColor, 0.7, '#00F' + @path.setMarkStyle @markStyle @path.update() + @addButtonPath?.update?() # Unset all the things we changed @path.style.fillColor = oldFill @path.style.strokeColor = oldStroke + if @addButtonPath?.active + @addButtonPath.style.fillColor = oldFill + @addButtonPath.style.strokeColor = oldStroke + + # BUttons + return null # ## computeOwnDropArea From d129f157faa632a7f149cbde986584315e4e1d6a Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 6 Jul 2016 14:10:08 -0400 Subject: [PATCH 08/60] Remove extraneous debug --- src/view.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/view.coffee b/src/view.coffee index f0dee532..2a597674 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -2414,8 +2414,6 @@ dedupe = (path) -> ) path = path.filter((x, i) -> - if x.x is 25 - debugger return not draw._collinear(path[(i - 1) %% path.length], x, path[(i + 1) %% path.length]) ) From bfa7674a216820d712f7be9aa00a94962ffdb1fe Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 11:30:26 -0400 Subject: [PATCH 09/60] Add necessary annotation pipeline --- src/controller.coffee | 7 ++++++- src/helper.coffee | 16 ++++++++++++++-- src/languages/c.coffee | 28 ++++++++++++++++++++++++++++ src/model.coffee | 5 +++-- src/parser.coffee | 3 ++- src/treewalk.coffee | 3 +++ 6 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index f0162909..1e49b0c5 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1341,7 +1341,9 @@ hook 'mousedown', 4, (point, event, state) -> str = hitTestResult.stringifyInPlace() if hitTestBlock.addButtonRect? and hitTestBlock.addButtonRect.contains mainPoint + console.log 'ADD BUTTONING!' line = @session.mode.handleButton str, 'add-button', hitTestResult.getReader() + console.log 'NEW LINE IS', line if line?.length >= 0 @populateBlock hitTestResult, line @redrawMain() @@ -2505,7 +2507,10 @@ Editor::populateSocket = (socket, string) -> @spliceIn (new model.List(first, last)), socket.start Editor::populateBlock = (block, string) -> - newBlock = @session.mode.parse(string, wrapAtRoot: false).start.next.container + newBlock = @session.mode.parse(string, { + context: block.parseContext + wrapAtRoot: false + }).start.next.container if newBlock # Find the first token before the block # that will still be around after the diff --git a/src/helper.coffee b/src/helper.coffee index 5b1528f5..4b480425 100644 --- a/src/helper.coffee +++ b/src/helper.coffee @@ -113,13 +113,25 @@ exports.clipLines = (lines, start, end) -> # "'#{lines[start.line][start.column..]}'", # "'#{lines[start.line + 1...end.line].join('\n')}'", # "'#{lines[end.line][...end.column]}'" - return lines[start.line][start.column..] + - lines[start.line + 1...end.line].join('\n') + + return lines[start.line][start.column..] + '\n' + + lines[start.line + 1...end.line].map((x) -> x + '\n').join('') + lines[end.line][...end.column] else #console.log 'clipping', lines[start.line], 'from', start.column + 1, 'to', end.column return lines[start.line][start.column...end.column] +exports.subtractBounds = (a, b) -> + return { + start: { + line: a.start.line - b.line + column: a.start.column - b.column + } + end: { + line: a.start.line - b.line + column: a.start.column - b.column + } + } + exports.getFontHeight = (family, size) -> metrics = fontMetrics family, size return metrics.descent - metrics.prettytop diff --git a/src/languages/c.coffee b/src/languages/c.coffee index c5c1947f..1e1f3c69 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -282,6 +282,34 @@ config.stringFixer = (string) -> config.empty = '__0_droplet__' config.emptyIndent = '' +# Annotate if/else with the location of the "else" token +config.annotate = (node) -> + if node.type is 'selectionStatement' and + node.children[0].data.text is 'if' and + node.children.length is 7 + originalNode = node + # Find the true final 'else' + ncases = 1 + while node.children[6].children[0].type is 'selectionStatement' and node.children[6].children[0].children.length is 7 + node = node.children[6].children[0] + ncases += 1 + return { + ncases, + elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start + } + return null + +config.handleButton = (str, type, block) -> + console.log str + if '__parse__selectionStatement' in block.classes + lines = str.split '\n' + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start + suffix = str[prefix.length...] + + return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix + + return str + # TODO Implement removing parentheses at some point #config.unParenWrap = (leading, trailing, node, context) -> # while true diff --git a/src/model.coffee b/src/model.coffee index f89c319f..7a296a69 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -506,6 +506,7 @@ exports.Container = class Container extends List precedence: @precedence classes: @classes parseContext: @parseContext + data: @data } setParent: (parent) -> @@ -983,7 +984,7 @@ exports.BlockEndToken = class BlockEndToken extends EndToken serialize: -> "" exports.Block = class Block extends Container - constructor: (@precedence = 0, @color = 'blank', @socketLevel = helper.ANY_DROP, @classes = [], @parseContext, @buttons = {}) -> + constructor: (@precedence = 0, @color = 'blank', @socketLevel = helper.ANY_DROP, @classes = [], @parseContext, @buttons = {}, @data = {}) -> @start = new BlockStartToken this @end = new BlockEndToken this @@ -1001,7 +1002,7 @@ exports.Block = class Block extends Container return null _cloneEmpty: -> - clone = new Block @precedence, @color, @socketLevel, @classes, @parseContext, @buttons + clone = new Block @precedence, @color, @socketLevel, @classes, @parseContext, @buttons, @data clone.currentlyParenWrapped = @currentlyParenWrapped return clone diff --git a/src/parser.coffee b/src/parser.coffee index 4dc24b03..c9dc758f 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -100,7 +100,8 @@ exports.Parser = class Parser opts.socketLevel, opts.classes, opts.parseContext, - opts.buttons + opts.buttons, + opts.data @addMarkup block, opts.bounds, opts.depth diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 3ad1a22e..ec526024 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -134,6 +134,7 @@ exports.createTreewalkParser = (parse, config, root) -> classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) buttons: @getButtons(node) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + data: config.annotate?(node) ? null when 'parens' # Parens are assumed to wrap the only child that has children @@ -170,6 +171,7 @@ exports.createTreewalkParser = (parse, config, root) -> color: @getColor node, rules classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + data: config.annotate?(node) ? null when 'indent' # A lone indent needs to be wrapped in a block. @@ -180,6 +182,7 @@ exports.createTreewalkParser = (parse, config, root) -> color: @getColor node, rules classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + data: config.annotate?(node) ? null depth += 1 From 1c9afed4e3684768cc86497793f755944c4c04df Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 14:39:19 -0400 Subject: [PATCH 10/60] Add +/- buttons for functions and plumbing for potentially paren unwrapping --- src/languages/c.coffee | 32 ++++++++++++++++++++++++++++++++ src/treewalk.coffee | 30 +++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 7afd07bd..f50385c9 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -65,6 +65,33 @@ RULES = { else return 'block' + # Special: functions + 'postfixExpression': (node, opts) -> + if ( + node.children.length is 3 and node.children[1].data?.text is '(' and node.children[2].data?.text is ')' or + node.children.length is 4 and node.children[1].data?.text is '(' and node.children[3].data?.text is ')' + ) and + ( + (not node.children[0].children[0]?.children?[0]?) or + node.children[0].children[0].children[0].type isnt 'Identifier' or not opts.knownFunctions? + node.children[0].children[0].children[0].data.text not of opts.knownFunctions or + opts.knownFunctions[node.children[0].children[0].children[0].data.text].variableArgs + ) + return {type: 'block', buttons: ADD_BUTTON} + else + return 'block' + + 'specialMethodCall': (node, opts) -> + if ( + not opts.knownFunctions? or + node.children[0].data.text not of opts.knownFunctions or + opts.knownFunctions[node.children[0].data.text].variableArgs + ) + return {type: 'block', buttons: ADD_BUTTON} + else + return 'block' + + # Sockets 'Identifier': 'socket', 'StringLiteral': 'socket', @@ -308,6 +335,11 @@ config.handleButton = (str, type, block) -> suffix = str[prefix.length...] return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix + else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes + if str.match(/\(\s*\)\s*;?$/)? + return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") + else + return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") return str diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 65beb517..72dc3400 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -40,7 +40,7 @@ exports.createTreewalkParser = (parse, config, root) -> applyRule: (rule, node) -> if rule instanceof Function - rule = rule(node) + rule = rule(node, @opts) if 'string' is typeof rule return {type: rule} else @@ -105,6 +105,8 @@ exports.createTreewalkParser = (parse, config, root) -> else if node.children.length > 0 switch @detNode node when 'block' + paddedRules = padRules wrapRules, rules + if wrap? bounds = wrap.bounds else @@ -114,14 +116,14 @@ exports.createTreewalkParser = (parse, config, root) -> @addSocket bounds: bounds depth: depth - classes: padRules(wrapRules ? rules) + classes: paddedRules parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) @addBlock bounds: bounds depth: depth + 1 color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) + classes: paddedRules.concat @getShape node, rules buttons: @getButtons(node) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) data: config.annotate?(node) ? null @@ -141,6 +143,8 @@ exports.createTreewalkParser = (parse, config, root) -> return else + paddedRules = padRules wrapRules, rules + node.blockified = true if wrap? @@ -152,25 +156,27 @@ exports.createTreewalkParser = (parse, config, root) -> @addSocket bounds: bounds depth: depth - classes: padRules(wrapRules ? rules) + classes: paddedRules parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) @addBlock bounds: bounds depth: depth + 1 color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) + classes: paddedRules parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) data: config.annotate?(node) ? null when 'indent' + paddedRules = padRules wrapRules, rules + # A lone indent needs to be wrapped in a block. if @det(context) isnt 'block' @addBlock bounds: node.bounds depth: depth color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) + classes: paddedRules.concat(@getShape(node, rules)) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) data: config.annotate?(node) ? null @@ -206,17 +212,18 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth prefix: prefix[oldPrefix.length...prefix.length] - classes: padRules(wrapRules ? rules) + classes: paddedRules parseContext: @applyRule(config.RULES[node.type], node).indentContext for child in node.children @mark child, prefix, depth + 2, false else if context? and @detNode(context) is 'block' if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) + paddedRules = padRules wrapRules, rules @addSocket bounds: node.bounds depth: depth - classes: padRules(wrapRules ? rules) + classes: paddedRules parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) if config.empty? and not @opts.preserveEmpty and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.empty @@ -286,5 +293,10 @@ exports.createTreewalkParser = (parse, config, root) -> return TreewalkParser PARSE_PREFIX = "__parse__" -padRules = (rules) -> rules.map (x) -> "#{PARSE_PREFIX}#{x}" +PAREN_PREFIX = "__paren__" +padRules = (wrap, rules) -> + if wrap? + return wrap.map((x) -> PARSE_PREFIX + x).concat rules.map((x) -> PAREN_PREFIX + x) + else + rules.map (x) -> PARSE_PREFIX + x parseClasses = (node) -> node.classes.filter((x) -> x[...PARSE_PREFIX.length] is PARSE_PREFIX).map((x) -> x[PARSE_PREFIX.length..]) From cdc38ccfa6a70f99cc6fd2d0d837ae8a5293d334 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 15:02:18 -0400 Subject: [PATCH 11/60] +/- buttons for declarator lists --- src/languages/c.coffee | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index f50385c9..6ce7e1a1 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -44,7 +44,13 @@ RULES = { 'parameterList': 'skip', 'argumentExpressionList': 'skip', 'initializerList': 'skip', - 'initDeclaratorList': 'skip', + 'initDeclarator': 'skip', + + 'initDeclaratorList': (node) -> + if node.parent?.type is 'initDeclaratorList' + 'skip' + else + {type: 'block', buttons: ADD_BUTTON} # Special: nested selection statement. Skip iff we are an if statement # in the else clause of another if statement. @@ -111,7 +117,7 @@ COLOR_RULES = [ ['selectionStatement', 'control'], # e.g. if `(a) { } else { }` OR `switch (a) { }` ['assignmentExpression', 'command'], # e.g. `a = b;` OR `a = b` ['relationalExpression', 'value'], # e.g. `a < b` - ['initDeclarator', 'command'], # e.g. `a = b` when inside `int a = b;` + ['initDeclaratorList', 'command'], # e.g. `a = b` when inside `int a = b;` ['blockItemList', 'control'], # List of commands ['compoundStatement', 'control'], # List of commands inside braces ['externalDeclaration', 'control'], # e.g. `int a = b` when global @@ -139,7 +145,7 @@ SHAPE_RULES = [ ['selectionStatement', 'block-only'], # e.g. if `(a) { } else { }` OR `switch (a) { }` ['assignmentExpression', 'block-only'], # e.g. `a = b;` OR `a = b` ['relationalExpression', 'value-only'], # e.g. `a < b` - ['initDeclarator', 'block-only'], # e.g. `a = b` when inside `int a = b;` + ['initDeclaratorList', 'value-only'], # e.g. `a = b` when inside `int a = b;` ['externalDeclaration', 'block-only'], # e.g. `int a = b` when global ['structDeclaration', 'block-only'], # e.g. `struct a { }` ['declarationSpecifier', 'block-only'], # e.g. `int` when in `int a = b;` @@ -340,6 +346,8 @@ config.handleButton = (str, type, block) -> return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") else return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") + else if '__parse__initDeclaratorList' in block.classes + return str += ', __0_droplet__ = __0_droplet__' return str From 6dbf7a93966829f1ac961750cdaa6500140245e3 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 15:27:47 -0400 Subject: [PATCH 12/60] Initializers and comma expressions --- src/languages/c.coffee | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 6ce7e1a1..b14df9cf 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -46,6 +46,20 @@ RULES = { 'initializerList': 'skip', 'initDeclarator': 'skip', + 'initializer': (node) -> + if node.children[0].data?.text is '{' + return {type: 'block', buttons: ADD_BUTTON} + else + return 'block' + + 'expression': (node) -> + if node.parent?.type is 'expression' + 'skip' + else if node.children[0].type is 'expression' + {type: 'block', buttons: ADD_BUTTON} + else + return 'block' + 'initDeclaratorList': (node) -> if node.parent?.type is 'initDeclaratorList' 'skip' @@ -347,7 +361,11 @@ config.handleButton = (str, type, block) -> else return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") else if '__parse__initDeclaratorList' in block.classes - return str += ', __0_droplet__ = __0_droplet__' + return str + ', __0_droplet__ = __0_droplet__' + else if '__parse__initializer' in block.classes + return str.replace(/(\s*}\s*)$/, ", __0_droplet__$1") + else if '__parse__expression' in block.classes or '__paren__expression' in block.classes + return str.replace(/(\s*;)?$/, ', __0_droplet__$1') return str From 3f8d44d8bc368e3e001562a695ff6b6fde12f661 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 15:36:55 -0400 Subject: [PATCH 13/60] Add button for if even when no else --- src/languages/c.coffee | 11 +++++++---- src/view.coffee | 20 +++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index b14df9cf..5658b7f3 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -350,11 +350,14 @@ config.annotate = (node) -> config.handleButton = (str, type, block) -> console.log str if '__parse__selectionStatement' in block.classes - lines = str.split '\n' - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start - suffix = str[prefix.length...] + if block.data.elseLocation? + lines = str.split '\n' + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start + suffix = str[prefix.length...] - return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix + return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix + else + return str + '\nelse\n{\n \n}' else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes if str.match(/\(\s*\)\s*;?$/)? return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") diff --git a/src/view.coffee b/src/view.coffee index e167a570..cc81c778 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1101,6 +1101,17 @@ exports.View = class View @minDistanceToBase[line].above + @minDistanceToBase[line].below + if @model.type is 'block' + @extraWidth = 0 + + if @model.buttons.addButton + @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding + + if @model.buttons.subtractButton + @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding + + @minDimensions[@minDimensions.length - 1].width += @extraWidth + # Go through and adjust the width of rectangles # immediately after the end of an indent to # be as long as necessary @@ -1974,21 +1985,12 @@ exports.View = class View super - @extraWidth = 0 - if @model.buttons.addButton - @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding - - if @model.buttons.subtractButton - @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding - # Blocks have a shape including a lego nubby "tab", and so # they need to be at least wide enough for tabWidth+tabOffset. for size, i in @minDimensions size.width = Math.max size.width, @view.opts.tabWidth + @view.opts.tabOffset - @minDimensions[@minDimensions.length - 1].width += @extraWidth - return null shouldAddTab: -> From fe888f231b22f1d46073fcde352f2f1f9e9b8ac0 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 16:38:39 -0400 Subject: [PATCH 14/60] Allow flexible button config --- src/controller.coffee | 23 +++----- src/draw.coffee | 12 +++- src/languages/c.coffee | 13 ++++- src/view.coffee | 122 +++++++++++++++++++++++------------------ 4 files changed, 99 insertions(+), 71 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index 72a84196..9a2b8200 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1347,22 +1347,13 @@ hook 'mousedown', 4, (point, event, state) -> hitTestBlock = @session.view.getViewNodeFor hitTestResult str = hitTestResult.stringifyInPlace() - if hitTestBlock.addButtonRect? and hitTestBlock.addButtonRect.contains mainPoint - console.log 'ADD BUTTONING!' - line = @session.mode.handleButton str, 'add-button', hitTestResult.getReader() - console.log 'NEW LINE IS', line - if line?.length >= 0 - @populateBlock hitTestResult, line - @redrawMain() - state.consumedHitTest = true - ### TODO - else if hitTestBlock.subtractButtonRect? and hitTestBlock.subtractButtonRect.contains mainPoint - line = @session.mode.handleButton str, 'subtract-button', hitTestResult.getReader() - if line?.length >= 0 - @populateBlock hitTestResult, line - @redrawMain() - state.consumedHitTest = true - ### + for key, button of hitTestBlock.buttonRects + if button.contains mainPoint + line = @session.mode.handleButton str, key, hitTestResult.getReader() + if line?.length >= 0 + @populateBlock hitTestResult, line + @redrawMain() + state.consumedHitTest = true # If the user lifts the mouse # before they have dragged five pixels, diff --git a/src/draw.coffee b/src/draw.coffee index 13cd0da6..1a0f189c 100644 --- a/src/draw.coffee +++ b/src/draw.coffee @@ -175,12 +175,22 @@ exports.Draw = class Draw @element.parentElement.removeChild @element @Group = class Group extends ElementWrapper - constructor: -> + constructor: (@style) -> super() + if @style? + @_lastTransform = @style.transform + makeElement: -> return document.createElementNS SVG_STANDARD, 'g' + update: -> + return unless @element? + + if @style? and @style.transform? and @style.transform isnt @_lastTransform + @_lastTransform = @style.transform + @element.setAttribute 'transform', @style.transform + # ## Path ## # This is called Path, but is forced to be closed so is actually a polygon. # It can do fast translation and rectangular intersection. diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 5658b7f3..bed938a7 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -9,7 +9,18 @@ antlrHelper = require '../antlr.coffee' {fixQuotedString, looseCUnescape, quoteAndCEscape} = helper -ADD_BUTTON = {addButton: true} +ADD_BUTTON = [ + { + key: 'subtract-button' + glyph: '\u25C0' + border: false + } + { + key: 'add-button' + glyph: '\u25B6' + border: false + } +] RULES = { # Indents diff --git a/src/view.coffee b/src/view.coffee index cc81c778..5ed4de21 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -30,9 +30,10 @@ DROP_TRIANGLE_COLOR = '#555' SVG_STANDARD = helper.SVG_STANDARD DEFAULT_OPTIONS = - buttonWidth: 15 + buttonWidth: 10 buttonHeight: 15 - buttonPadding: 6 + buttonVertPadding: 6 + buttonHorizPadding: 3 minIndentTongueWidth: 150 showDropdowns: true padding: 5 @@ -1064,11 +1065,11 @@ exports.View = class View @minDistanceToBase[desiredLine].below = Math.max( @minDistanceToBase[desiredLine].below, minDistanceToBase[line].below + Math.max(bottomMargin, ( - if (@model.buttons?.addButton or @model.buttons?.subtractButton) and + if @model.buttons? and @model.buttons.length > 0 and desiredLine is @lineLength - 1 and @multilineChildrenData[line] is MULTILINE_END and @lineChildren[line].length is 1 - @view.opts.buttonPadding + @view.opts.buttonHeight + @view.opts.buttonVertPadding + @view.opts.buttonHeight else 0 ))) @@ -1104,11 +1105,8 @@ exports.View = class View if @model.type is 'block' @extraWidth = 0 - if @model.buttons.addButton - @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding - - if @model.buttons.subtractButton - @extraWidth += @view.opts.buttonWidth + @view.opts.buttonPadding + if @model.buttons? then for {key} in @model.buttons + @extraWidth += @view.opts.buttonWidth + @view.opts.buttonHorizPadding @minDimensions[@minDimensions.length - 1].width += @extraWidth @@ -1819,29 +1817,34 @@ exports.View = class View if @model.type is 'block' @path.style.fillColor = @view.getColor @model.color - # Add the add button if necessary - if @model.buttons?.addButton + if @model.buttons? + # Add the add button if necessary lastLine = @bounds.length - 1 lastRect = @bounds[lastLine] - start = lastRect.x + lastRect.width - @extraWidth - top = lastRect.y + lastRect.height/2 - @view.opts.buttonHeight/2 - # Cases when last line is MULTILINE - if @multilineChildrenData[lastLine] is MULTILINE_END - multilineChild = @lineChildren[lastLine][0] - multilineBounds = @view.getViewNodeFor(multilineChild.child).bounds[lastLine - multilineChild.startLine] - # If it is a G-Shape - if @lineChildren[lastLine].length > 1 - height = multilineBounds.bottom() - lastRect.y - top = lastRect.y + height/2 - @view.opts.buttonHeight/2 - else - height = lastRect.bottom() - multilineBounds.bottom() - top = multilineBounds.bottom() + height/2 - @view.opts.buttonHeight/2 - @addButtonPath.style.transform = "translate(#{start}, #{top})" - @addButtonPath.update() - @addButtonRect = new @view.draw.Rectangle start, top, @view.opts.buttonWidth, @view.opts.buttonHeight + start = lastRect.x + lastRect.width - @extraWidth - @view.opts.padding / 2 + top = lastRect.y + lastRect.height / 2 - @view.opts.buttonHeight / 2 + for {key} in @model.buttons + # Cases when last line is MULTILINE + if @multilineChildrenData[lastLine] is MULTILINE_END + multilineChild = @lineChildren[lastLine][0] + multilineBounds = @view.getViewNodeFor(multilineChild.child).bounds[lastLine - multilineChild.startLine] + # If it is a G-Shape + if @lineChildren[lastLine].length > 1 + height = multilineBounds.bottom() - lastRect.y + top = lastRect.y + height/2 - @view.opts.buttonHeight/2 + else + height = lastRect.bottom() - multilineBounds.bottom() + top = multilineBounds.bottom() + height/2 - @view.opts.buttonHeight/2 + + @buttonGroups[key].style.transform = "translate(#{start}, #{top})" + @buttonGroups[key].update() + @buttonPaths[key].update() + @buttonRects[key] = new @view.draw.Rectangle start, top, @view.opts.buttonWidth, @view.opts.buttonHeight + + @elements.push @buttonPaths[key] - @elements.push @addButtonPath + start += @view.opts.buttonWidth + @view.opts.buttonHorizPadding # Return it. return @path @@ -1900,11 +1903,12 @@ exports.View = class View @path.style.strokeColor = avgColor @path.style.strokeColor, 0.5, '#888' # Change button color - if @addButtonPath?.active - if @addButtonPath.style.fillColor isnt 'none' - @addButtonPath.style.fillColor = avgColor @addButtonPath.style.fillColor, 0.5, '#888' - if @addButtonPath.style.strokeColor isnt 'none' - @addButtonPath.style.strokeColor = avgColor @addButtonPath.style.strokeColor, 0.5, '#888' + if @model.buttons? then for {key} in @model.buttons + if @buttonPaths[key].active + if @buttonPaths[key].style.fillColor isnt 'none' + @buttonPaths[key].style.fillColor = avgColor @buttonPaths[key].style.fillColor, 0.5, '#888' + if @buttonPaths[key].style.strokeColor isnt 'none' + @buttonPaths[key].style.strokeColor = avgColor @buttonPaths[key].style.strokeColor, 0.5, '#888' if style.selected # Change path color @@ -1914,26 +1918,28 @@ exports.View = class View @path.style.strokeColor = avgColor @path.style.strokeColor, 0.7, '#00F' # Change button color - if @addButtonPath?.active - if @addButtonPath.style.fillColor isnt 'none' - @addButtonPath.style.fillColor = avgColor @addButtonPath.style.fillColor, 0.7, '#00F' - if @addButtonPath.style.strokeColor isnt 'none' - @addButtonPath.style.strokeColor = avgColor @addButtonPath.style.strokeColor, 0.7, '#00F' + if @model.buttons? then for {key} in @model.buttons + if @buttonPaths[key].active + if @buttonPaths[key].style.fillColor isnt 'none' + @buttonPaths[key].style.fillColor = avgColor @buttonPaths[key].style.fillColor, 0.7, '#00F' + if @buttonPaths[key].style.strokeColor isnt 'none' + @buttonPaths[key].style.strokeColor = avgColor @buttonPaths[key].style.strokeColor, 0.7, '#00F' @path.setMarkStyle @markStyle @path.update() - @addButtonPath?.update?() + if @model.buttons? then for {key} in @model.buttons + @buttonPaths[key].update() + @buttonGroups[key].update() # Unset all the things we changed @path.style.fillColor = oldFill @path.style.strokeColor = oldStroke - if @addButtonPath?.active - @addButtonPath.style.fillColor = oldFill - @addButtonPath.style.strokeColor = oldStroke - - # BUttons + if @model.buttons? then for {key} in @model.buttons + if @buttonPaths[key].active + @buttonPaths[key].style.fillColor = oldFill + @buttonPaths[key].style.strokeColor = oldStroke return null @@ -1956,28 +1962,38 @@ exports.View = class View class BlockViewNode extends ContainerViewNode constructor: -> super - if @model.buttons?.addButton - @addButtonPath = new @view.draw.Path([ + + @buttonGroups = {} + @buttonPaths = {} + @buttonRects = {} + + if @model.buttons? then for {key, glyph, border} in @model.buttons + @buttonGroups[key] = new @view.draw.Group() + @buttonPaths[key] = new @view.draw.Path([ new @view.draw.Point 0, 0 new @view.draw.Point 0 + @view.opts.buttonWidth, 0 new @view.draw.Point 0 + @view.opts.buttonWidth, 0 + @view.opts.buttonHeight new @view.draw.Point 0, 0 + @view.opts.buttonHeight - ], true, { + ], border ? true, { fillColor: @view.getColor(@model.color) cssClass: 'droplet-button-path' }) + @buttonGroups[key].style = {} + textElement = new @view.draw.Text(new @view.draw.Point( - (@view.opts.buttonWidth - @view.draw.measureCtx.measureText('+').width)/ 2, + (@view.opts.buttonWidth - @view.draw.measureCtx.measureText(glyph).width)/ 2, @view.opts.buttonHeight - @view.opts.textHeight - ), '+') - textElement.setParent @addButtonPath + ), glyph) + @buttonPaths[key].setParent @buttonGroups[key] + textElement.setParent @buttonGroups[key] - @addButtonPath.setParent @group - @elements.push @addButtonPath + @buttonGroups[key].setParent @group + @elements.push @buttonGroups[key] + @activeElements.push @buttonPaths[key] @activeElements.push textElement - @activeElements.push @addButtonPath + @activeElements.push @buttonGroups[key] computeMinDimensions: -> if @computedVersion is @model.version From cfad85f0b6ca2df86313a59ddf35efbe0e2c4be3 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 16:55:12 -0400 Subject: [PATCH 15/60] +/- buttons for functions --- src/languages/c.coffee | 83 ++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index bed938a7..610d13cd 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -10,6 +10,13 @@ antlrHelper = require '../antlr.coffee' {fixQuotedString, looseCUnescape, quoteAndCEscape} = helper ADD_BUTTON = [ + { + key: 'add-button' + glyph: '\u25B6' + border: false + } +] +BOTH_BUTTON = [ { key: 'subtract-button' glyph: '\u25C0' @@ -108,7 +115,10 @@ RULES = { node.children[0].children[0].children[0].data.text not of opts.knownFunctions or opts.knownFunctions[node.children[0].children[0].children[0].data.text].variableArgs ) - return {type: 'block', buttons: ADD_BUTTON} + if node.children.length is 3 + return {type: 'block', buttons: ADD_BUTTON} + else + return {type: 'block', buttons: BOTH_BUTTON} else return 'block' @@ -118,7 +128,7 @@ RULES = { node.children[0].data.text not of opts.knownFunctions or opts.knownFunctions[node.children[0].data.text].variableArgs ) - return {type: 'block', buttons: ADD_BUTTON} + return {type: 'block', buttons: BOTH_BUTTON} else return 'block' @@ -356,30 +366,63 @@ config.annotate = (node) -> ncases, elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start } + + if node.type is 'postfixExpression' + if ( + node.children.length is 3 and node.children[1].data?.text is '(' and node.children[2].data?.text is ')' or + node.children.length is 4 and node.children[1].data?.text is '(' and node.children[3].data?.text is ')' + ) + if node.children.length is 4 + param = node.children[2] + while param.type is 'argumentExpressionList' + param = param.children[param.children.length - 1] + + return { + lastParam: helper.subtractBounds param.bounds, node.bounds.start + } + + if node.type is 'specialMethodCall' + return { + lastParam: helper.subtractBounds node.children[2].bounds, node.bounds.start + } + return null config.handleButton = (str, type, block) -> console.log str - if '__parse__selectionStatement' in block.classes - if block.data.elseLocation? + if type is 'add-button' + if '__parse__selectionStatement' in block.classes + if block.data.elseLocation? + lines = str.split '\n' + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start + suffix = str[prefix.length...] + + return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix + else + return str + '\nelse\n{\n \n}' + else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes + if str.match(/\(\s*\)\s*;?$/)? + return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") + else + return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") + else if '__parse__initDeclaratorList' in block.classes + return str + ', __0_droplet__ = __0_droplet__' + else if '__parse__initializer' in block.classes + return str.replace(/(\s*}\s*)$/, ", __0_droplet__$1") + else if '__parse__expression' in block.classes or '__paren__expression' in block.classes + return str.replace(/(\s*;)?$/, ', __0_droplet__$1') + else + if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes lines = str.split '\n' - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start - suffix = str[prefix.length...] + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastParam.start + suffix = str.match(/\s*\)\s*;?\s*$/g)[0] - return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix - else - return str + '\nelse\n{\n \n}' - else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes - if str.match(/\(\s*\)\s*;?$/)? - return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") - else - return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") - else if '__parse__initDeclaratorList' in block.classes - return str + ', __0_droplet__ = __0_droplet__' - else if '__parse__initializer' in block.classes - return str.replace(/(\s*}\s*)$/, ", __0_droplet__$1") - else if '__parse__expression' in block.classes or '__paren__expression' in block.classes - return str.replace(/(\s*;)?$/, ', __0_droplet__$1') + console.log 'PREFIX', prefix + console.log 'SUFFIX', suffix + + prefix = prefix.replace /\s*,\s*$/, '' + + return prefix + suffix return str From dc396627e6a7398fa83feb25f3690a04413fd8ef Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 11 Jul 2016 17:18:40 -0400 Subject: [PATCH 16/60] Subtract button for if/else, and vertical glyphs --- src/languages/c.coffee | 61 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 610d13cd..ac7445d6 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -29,6 +29,27 @@ BOTH_BUTTON = [ } ] +ADD_BUTTON_VERT = [ + { + key: 'add-button' + glyph: '\u25BC' + border: false + } +] + +BOTH_BUTTON_VERT = [ + { + key: 'subtract-button' + glyph: '\u25B2' + border: false + } + { + key: 'add-button' + glyph: '\u25BC' + border: false + } +] + RULES = { # Indents 'compoundStatement': { @@ -99,7 +120,10 @@ RULES = { return 'skip' # Otherwise, if we are an if statement, give us a mutation button else if node.children[0].data.text is 'if' - return {type: 'block', buttons: ADD_BUTTON} + if node.children.length is 7 + return {type: 'block', buttons: BOTH_BUTTON_VERT} + else + return {type: 'block', buttons: ADD_BUTTON_VERT} else return 'block' @@ -352,6 +376,10 @@ config.empty = '__0_droplet__' config.emptyIndent = '' # Annotate if/else with the location of the "else" token + +# TODO computing relative boundaries does not actually work very well right now; +# it will fail whenever something starts( +# ) one one line and ends on the other like so. config.annotate = (node) -> if node.type is 'selectionStatement' and node.children[0].data.text is 'if' and @@ -362,10 +390,20 @@ config.annotate = (node) -> while node.children[6].children[0].type is 'selectionStatement' and node.children[6].children[0].children.length is 7 node = node.children[6].children[0] ncases += 1 - return { - ncases, - elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start - } + + # Find the second-to-last else, if it exists + if node.parent?.parent?.type is 'selectionStatement' and node.parent.parent.children.length is 7 and node is node.parent.parent.children[6].children[0] + secondToLastNode = node.parent.parent + return { + ncases, + elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start + elifLocation: helper.subtractBounds secondToLastNode.children[5].bounds, originalNode.bounds.start + } + else + return { + ncases, + elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start + } if node.type is 'postfixExpression' if ( @@ -412,7 +450,18 @@ config.handleButton = (str, type, block) -> else if '__parse__expression' in block.classes or '__paren__expression' in block.classes return str.replace(/(\s*;)?$/, ', __0_droplet__$1') else - if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes + if '__parse__selectionStatement' in block.classes + lines = str.split '\n' + + if block.data.elifLocation + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elifLocation.start + suffix = helper.clipLines lines, block.data.elseLocation.start, {line: lines.length - 1, column: lines.length} + + return prefix + suffix + else + return helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start + + else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes lines = str.split '\n' prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastParam.start suffix = str.match(/\s*\)\s*;?\s*$/g)[0] From a6f87c878194b686a5bada943325a70a2751117f Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 09:40:33 -0400 Subject: [PATCH 17/60] Usability improvements, and dual buttons for declarations --- css/droplet.css | 4 ++++ src/languages/c.coffee | 48 ++++++++++++++++++++++++++++-------------- src/view.coffee | 15 +++++++++---- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/css/droplet.css b/css/droplet.css index f8796517..e6d492e0 100644 --- a/css/droplet.css +++ b/css/droplet.css @@ -375,6 +375,10 @@ text { .droplet-dropdown-arrow, .droplet-button-path { cursor: pointer; } +.droplet-button-path:hover { + fill: #FFF; + opacity: 0.5; +} .droplet-socket-path { /*fill: #FFF;*/ } diff --git a/src/languages/c.coffee b/src/languages/c.coffee index ac7445d6..9f5729e2 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -84,6 +84,14 @@ RULES = { 'argumentExpressionList': 'skip', 'initializerList': 'skip', 'initDeclarator': 'skip', + 'initDeclaratorList': 'skip' + 'declaration': (node) -> + if node.children.length is 3 and node.children[1].children.length is 3 + return {type: 'block', buttons: BOTH_BUTTON} + else if node.children.length >= 2 + return {type: 'block', buttons: ADD_BUTTON} + else + return 'block' 'initializer': (node) -> if node.children[0].data?.text is '{' @@ -99,12 +107,6 @@ RULES = { else return 'block' - 'initDeclaratorList': (node) -> - if node.parent?.type is 'initDeclaratorList' - 'skip' - else - {type: 'block', buttons: ADD_BUTTON} - # Special: nested selection statement. Skip iff we are an if statement # in the else clause of another if statement. 'selectionStatement': (node) -> @@ -424,6 +426,15 @@ config.annotate = (node) -> lastParam: helper.subtractBounds node.children[2].bounds, node.bounds.start } + if node.type is 'declaration' and node.children.length is 3 + lastDeclaration = node.children[1] + while lastDeclaration.type is 'initDeclaratorList' and lastDeclaration.children.length is 3 + lastDeclaration = lastDeclaration.children[2] + + return { + lastDeclaration: helper.subtractBounds lastDeclaration.bounds, node.bounds.start + } + return null config.handleButton = (str, type, block) -> @@ -440,15 +451,15 @@ config.handleButton = (str, type, block) -> return str + '\nelse\n{\n \n}' else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes if str.match(/\(\s*\)\s*;?$/)? - return str.replace(/(\s*\)\s*;?)$/, "#{config.empty}$1") + return str.replace(/(\s*\)\s*;?\s*)$/, "#{config.empty}$1") else - return str.replace(/(\s*\)\s*;?)$/, ", #{config.empty}$1") - else if '__parse__initDeclaratorList' in block.classes - return str + ', __0_droplet__ = __0_droplet__' + return str.replace(/(\s*\)\s*;?\s*)$/, ", #{config.empty}$1") + else if '__parse__declaration' in block.classes + return str.replace(/(\s*;?\s*)$/, ", #{config.empty} = #{config.empty}$1") else if '__parse__initializer' in block.classes - return str.replace(/(\s*}\s*)$/, ", __0_droplet__$1") + return str.replace(/(\s*}\s*)$/, ", #{config.empty}$1") else if '__parse__expression' in block.classes or '__paren__expression' in block.classes - return str.replace(/(\s*;)?$/, ', __0_droplet__$1') + return str.replace(/(\s*;\s*)?$/, ", #{config.empty}$1") else if '__parse__selectionStatement' in block.classes lines = str.split '\n' @@ -464,15 +475,20 @@ config.handleButton = (str, type, block) -> else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes lines = str.split '\n' prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastParam.start - suffix = str.match(/\s*\)\s*;?\s*$/g)[0] - - console.log 'PREFIX', prefix - console.log 'SUFFIX', suffix + suffix = str.match(/\s*\)\s*;?\s*$/)[0] prefix = prefix.replace /\s*,\s*$/, '' return prefix + suffix + else if '__parse__declaration' in block.classes + lines = str.split '\n' + prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastDeclaration.start + suffix = str.match(/\s*;?\s*$/)[0] + + prefix = prefix.replace /\s*,\s*$/, '' + + return prefix + suffix return str # TODO Implement removing parentheses at some point diff --git a/src/view.coffee b/src/view.coffee index 5ed4de21..79c84d53 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1970,10 +1970,17 @@ exports.View = class View if @model.buttons? then for {key, glyph, border} in @model.buttons @buttonGroups[key] = new @view.draw.Group() @buttonPaths[key] = new @view.draw.Path([ - new @view.draw.Point 0, 0 - new @view.draw.Point 0 + @view.opts.buttonWidth, 0 - new @view.draw.Point 0 + @view.opts.buttonWidth, 0 + @view.opts.buttonHeight - new @view.draw.Point 0, 0 + @view.opts.buttonHeight + new @view.draw.Point 0, @view.opts.bevelClip + new @view.draw.Point @view.opts.bevelClip, 0 + + new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, 0 + new @view.draw.Point @view.opts.buttonWidth, @view.opts.bevelClip + + new @view.draw.Point @view.opts.buttonWidth, @view.opts.buttonHeight - @view.opts.bevelClip + new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, @view.opts.buttonHeight + + new @view.draw.Point @view.opts.bevelClip, @view.opts.buttonHeight + new @view.draw.Point 0, @view.opts.buttonHeight - @view.opts.bevelClip ], border ? true, { fillColor: @view.getColor(@model.color) cssClass: 'droplet-button-path' From 809a1044dd8793c4dc7281b26161a0eafd1ef2c4 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 09:55:24 -0400 Subject: [PATCH 18/60] Fix a bug with dragging mutation buttons --- src/draw.coffee | 7 +++++++ src/languages/c.coffee | 2 +- src/view.coffee | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/draw.coffee b/src/draw.coffee index 1a0f189c..3ef3945d 100644 --- a/src/draw.coffee +++ b/src/draw.coffee @@ -184,6 +184,13 @@ exports.Draw = class Draw makeElement: -> return document.createElementNS SVG_STANDARD, 'g' + activate: -> + super() + + if @style? and @style.transform? + @_lastTransform = @style.transform + @element.setAttribute 'transform', @style.transform + update: -> return unless @element? diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 9f5729e2..bbe6d1de 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -169,7 +169,7 @@ RULES = { COLOR_RULES = [ ['jumpStatement', 'return'] # e.g. `return 0;` ['declaration', 'control'], # e.g. `int a;` - ['specialMethodCall', 'command'], # e.g. `a(b);` + ['specialMethodCall', 'value'], # e.g. `a(b);` ['equalityExpression', 'value'] # e.g. `a == b` ['additiveExpression', 'value'], # e.g. `a + b` ['multiplicativeExpression', 'value'], # e.g. `a * b` diff --git a/src/view.coffee b/src/view.coffee index 79c84d53..68bc2fab 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -30,7 +30,7 @@ DROP_TRIANGLE_COLOR = '#555' SVG_STANDARD = helper.SVG_STANDARD DEFAULT_OPTIONS = - buttonWidth: 10 + buttonWidth: 15 buttonHeight: 15 buttonVertPadding: 6 buttonHorizPadding: 3 From 7778591ef758bf7297905cdb3895f8a920f70dc8 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 09:57:35 -0400 Subject: [PATCH 19/60] Undo capture for mutation buttons --- src/controller.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controller.coffee b/src/controller.coffee index 9a2b8200..8245d452 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1350,7 +1350,8 @@ hook 'mousedown', 4, (point, event, state) -> for key, button of hitTestBlock.buttonRects if button.contains mainPoint line = @session.mode.handleButton str, key, hitTestResult.getReader() - if line?.length >= 0 + if line?.length >= 0 and line isnt str + @undoCapture() @populateBlock hitTestResult, line @redrawMain() state.consumedHitTest = true From df0617a1ea3e01374b6d3aca020464f7a2a8114c Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 12:06:48 -0400 Subject: [PATCH 20/60] Move from parse annotations to droplet tree inspection for +/- buttons --- src/controller.coffee | 2 +- src/languages/c.coffee | 142 ++++++++++++++++++++++++++++++++++------- src/model.coffee | 39 +++++++++++ src/treewalk.coffee | 22 +++++-- 4 files changed, 174 insertions(+), 31 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index 8245d452..e4b84398 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1349,7 +1349,7 @@ hook 'mousedown', 4, (point, event, state) -> for key, button of hitTestBlock.buttonRects if button.contains mainPoint - line = @session.mode.handleButton str, key, hitTestResult.getReader() + line = @session.mode.handleButton str, key, hitTestResult #.getReader() # TODO getReader() that allows tree walking if line?.length >= 0 and line isnt str @undoCapture() @populateBlock hitTestResult, line diff --git a/src/languages/c.coffee b/src/languages/c.coffee index bbe6d1de..73e1489a 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -7,6 +7,8 @@ helper = require '../helper.coffee' parser = require '../parser.coffee' antlrHelper = require '../antlr.coffee' +model = require '../model.coffee' + {fixQuotedString, looseCUnescape, quoteAndCEscape} = helper ADD_BUTTON = [ @@ -139,10 +141,21 @@ RULES = { (not node.children[0].children[0]?.children?[0]?) or node.children[0].children[0].children[0].type isnt 'Identifier' or not opts.knownFunctions? node.children[0].children[0].children[0].data.text not of opts.knownFunctions or - opts.knownFunctions[node.children[0].children[0].children[0].data.text].variableArgs + opts.knownFunctions[node.children[0].children[0].children[0].data.text].minArgs? ) if node.children.length is 3 return {type: 'block', buttons: ADD_BUTTON} + else if opts.knownFunctions? and node.children[0].children[0].children[0].data.text of opts.knownFunctions + minimum = opts.knownFunctions[node.children[0].children[0].children[0].data.text].minArgs + nargs = 0 + param = node.children[2] + while param.type is 'argumentExpressionList' + nargs += 1 + param = param.children[0] + if nargs > minimum + return {type: 'block', buttons: BOTH_BUTTON} + else + return {type: 'block', buttons: ADD_BUTTON} else return {type: 'block', buttons: BOTH_BUTTON} else @@ -151,10 +164,14 @@ RULES = { 'specialMethodCall': (node, opts) -> if ( not opts.knownFunctions? or - node.children[0].data.text not of opts.knownFunctions or - opts.knownFunctions[node.children[0].data.text].variableArgs + node.children[0].data.text not of opts.knownFunctions ) return {type: 'block', buttons: BOTH_BUTTON} + else if opts.knownFunctions[node.children[0].data.text].minArgs? + if opts.knownFunctions[node.children[0].data.text].minArgs is 0 + return {type: 'block', buttons: BOTH_BUTTON} + else + return {type: 'block', buttons: ADD_BUTTON} else return 'block' @@ -437,18 +454,84 @@ config.annotate = (node) -> return null +insertAfterLastSocket = (str, block, insert) -> + + {string: suffix} = model.stringThrough( + block.end, + ((token) -> token.parent is block and token.type is 'socketEnd'), + ((token) -> token.prev) + ) + + prefix = str[...-suffix.length] + + return prefix + insert + suffix + +removeLastSocketAnd = (str, block, prefixClip = null, suffixClip = null) -> + {string: suffix, token: socketToken} = model.stringThrough( + block.end, + ((token) -> token.parent is block and token.type is 'socketEnd'), + true + ) + + if suffixClip? + suffix = suffix.replace suffixClip, '' + + {string: prefix} = model.stringThrough( + block.start, + ((token) -> token.container is socketToken.container), + false + ) + + if prefixClip? + prefix = prefix.replace prefixClip, '' + + console.log prefix, suffix + + return prefix + suffix + config.handleButton = (str, type, block) -> - console.log str if type is 'add-button' if '__parse__selectionStatement' in block.classes - if block.data.elseLocation? - lines = str.split '\n' - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start - suffix = str[prefix.length...] + indents = [] + block.traverseOneLevel (child) -> + console.log child + if child.type is 'indent' + indents.push child + indents = indents[-3...] + + console.log indents + + if indents.length is 1 + return str + '\nelse\n{\n \n}\n' + + else if indents.length is 2 + {string: prefix} = model.stringThrough( + block.start, + ((token) -> token is indents[0].end), + false + ) + + suffix = str[prefix.length + 1...] + + console.log 'PREFIX', prefix + console.log 'SUFFIX', suffix + + return prefix + '\n}\nelse if (a == b)\n{\n \n' + suffix + + else if indents.length is 3 + {string: prefix} = model.stringThrough( + block.start, + ((token) -> token is indents[1].end), + false + ) + + suffix = str[prefix.length + 1...] + + console.log 'PREFIX', prefix + console.log 'SUFFIX', suffix + + return prefix + '\n}\nelse if (a == b)\n{\n \n' + suffix - return prefix + "else if (case#{block.data.ncases})\n{\n \n}\n" + suffix - else - return str + '\nelse\n{\n \n}' else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes if str.match(/\(\s*\)\s*;?$/)? return str.replace(/(\s*\)\s*;?\s*)$/, "#{config.empty}$1") @@ -462,24 +545,37 @@ config.handleButton = (str, type, block) -> return str.replace(/(\s*;\s*)?$/, ", #{config.empty}$1") else if '__parse__selectionStatement' in block.classes - lines = str.split '\n' + indents = [] + block.traverseOneLevel (child) -> + console.log child + if child.type is 'indent' + indents.push child + indents = indents[-3...] - if block.data.elifLocation - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.elifLocation.start - suffix = helper.clipLines lines, block.data.elseLocation.start, {line: lines.length - 1, column: lines.length} + console.log indents - return prefix + suffix + if indents.length < 3 + return str else - return helper.clipLines lines, {line: 0, column: 0}, block.data.elseLocation.start + {string: prefix} = model.stringThrough( + block.start, + ((token) -> token is indents[0].end), + false + ) - else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes - lines = str.split '\n' - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastParam.start - suffix = str.match(/\s*\)\s*;?\s*$/)[0] + {string: suffix} = model.stringThrough( + block.end, + ((token) -> token is indents[1].end), + true + ) - prefix = prefix.replace /\s*,\s*$/, '' + console.log 'DELETING PREFIX', prefix + console.log 'DELETING SUFFIX', suffix - return prefix + suffix + return prefix + suffix + + else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes + return removeLastSocketAnd str, block, /\s*,\s*$/ else if '__parse__declaration' in block.classes lines = str.split '\n' diff --git a/src/model.coffee b/src/model.coffee index 7a296a69..96c7b833 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -1199,3 +1199,42 @@ traverseOneLevel = (head, fn, tail) -> return head = head.next + +exports.stringThrough = (start, terminating, backward = false) -> + str = '' + + indent = [] + + head = start + while true + if terminating head + break + + if head instanceof IndentStartToken + if backward + indent.pop() + else + indent.push head.container.prefix + else if head instanceof IndentEndToken + if backward + indent.push head.container.prefix + else + indent.pop() + + if head instanceof NewlineToken + if backward + str = '\n' + (head.specialIndent ? indent.join('')) + str + else + str += '\n' + (head.specialIndent ? indent.join('')) + else + if backward + str = head.stringify() + str + else + str += head.stringify() + + if backward + head = head.prev + else + head = head.next + + return {string: str, token: head} diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 72dc3400..88ab559d 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -38,22 +38,30 @@ exports.createTreewalkParser = (parse, config, root) -> line = @lines[bounds.start.line + 1] return line[0...line.length - line.trimLeft().length] - applyRule: (rule, node) -> + applyRule: (node) -> + if node._cachedApplication? + return node._cachedApplication + + rule = config.RULES[node.type] + if rule instanceof Function rule = rule(node, @opts) + if 'string' is typeof rule - return {type: rule} - else - return rule + rule = {type: rule} + + node._cachedApplication = rule + + return rule det: (node) -> if node.type of config.RULES - return @applyRule(config.RULES[node.type], node).type + return @applyRule(node).type return 'block' getButtons: (node) -> if node.type of config.RULES - return @applyRule(config.RULES[node.type], node).buttons ? EMPTY_OBJECT + return @applyRule(node).buttons ? EMPTY_OBJECT return EMPTY_OBJECT detNode: (node) -> if node.blockified then 'block' else @det(node) @@ -213,7 +221,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth prefix: prefix[oldPrefix.length...prefix.length] classes: paddedRules - parseContext: @applyRule(config.RULES[node.type], node).indentContext + parseContext: @applyRule(node).indentContext for child in node.children @mark child, prefix, depth + 2, false From d5228dd6f036408e09ae9ea89f801caf6074e242 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 12:26:12 -0400 Subject: [PATCH 21/60] Move more to structure examination --- src/languages/c.coffee | 94 ++++-------------------------------------- 1 file changed, 9 insertions(+), 85 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 73e1489a..99a26aaf 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -97,7 +97,10 @@ RULES = { 'initializer': (node) -> if node.children[0].data?.text is '{' - return {type: 'block', buttons: ADD_BUTTON} + if node.children[1].children.length > 2 + return {type: 'block', buttons: BOTH_BUTTON} + else + return {type: 'block', buttons: ADD_BUTTON} else return 'block' @@ -394,66 +397,6 @@ config.stringFixer = (string) -> config.empty = '__0_droplet__' config.emptyIndent = '' -# Annotate if/else with the location of the "else" token - -# TODO computing relative boundaries does not actually work very well right now; -# it will fail whenever something starts( -# ) one one line and ends on the other like so. -config.annotate = (node) -> - if node.type is 'selectionStatement' and - node.children[0].data.text is 'if' and - node.children.length is 7 - originalNode = node - # Find the true final 'else' - ncases = 1 - while node.children[6].children[0].type is 'selectionStatement' and node.children[6].children[0].children.length is 7 - node = node.children[6].children[0] - ncases += 1 - - # Find the second-to-last else, if it exists - if node.parent?.parent?.type is 'selectionStatement' and node.parent.parent.children.length is 7 and node is node.parent.parent.children[6].children[0] - secondToLastNode = node.parent.parent - return { - ncases, - elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start - elifLocation: helper.subtractBounds secondToLastNode.children[5].bounds, originalNode.bounds.start - } - else - return { - ncases, - elseLocation: helper.subtractBounds node.children[5].bounds, originalNode.bounds.start - } - - if node.type is 'postfixExpression' - if ( - node.children.length is 3 and node.children[1].data?.text is '(' and node.children[2].data?.text is ')' or - node.children.length is 4 and node.children[1].data?.text is '(' and node.children[3].data?.text is ')' - ) - if node.children.length is 4 - param = node.children[2] - while param.type is 'argumentExpressionList' - param = param.children[param.children.length - 1] - - return { - lastParam: helper.subtractBounds param.bounds, node.bounds.start - } - - if node.type is 'specialMethodCall' - return { - lastParam: helper.subtractBounds node.children[2].bounds, node.bounds.start - } - - if node.type is 'declaration' and node.children.length is 3 - lastDeclaration = node.children[1] - while lastDeclaration.type is 'initDeclaratorList' and lastDeclaration.children.length is 3 - lastDeclaration = lastDeclaration.children[2] - - return { - lastDeclaration: helper.subtractBounds lastDeclaration.bounds, node.bounds.start - } - - return null - insertAfterLastSocket = (str, block, insert) -> {string: suffix} = model.stringThrough( @@ -485,8 +428,6 @@ removeLastSocketAnd = (str, block, prefixClip = null, suffixClip = null) -> if prefixClip? prefix = prefix.replace prefixClip, '' - console.log prefix, suffix - return prefix + suffix config.handleButton = (str, type, block) -> @@ -494,13 +435,10 @@ config.handleButton = (str, type, block) -> if '__parse__selectionStatement' in block.classes indents = [] block.traverseOneLevel (child) -> - console.log child if child.type is 'indent' indents.push child indents = indents[-3...] - console.log indents - if indents.length is 1 return str + '\nelse\n{\n \n}\n' @@ -513,9 +451,6 @@ config.handleButton = (str, type, block) -> suffix = str[prefix.length + 1...] - console.log 'PREFIX', prefix - console.log 'SUFFIX', suffix - return prefix + '\n}\nelse if (a == b)\n{\n \n' + suffix else if indents.length is 3 @@ -527,9 +462,6 @@ config.handleButton = (str, type, block) -> suffix = str[prefix.length + 1...] - console.log 'PREFIX', prefix - console.log 'SUFFIX', suffix - return prefix + '\n}\nelse if (a == b)\n{\n \n' + suffix else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes @@ -547,13 +479,10 @@ config.handleButton = (str, type, block) -> if '__parse__selectionStatement' in block.classes indents = [] block.traverseOneLevel (child) -> - console.log child if child.type is 'indent' indents.push child indents = indents[-3...] - console.log indents - if indents.length < 3 return str else @@ -569,22 +498,17 @@ config.handleButton = (str, type, block) -> true ) - console.log 'DELETING PREFIX', prefix - console.log 'DELETING SUFFIX', suffix - return prefix + suffix else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes return removeLastSocketAnd str, block, /\s*,\s*$/ - else if '__parse__declaration' in block.classes - lines = str.split '\n' - prefix = helper.clipLines lines, {line: 0, column: 0}, block.data.lastDeclaration.start - suffix = str.match(/\s*;?\s*$/)[0] - - prefix = prefix.replace /\s*,\s*$/, '' + return removeLastSocketAnd str, block, /((\s*,\s*)|(\s*\=\s*))$/ + else if '__parse__initializer' in block.classes + return removeLastSocketAnd str, block, /\s*,\s*$/ + else if '__parse__expression' in block.classes or '__paren__expression' in block.classes + return removeLastSocketAnd str, block, /\s*,\s*$/ - return prefix + suffix return str # TODO Implement removing parentheses at some point From e9ba713b5962ff41c3eb929714e60fb0a3b855b5 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 12:59:11 -0400 Subject: [PATCH 22/60] Move back to parsing for declarations to fix a bug --- src/antlr.coffee | 2 ++ src/languages/c.coffee | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/antlr.coffee b/src/antlr.coffee index 623dd41a..c6574871 100644 --- a/src/antlr.coffee +++ b/src/antlr.coffee @@ -95,4 +95,6 @@ exports.createANTLRParser = (name, config, root) -> } } + config.__antlrParse = parse + return treewalk.createTreewalkParser parse, config, root diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 99a26aaf..e3d2f581 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -503,7 +503,15 @@ config.handleButton = (str, type, block) -> else if '__parse__postfixExpression' in block.classes or '__paren__postfixExpression' in block.classes or '__parse__specialMethodCall' in block.classes return removeLastSocketAnd str, block, /\s*,\s*$/ else if '__parse__declaration' in block.classes - return removeLastSocketAnd str, block, /((\s*,\s*)|(\s*\=\s*))$/ + reparsed = config.__antlrParse 'declaration', str + + lines = str.split '\n' + prefix = helper.clipLines lines, {line: 0, column: 0}, reparsed.children[1].children[2].bounds.start + suffix = str.match(/\s*;?\s*$/)[0] + + prefix = prefix.replace /\s*,\s*$/, '' + + return prefix + suffix else if '__parse__initializer' in block.classes return removeLastSocketAnd str, block, /\s*,\s*$/ else if '__parse__expression' in block.classes or '__paren__expression' in block.classes From f4a75063a8801e80e18c9ad68bb5f519032d9b24 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 16:01:26 -0400 Subject: [PATCH 23/60] View socket bug fix --- css/droplet.css | 5 ++ src/controller.coffee | 42 ++++++++++----- src/languages/c.coffee | 27 ++++++++-- src/model.coffee | 19 ++++++- src/parser.coffee | 14 +++-- src/treewalk.coffee | 23 ++++++-- src/view.coffee | 117 +++++++++++++++++++---------------------- 7 files changed, 156 insertions(+), 91 deletions(-) diff --git a/css/droplet.css b/css/droplet.css index e6d492e0..3433f0a4 100644 --- a/css/droplet.css +++ b/css/droplet.css @@ -373,6 +373,8 @@ text { cursor: grab; } .droplet-dropdown-arrow, .droplet-button-path { + fill: #FFF; + opacity: 0; cursor: pointer; } .droplet-button-path:hover { @@ -392,3 +394,6 @@ text { fill: '#88F' stroke: '#88F' } +.droplet-buttonContainer-path { + display: none; +} diff --git a/src/controller.coffee b/src/controller.coffee index e4b84398..f3c6af33 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1341,20 +1341,34 @@ hook 'mousedown', 4, (point, event, state) -> #Buttons aren't clickable in a selection if @lassoSelection? and @hitTest(mainPoint, @lassoSelection)? then return - hitTestResult = @hitTest mainPoint, @session.tree + head = @session.tree.start + seek = @session.tree.end + result = null - if hitTestResult? - hitTestBlock = @session.view.getViewNodeFor hitTestResult - str = hitTestResult.stringifyInPlace() - - for key, button of hitTestBlock.buttonRects - if button.contains mainPoint - line = @session.mode.handleButton str, key, hitTestResult #.getReader() # TODO getReader() that allows tree walking - if line?.length >= 0 and line isnt str - @undoCapture() - @populateBlock hitTestResult, line - @redrawMain() - state.consumedHitTest = true + until head is seek + if head.type in ['blockStart', 'buttonContainerStart'] + viewNode = @session.view.getViewNodeFor(head.container) + result = head.container + + for key, button of viewNode.buttonRects + if button.contains mainPoint + str = result.stringifyInPlace() + line = @session.mode.handleButton str, key, result #.getReader() # TODO getReader() that allows tree walking + if line?.length >= 0 and line isnt str + @undoCapture() + @populateBlock result, line + @redrawMain() + state.consumedHitTest = true + + return + + if viewNode.path.contains mainPoint + seek = head.container.end + + head = head.next + + # If we had a child hit, return it. + return result # If the user lifts the mouse # before they have dragged five pixels, @@ -1498,7 +1512,7 @@ hook 'mousemove', 1, (point, event, state) -> if head is @draggingBlock.start head = @draggingBlock.end - if head instanceof model.StartToken + if head instanceof model.StartToken and head.type isnt 'buttonContainerStart' acceptLevel = @getAcceptLevel @draggingBlock, head.container unless acceptLevel is helper.FORBID dropPoint = @session.view.getViewNodeFor(head.container).dropPoint diff --git a/src/languages/c.coffee b/src/languages/c.coffee index e3d2f581..0929d21b 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -82,8 +82,14 @@ RULES = { 'directDeclarator': 'skip', 'rootDeclarator': 'skip', 'parameterTypeList': 'skip', - 'parameterList': 'skip', - 'argumentExpressionList': 'skip', + 'parameterList': (node) -> + if node.parent?.type is 'parameterList' + return 'skip' + else if node.children.length is 1 and node.children[0].children[0].children[0].children[0].children[0].type is 'Void' + {type: 'buttonContainer', buttons: ADD_BUTTON} + else + {type: 'buttonContainer', buttons: BOTH_BUTTON} + 'argumentExpressionList': 'skip' 'initializerList': 'skip', 'initDeclarator': 'skip', 'initDeclaratorList': 'skip' @@ -119,9 +125,9 @@ RULES = { # Check to make sure the parent is an if. Actually, # our immediate parent is a 'statement'; the logical wrapping # parent is parent.parent - node.parent.type is 'statement' and - node.parent.parent.type is 'selectionStatement' and - node.parent.parent.children[0].data.text is 'if' and + node.parent?.type is 'statement' and + node.parent.parent?.type is 'selectionStatement' and + node.parent.parent.children[0].data?.text is 'if' and # This last one will only occur if we are the else clause node.parent is node.parent.parent.children[6] return 'skip' @@ -469,6 +475,10 @@ config.handleButton = (str, type, block) -> return str.replace(/(\s*\)\s*;?\s*)$/, "#{config.empty}$1") else return str.replace(/(\s*\)\s*;?\s*)$/, ", #{config.empty}$1") + else if '__parse__parameterList' in block.classes + if str.match(/^\s*void\s*$/) + return "type param" + return str + ", type param" else if '__parse__declaration' in block.classes return str.replace(/(\s*;?\s*)$/, ", #{config.empty} = #{config.empty}$1") else if '__parse__initializer' in block.classes @@ -514,6 +524,13 @@ config.handleButton = (str, type, block) -> return prefix + suffix else if '__parse__initializer' in block.classes return removeLastSocketAnd str, block, /\s*,\s*$/ + else if '__parse__parameterList' in block.classes + count = 0 + block.traverseOneLevel (x) -> if x.type is 'socket' then count++ + if count is 1 + return 'void' + else + return removeLastSocketAnd str, block, /\s*,\s*$/ else if '__parse__expression' in block.classes or '__paren__expression' in block.classes return removeLastSocketAnd str, block, /\s*,\s*$/ diff --git a/src/model.coffee b/src/model.coffee index 96c7b833..9b37b23a 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -456,7 +456,7 @@ exports.List = class List # A generic XML-style container from which # all other containers (Block, Indent, Socket) will extend. exports.Container = class Container extends List - constructor: -> + constructor: () -> unless @start? or @end? @start = new StartToken this @end = new EndToken this @@ -973,6 +973,23 @@ exports.EndToken = class EndToken extends Token serialize: -> '' +exports.ButtonContainer = class ButtonContainer extends Container + constructor: (@classes = [], @parseContext, @buttons = {}, @data = {}) -> + @start = new ButtonContainerStartToken this + @end = new ButtonContainerEndToken this + + @type = 'buttonContainer' + + super + + _cloneEmpty: -> new ButtonContainer @classes, @parseContext, @buttons, @data + +exports.ButtonContainerStartToken = class ButtonContainerStartToken extends StartToken + constructor: -> super; @type = 'buttonContainerStart' + +exports.ButtonContainerEndToken = class ButtonContainerEndToken extends EndToken + constructor: -> super; @type = 'buttonContainerEnd' + # Block # ================== diff --git a/src/parser.coffee b/src/parser.coffee index c9dc758f..7688c376 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -105,6 +105,14 @@ exports.Parser = class Parser @addMarkup block, opts.bounds, opts.depth + addButtonContainer: (opts) -> + container= new model.ButtonContainer opts.classes, + opts.parseContext, + opts.buttons, + opts.data + + @addMarkup container, opts.bounds, opts.depth + # flagToRemove, used for removing the placeholders that # are placed when round-tripping empty sockets, so that, e.g. in CoffeeScript mode # a + (empty socket) -> a + `` -> a + (empty socket). @@ -439,19 +447,19 @@ exports.Parser = class Parser when 'indentStart' # An Indent is only allowed to be # directly inside a block; if not, then throw. - unless stack?[stack.length - 1]?.type is 'block' + unless stack?[stack.length - 1]?.type in ['block', 'buttonContainer'] throw new Error 'Improper parser: indent must be inside block, but is inside ' + stack?[stack.length - 1]?.type indentDepth += mark.token.container.prefix.length when 'blockStart' # If the a block is embedded # directly in another block, throw. - if stack[stack.length - 1]?.type is 'block' + if stack[stack.length - 1]?.type in ['block', 'buttonContainer'] throw new Error 'Improper parser: block cannot nest immediately inside another block.' when 'socketStart' # A socket is only allowed to be directly inside a block. - unless stack[stack.length - 1]?.type is 'block' + unless stack[stack.length - 1]?.type in ['block', 'buttonContainer'] throw new Error 'Improper parser: socket must be immediately inside a block.' when 'indentEnd' diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 88ab559d..8f83255f 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -107,7 +107,7 @@ exports.createTreewalkParser = (parse, config, root) -> rules.push node.type # Pass through to child if single-child - if node.children.length is 1 and @detNode(node) isnt 'indent' + if node.children.length is 1 and @detNode(node) not in ['indent', 'buttonContainer'] @mark node.children[0], prefix, depth, true, rules, context, wrap, wrapRules else if node.children.length > 0 @@ -120,7 +120,7 @@ exports.createTreewalkParser = (parse, config, root) -> else bounds = node.bounds - if context? and @detNode(context) is 'block' + if context? and @detNode(context) in ['block', 'buttonContainer'] @addSocket bounds: bounds depth: depth @@ -136,6 +136,21 @@ exports.createTreewalkParser = (parse, config, root) -> parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) data: config.annotate?(node) ? null + when 'buttonContainer' + paddedRules = padRules wrapRules, rules + + if wrap? + bounds = wrap.bounds + else + bounds = node.bounds + + @addButtonContainer + bounds: bounds + depth: depth + 1 + parseContext: rules[0] + classes: paddedRules + buttons: @getButtons(node) + when 'parens' # Parens are assumed to wrap the only child that has children child = null; ok = true @@ -160,7 +175,7 @@ exports.createTreewalkParser = (parse, config, root) -> else bounds = node.bounds - if context? and @detNode(context) is 'block' + if context? and @detNode(context) in ['block', 'buttonContainer'] @addSocket bounds: bounds depth: depth @@ -225,7 +240,7 @@ exports.createTreewalkParser = (parse, config, root) -> for child in node.children @mark child, prefix, depth + 2, false - else if context? and @detNode(context) is 'block' + else if context? and @detNode(context) in ['block', 'buttonContainer'] if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) paddedRules = padRules wrapRules, rules @addSocket diff --git a/src/view.coffee b/src/view.coffee index 68bc2fab..e4639f0b 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -240,6 +240,7 @@ exports.View = class View when 'block' then new BlockViewNode entity, this when 'indent' then new IndentViewNode entity, this when 'socket' then new SocketViewNode entity, this + when 'buttonContainer' then new ContainerViewNode entity, this when 'document' then new DocumentViewNode entity, this # Looks up a color name, or passes through a #hex color. @@ -464,7 +465,7 @@ exports.View = class View top: 0 bottom: if @lineLength > 1 then @view.opts.indentTongueHeight else padding - firstLeft: 0 + firstLeft: padding midLeft: @view.opts.indentWidth lastLeft: @view.opts.indentWidth @@ -1102,7 +1103,7 @@ exports.View = class View @minDistanceToBase[line].above + @minDistanceToBase[line].below - if @model.type is 'block' + if @model.type in ['block', 'buttonContainer'] @extraWidth = 0 if @model.buttons? then for {key} in @model.buttons @@ -1392,6 +1393,46 @@ exports.View = class View }) @highlightArea.deactivate() + @buttonGroups = {} + @buttonPaths = {} + @buttonRects = {} + + if @model.buttons? then for {key, glyph} in @model.buttons + @buttonGroups[key] = new @view.draw.Group() + @buttonPaths[key] = new @view.draw.Path([ + new @view.draw.Point 0, @view.opts.bevelClip + new @view.draw.Point @view.opts.bevelClip, 0 + + new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, 0 + new @view.draw.Point @view.opts.buttonWidth, @view.opts.bevelClip + + new @view.draw.Point @view.opts.buttonWidth, @view.opts.buttonHeight - @view.opts.bevelClip + new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, @view.opts.buttonHeight + + new @view.draw.Point @view.opts.bevelClip, @view.opts.buttonHeight + new @view.draw.Point 0, @view.opts.buttonHeight - @view.opts.bevelClip + ], false, { + fillColor: 'none' + cssClass: 'droplet-button-path' + }) + + @buttonGroups[key].style = {} + + textElement = new @view.draw.Text(new @view.draw.Point( + (@view.opts.buttonWidth - @view.draw.measureCtx.measureText(glyph).width)/ 2, + @view.opts.buttonHeight - @view.opts.textHeight + ), glyph) + @buttonPaths[key].setParent @buttonGroups[key] + textElement.setParent @buttonGroups[key] + + @buttonGroups[key].setParent @group + @elements.push @buttonGroups[key] + + @activeElements.push @buttonPaths[key] + @activeElements.push textElement + @activeElements.push @buttonGroups[key] + + @elements.push @group @elements.push @path @elements.push @highlightArea @@ -1822,7 +1863,11 @@ exports.View = class View lastLine = @bounds.length - 1 lastRect = @bounds[lastLine] - start = lastRect.x + lastRect.width - @extraWidth - @view.opts.padding / 2 + if @model.type is 'block' + start = lastRect.x + lastRect.width - @extraWidth - @view.opts.buttonHorizPadding + else + start = lastRect.x + lastRect.width - @extraWidth + @view.opts.buttonHorizPadding + top = lastRect.y + lastRect.height / 2 - @view.opts.buttonHeight / 2 for {key} in @model.buttons # Cases when last line is MULTILINE @@ -1902,14 +1947,6 @@ exports.View = class View if @path.style.strokeColor isnt 'none' @path.style.strokeColor = avgColor @path.style.strokeColor, 0.5, '#888' - # Change button color - if @model.buttons? then for {key} in @model.buttons - if @buttonPaths[key].active - if @buttonPaths[key].style.fillColor isnt 'none' - @buttonPaths[key].style.fillColor = avgColor @buttonPaths[key].style.fillColor, 0.5, '#888' - if @buttonPaths[key].style.strokeColor isnt 'none' - @buttonPaths[key].style.strokeColor = avgColor @buttonPaths[key].style.strokeColor, 0.5, '#888' - if style.selected # Change path color if @path.style.fillColor isnt 'none' @@ -1917,14 +1954,6 @@ exports.View = class View if @path.style.strokeColor isnt 'none' @path.style.strokeColor = avgColor @path.style.strokeColor, 0.7, '#00F' - # Change button color - if @model.buttons? then for {key} in @model.buttons - if @buttonPaths[key].active - if @buttonPaths[key].style.fillColor isnt 'none' - @buttonPaths[key].style.fillColor = avgColor @buttonPaths[key].style.fillColor, 0.7, '#00F' - if @buttonPaths[key].style.strokeColor isnt 'none' - @buttonPaths[key].style.strokeColor = avgColor @buttonPaths[key].style.strokeColor, 0.7, '#00F' - @path.setMarkStyle @markStyle @path.update() @@ -1963,45 +1992,6 @@ exports.View = class View constructor: -> super - @buttonGroups = {} - @buttonPaths = {} - @buttonRects = {} - - if @model.buttons? then for {key, glyph, border} in @model.buttons - @buttonGroups[key] = new @view.draw.Group() - @buttonPaths[key] = new @view.draw.Path([ - new @view.draw.Point 0, @view.opts.bevelClip - new @view.draw.Point @view.opts.bevelClip, 0 - - new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, 0 - new @view.draw.Point @view.opts.buttonWidth, @view.opts.bevelClip - - new @view.draw.Point @view.opts.buttonWidth, @view.opts.buttonHeight - @view.opts.bevelClip - new @view.draw.Point @view.opts.buttonWidth - @view.opts.bevelClip, @view.opts.buttonHeight - - new @view.draw.Point @view.opts.bevelClip, @view.opts.buttonHeight - new @view.draw.Point 0, @view.opts.buttonHeight - @view.opts.bevelClip - ], border ? true, { - fillColor: @view.getColor(@model.color) - cssClass: 'droplet-button-path' - }) - - @buttonGroups[key].style = {} - - textElement = new @view.draw.Text(new @view.draw.Point( - (@view.opts.buttonWidth - @view.draw.measureCtx.measureText(glyph).width)/ 2, - @view.opts.buttonHeight - @view.opts.textHeight - ), glyph) - @buttonPaths[key].setParent @buttonGroups[key] - textElement.setParent @buttonGroups[key] - - @buttonGroups[key].setParent @group - @elements.push @buttonGroups[key] - - @activeElements.push @buttonPaths[key] - @activeElements.push textElement - @activeElements.push @buttonGroups[key] - computeMinDimensions: -> if @computedVersion is @model.version return null @@ -2169,11 +2159,7 @@ exports.View = class View not @changedBoundingBox return @path - if @model.start.next.type is 'blockStart' - @path.style.fill = 'none' - - # Otherwise, call super. - else + unless @model.start.next.type is 'blockStart' super # If the socket is empty, make it invisible except @@ -2183,7 +2169,10 @@ exports.View = class View @path.style.fillColor = 'none' else @path.style.cssClass = 'droplet-socket-path' - @path.style.fillColor = '#FFF' + if @model.start.next.type is 'blockStart' + @path.style.fillColor = 'none' + else + @path.style.fillColor = '#FFF' return @path From 67056a23027abd7d8023a39e200a9204bdd15cb4 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 12 Jul 2016 16:15:18 -0400 Subject: [PATCH 24/60] Center glyphs in buttons --- src/view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/view.coffee b/src/view.coffee index e4639f0b..f53a9dbb 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1420,7 +1420,7 @@ exports.View = class View textElement = new @view.draw.Text(new @view.draw.Point( (@view.opts.buttonWidth - @view.draw.measureCtx.measureText(glyph).width)/ 2, - @view.opts.buttonHeight - @view.opts.textHeight + (@view.opts.buttonHeight - @view.opts.textHeight) / 2 ), glyph) @buttonPaths[key].setParent @buttonGroups[key] textElement.setParent @buttonGroups[key] From 8689eea55cc38278c699bb7771b7b4fa289810c1 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 13 Jul 2016 01:19:16 -0400 Subject: [PATCH 25/60] python block drop encourage/discourage at document level (WIP) --- src/treewalk.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/treewalk.coffee b/src/treewalk.coffee index e95d06a7..1ea0fa8a 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -249,6 +249,11 @@ exports.createTreewalkParser = (parse, config, root) -> 'translationUnit' in parseClasses(block) return helper.ENCOURAGE + # Python-specific? + if 'small_stmt' in parseClasses(block) or + 'compound_stmt' in parseClasses(block) + return helper.ENCOURAGE + return helper.DISCOURAGE return helper.DISCOURAGE From 1ec6e1e0d6d9da66651ed21bef27ab3b8b7afa43 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 13 Jul 2016 19:24:57 -0400 Subject: [PATCH 26/60] python mode block drop to/from indent issue --- src/languages/python.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index 2bf4ee98..f7cb7e2c 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -134,7 +134,7 @@ config = { # 'suite': 'indent', 'suite': { 'type': 'indent', - 'indentContext': 'blockItem' + 'indentContext': 'small_stmt' } # Parens @@ -159,6 +159,8 @@ config = { 'T_STRING': 'socket' } + PAREN_RULES: {} + BLOCK_TOKENS: [], PLAIN_SOCKETS: [], VALUE_TYPES: [], BLOCK_TYPES: [] DROPDOWN_CALLBACK: getDropdown COLOR_CALLBACK: getColor From 97c37e444096a720dc987a5096479430c896bb61 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 14 Jul 2016 15:23:19 -0400 Subject: [PATCH 27/60] Move to new architecture for droppability rules and shapes --- package.json | 5 +- src/antlr.coffee | 12 +++++ src/controller.coffee | 19 ++++---- src/helper.coffee | 14 ++++++ src/languages/c.coffee | 50 ++++++++++---------- src/model.coffee | 35 ++++++-------- src/parser.coffee | 23 ++++------ src/treewalk.coffee | 102 +++++++++++------------------------------ src/view.coffee | 3 +- 9 files changed, 117 insertions(+), 146 deletions(-) diff --git a/package.json b/package.json index 8b2815c6..4f6d59af 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,9 @@ "homepage": "https://github.com/dabbler0/droplet", "dependencies": { "acorn": "^1.2.2", - "sax": "^1.1.1", "antlr4": "latest", - "parse5": "latest" + "node-dijkstra": "^1.1.3", + "parse5": "latest", + "sax": "^1.1.1" } } diff --git a/src/antlr.coffee b/src/antlr.coffee index 623dd41a..f186cc74 100644 --- a/src/antlr.coffee +++ b/src/antlr.coffee @@ -12,8 +12,11 @@ antlr4 = require 'antlr4' ANTLR_PARSER_COLLECTION = { 'JavaLexer': require('../antlr/JavaLexer'), 'JavaParser': require('../antlr/JavaParser'), + 'CLexer': require('../antlr/CLexer'), 'CParser': require('../antlr/CParser'), + 'CDroppabilityGraph': require('../antlr/CDroppabilityGraph.json'), + 'jvmBasicLexer': require('../antlr/jvmBasicLexer'), 'jvmBasicParser': require('../antlr/jvmBasicParser'), } @@ -95,4 +98,13 @@ exports.createANTLRParser = (name, config, root) -> } } + droppabilityGraph = ANTLR_PARSER_COLLECTION["#{name}DroppabilityGraph"] + if droppabilityGraph? + config.droppabilityGraph = {} + for rule, edges of droppabilityGraph + config.droppabilityGraph[rule] ={} + for outEdge in edges when outEdge isnt 0 + config.droppabilityGraph[rule][outEdge] = 1 + console.log 'set droppability graph', droppabilityGraph + return treewalk.createTreewalkParser parse, config, root diff --git a/src/controller.coffee b/src/controller.coffee index 985805a8..a8e89030 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1192,7 +1192,7 @@ Editor::prepareNode = (node, context) -> else trailing = node.getTrailingText() - [leading, trailing, classes] = @session.mode.parens leading, trailing, node.getReader(), + [leading, trailing] = @session.mode.parens leading, trailing, node.getReader(), context?.getReader?() ? null node.setLeadingText leading; node.setTrailingText trailing @@ -1428,8 +1428,7 @@ hook 'mousemove', 1, (point, event, state) -> if 'function' is typeof @clickedBlockPaletteEntry.expansion # Any block generated from an expansion function should be treated as # any-drop because it can change with subsequent expansion() calls. - if 'mostly-value' in @draggingBlock.classes - @draggingBlock.classes.push 'any-drop' + @draggingBlock.shape = helper.ANY_DROP # Attach expansion() function and lastExpansionText to @draggingBlock. @draggingBlock.lastExpansionText = expansion @@ -1617,8 +1616,8 @@ hook 'mousemove', 0, (point, event, state) -> newBlock = parseBlock(@session.mode, expansionText) newBlock.lastExpansionText = expansionText newBlock.expansion = @draggingBlock.expansion - if 'any-drop' in @draggingBlock.classes - newBlock.classes.push 'any-drop' + newBlock.shape = @draggingBlock.shape + @draggingBlock = newBlock @drawDraggingBlock() @@ -3026,7 +3025,7 @@ Editor::setCursor = (destination, validate = (-> true), direction = 'after') -> # If the cursor was at a text input, reparse the old one if @cursorAtSocket() and not @session.cursor.is(destination) socket = @getCursor() - if '__comment__' not in socket.classes + if '__comment__' isnt socket.parseContext @reparse socket, null, (if destination.document is @session.cursor.document then [destination.location] else []) @hiddenInput.blur() @dropletElement.focus() @@ -3230,15 +3229,15 @@ hook 'keydown', 0, (event, state) -> @dropletElement.focus() @setCursor @session.cursor, (token) -> token.type isnt 'socketStart' @redrawMain() - if '__comment__' in socket.classes and @session.mode.startSingleLineComment + if '__comment__' is socket.parseContext and @session.mode.startSingleLineComment # Create another single line comment block just below - newBlock = new model.Block 0, 'blank', helper.ANY_DROP - newBlock.classes = ['__comment__', 'block-only'] + newBlock = new model.Block 0, 'blank', helper.BLOCK_ONLY + newBlock.parseContext = '__comment__' newBlock.socketLevel = helper.BLOCK_ONLY newTextMarker = new model.TextToken @session.mode.startSingleLineComment newTextMarker.setParent newBlock newSocket = new model.Socket '', 0, true - newSocket.classes = ['__comment__'] + newSocket.parseContext = '__comment__' newSocket.setParent newBlock helper.connect newBlock.start, newTextMarker diff --git a/src/helper.coffee b/src/helper.coffee index 5b1528f5..869eee78 100644 --- a/src/helper.coffee +++ b/src/helper.coffee @@ -250,3 +250,17 @@ exports.PairDict = class PairDict @pairs.push [index, value] return false +dfs = (graph, a, b, visited = {}) -> + console.log 'DFS', a + visited[a] = true + for out_edge of graph.vertices[a] + if out_edge is b + console.log 'AND', b + console.log '--SUCCESS--' + return true + else if dfs(graph, out_edge, b, visited) + return true + console.log '--DEAD END--' + return false + +exports.dfs = dfs diff --git a/src/languages/c.coffee b/src/languages/c.coffee index f3f045c1..2ac8f79d 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -81,31 +81,31 @@ COLOR_RULES = [ ] SHAPE_RULES = [ - ['blockItem', 'block-only'], # Any statement, like `return 0;` - ['expression', 'value-only'], # Any expression, like `a + b` - ['postfixExpression', 'block-only'], # e.g. `a(b, c);` OR `a++` - ['equalityExpression', 'value-only'], # e.g. `a == b` - ['logicalAndExpression', 'value-only'], # e.g. `a && b` - ['logicalOrExpression', 'value-only'], # e.g. `a || b` - ['iterationStatement', 'block-only'], # e.g. `for (int i = 0; i < 10; i++) { }` - ['selectionStatement', 'block-only'], # e.g. if `(a) { } else { }` OR `switch (a) { }` - ['assignmentExpression', 'block-only'], # e.g. `a = b;` OR `a = b` - ['relationalExpression', 'value-only'], # e.g. `a < b` - ['initDeclarator', 'block-only'], # e.g. `a = b` when inside `int a = b;` - ['externalDeclaration', 'block-only'], # e.g. `int a = b` when global - ['structDeclaration', 'block-only'], # e.g. `struct a { }` - ['declarationSpecifier', 'block-only'], # e.g. `int` when in `int a = b;` - ['statement', 'block-only'], # Any statement, like `return 0;` - ['functionDefinition', 'block-only'], # e.g. `int myMethod() { }` - ['expressionStatement', 'block-only'], # Statement that consists of an expression, like `a = b;` - ['additiveExpression', 'value-only'], # e.g. `a + b` - ['multiplicativeExpression', 'value-only'], # e.g. `a * b` - ['declaration', 'block-only'], # e.g. `int a;` - ['parameterDeclaration', 'block-only'], # e.g. `int a` when in `int myMethod(int a) { }` - ['unaryExpression', 'value-only'], # e.g. `sizeof(a)` - ['typeName', 'value-only'], # e.g. `int` - ['initializer', 'value-only'], # e.g. `{a, b, c}` when in `int x[] = {a, b, c};` - ['castExpression', 'value-only'] # e.g. `(b)a` + ['blockItem', helper.BLOCK_ONLY], # Any statement, like `return 0;` + ['expression', helper.VALUE_ONLY], # Any expression, like `a + b` + ['postfixExpression', helper.BLOCK_ONLY], # e.g. `a(b, c);` OR `a++` + ['equalityExpression', helper.VALUE_ONLY], # e.g. `a == b` + ['logicalAndExpression', helper.VALUE_ONLY], # e.g. `a && b` + ['logicalOrExpression', helper.VALUE_ONLY], # e.g. `a || b` + ['iterationStatement', helper.BLOCK_ONLY], # e.g. `for (int i = 0; i < 10; i++) { }` + ['selectionStatement', helper.BLOCK_ONLY], # e.g. if `(a) { } else { }` OR `switch (a) { }` + ['assignmentExpression', helper.BLOCK_ONLY], # e.g. `a = b;` OR `a = b` + ['relationalExpression', helper.VALUE_ONLY], # e.g. `a < b` + ['initDeclarator', helper.BLOCK_ONLY], # e.g. `a = b` when inside `int a = b;` + ['externalDeclaration', helper.BLOCK_ONLY], # e.g. `int a = b` when global + ['structDeclaration', helper.BLOCK_ONLY], # e.g. `struct a { }` + ['declarationSpecifier', helper.BLOCK_ONLY], # e.g. `int` when in `int a = b;` + ['statement', helper.BLOCK_ONLY], # Any statement, like `return 0;` + ['functionDefinition', helper.BLOCK_ONLY], # e.g. `int myMethod() { }` + ['expressionStatement', helper.BLOCK_ONLY], # Statement that consists of an expression, like `a = b;` + ['additiveExpression', helper.VALUE_ONLY], # e.g. `a + b` + ['multiplicativeExpression', helper.VALUE_ONLY], # e.g. `a * b` + ['declaration', helper.BLOCK_ONLY], # e.g. `int a;` + ['parameterDeclaration', helper.BLOCK_ONLY], # e.g. `int a` when in `int myMethod(int a) { }` + ['unaryExpression', helper.VALUE_ONLY], # e.g. `sizeof(a)` + ['typeName', helper.VALUE_ONLY], # e.g. `int` + ['initializer', helper.VALUE_ONLY], # e.g. `{a, b, c}` when in `int x[] = {a, b, c};` + ['castExpression', helper.VALUE_ONLY] # e.g. `(b)a` ] config = { diff --git a/src/model.coffee b/src/model.coffee index f89c319f..a46b9e67 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -370,7 +370,7 @@ exports.List = class List return @end.next in [@parent?.end, @parent?.parent?.end, null] or @end.next?.type in ['newline', 'indentStart', 'indentEnd'] - getReader: -> {type: 'document', classes: []} + getReader: -> {type: 'document', indentContext: @indentContext} setParent: (parent) -> traverseOneLevel @start, ((head)-> @@ -504,7 +504,8 @@ exports.Container = class Container extends List id: @id type: @type precedence: @precedence - classes: @classes + shape: @shape + indentContext: @indentContext parseContext: @parseContext } @@ -983,7 +984,7 @@ exports.BlockEndToken = class BlockEndToken extends EndToken serialize: -> "" exports.Block = class Block extends Container - constructor: (@precedence = 0, @color = 'blank', @socketLevel = helper.ANY_DROP, @classes = [], @parseContext, @buttons = {}) -> + constructor: (@precedence = 0, @color = 'blank', @shape = helper.ANY_DROP, @parseContext, @buttons = {}) -> @start = new BlockStartToken this @end = new BlockEndToken this @@ -1001,16 +1002,16 @@ exports.Block = class Block extends Container return null _cloneEmpty: -> - clone = new Block @precedence, @color, @socketLevel, @classes, @parseContext, @buttons + clone = new Block @precedence, @color, @shape, @parseContext, @buttons clone.currentlyParenWrapped = @currentlyParenWrapped return clone _serialize_header: -> "" _serialize_footer: -> "" @@ -1047,9 +1048,6 @@ exports.Socket = class Socket extends Container # This determines whether it can be deleted again by pressing delete when the socket is empty. @handwritten = false, - # @classes -- passed to mode callbacks for droppability and parentheses callbacks - @classes = [], - # @dropdown -- dropdown options, if they exist @dropdown = null, @@ -1077,15 +1075,13 @@ exports.Socket = class Socket extends Container isDroppable: -> @start.next is @end or @start.next.type is 'text' - _cloneEmpty: -> new Socket @emptyString, @precedence, @handwritten, @classes, @dropdown, @parseContext + _cloneEmpty: -> new Socket @emptyString, @precedence, @handwritten, @dropdown, @parseContext _serialize_header: -> " "" exports.Indent = class Indent extends Container - constructor: (@emptyString, @prefix = '', @classes = [], @parseContext = null) -> + constructor: (@emptyString, @prefix = '', @indentContext = null) -> @start = new IndentStartToken this @end = new IndentEndToken this @@ -1120,13 +1116,13 @@ exports.Indent = class Indent extends Container super - _cloneEmpty: -> new Indent @emptyString, @prefix, @classes, @parseContext + _cloneEmpty: -> new Indent @emptyString, @prefix, @indentContext firstChild: -> return @_firstChild() _serialize_header: -> "" _serialize_footer: -> "" @@ -1143,10 +1139,9 @@ exports.DocumentEndToken = class DocumentEndToken extends EndToken serialize: -> "" exports.Document = class Document extends Container - constructor: (@opts = {}) -> + constructor: (@opts = {}, @indentContext = null) -> @start = new DocumentStartToken this @end = new DocumentEndToken this - @classes = ['__document__'] @type = 'document' diff --git a/src/parser.coffee b/src/parser.coffee index 4dc24b03..c96dea33 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -97,8 +97,7 @@ exports.Parser = class Parser addBlock: (opts) -> block = new model.Block opts.precedence, opts.color, - opts.socketLevel, - opts.classes, + opts.shape, opts.parseContext, opts.buttons @@ -129,7 +128,6 @@ exports.Parser = class Parser addSocket: (opts) -> socket = new model.Socket opts.empty ? @empty, opts.precedence, false, - opts.classes, opts.dropdown, opts.parseContext @@ -145,7 +143,7 @@ exports.Parser = class Parser # prefix: String # } addIndent: (opts) -> - indent = new model.Indent @emptyIndent, opts.prefix, opts.classes, opts.parseContext + indent = new model.Indent @emptyIndent, opts.prefix, opts.indentContext @addMarkup indent, opts.bounds, opts.depth @@ -223,7 +221,8 @@ exports.Parser = class Parser block = new model.Block 0, 'comment', helper.ANY_DROP if @isComment text block.socketLevel = helper.BLOCK_ONLY - block.classes = ['__comment__', 'block-only'] + block.shape = helper.BLOCK_ONLY + block.parseContext = '__comment__' head = block.start @@ -239,8 +238,6 @@ exports.Parser = class Parser socket = new model.Socket '', 0, true socket.setParent block - socket.classes = ['__comment__'] - padText = text[lastPosition...socketPosition[0]] if padText.length > 0 @@ -279,7 +276,7 @@ exports.Parser = class Parser textToken = new model.TextToken text textToken.setParent socket - block.classes = ['__handwritten__', 'block-only'] + block.shape = helper.BLOCK_ONLY helper.connect block.start, socket.start helper.connect socket.start, textToken @@ -394,7 +391,8 @@ exports.Parser = class Parser if line.length is 0 and not placedSomething and stack[stack.length - 1]?.type in ['indent', 'document', undefined] and hasSomeTextAfter(lines, i) block = new model.Block 0, @opts.emptyLineColor, helper.BLOCK_ONLY - block.classes = ['__comment__', 'any-drop'] + block.shape = helper.ANY_DROP + block.parseContext = '__comment__' head = helper.connect head, block.start head = helper.connect head, block.end @@ -540,12 +538,11 @@ exports.parseXML = (xml) -> switch node.name when 'block' container = new model.Block attributes.precedence, attributes.color, - attributes.socketLevel, attributes.classes?.split?(' ') + attributes.shape, attributes.parseContext when 'socket' - container = new model.Socket '', attributes.precedence, attributes.handritten, - attributes.classes?.split?(' ') + container = new model.Socket '', attributes.precedence, attributes.handritten, attributes.parseContext when 'indent' - container = new model.Indent '', attributes.prefix, attributes.classes?.split?(' ') + container = new model.Indent '', attributes.prefix, attributes.indentContext when 'document' # Root is optional unless stack.length is 0 diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 79b3a70d..bef9cdbf 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -6,6 +6,8 @@ helper = require './helper.coffee' model = require './model.coffee' parser = require './parser.coffee' +Graph = require 'node-dijkstra' + exports.createTreewalkParser = (parse, config, root) -> class TreewalkParser extends parser.Parser constructor: (@text, @opts = {}) -> @@ -75,9 +77,9 @@ exports.createTreewalkParser = (parse, config, root) -> if shapeRule[0] of rulesSet return shapeRule[1] - return 'any-drop' + return helper.ANY_DROP - mark: (node, prefix, depth, pass, rules, context, wrap, wrapRules) -> + mark: (node, prefix, depth, pass, rules, context, wrap) -> unless pass context = node.parent while context? and @detNode(context) in ['skip', 'parens'] @@ -85,11 +87,13 @@ exports.createTreewalkParser = (parse, config, root) -> rules ?= [] rules = rules.slice 0 - rules.push node.type + + unless wrap? + rules.push node.type # Pass through to child if single-child if node.children.length is 1 and @detNode(node) isnt 'indent' - @mark node.children[0], prefix, depth, true, rules, context, wrap, wrapRules + @mark node.children[0], prefix, depth, true, rules, context, wrap else if node.children.length > 0 switch @detNode node @@ -103,15 +107,14 @@ exports.createTreewalkParser = (parse, config, root) -> @addSocket bounds: bounds depth: depth - classes: padRules(wrapRules ? rules) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + parseContext: rules[0] @addBlock bounds: bounds depth: depth + 1 color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + shape: @getShape node, rules + parseContext: rules[rules.length - 1] when 'parens' # Parens are assumed to wrap the only child that has children @@ -124,7 +127,7 @@ exports.createTreewalkParser = (parse, config, root) -> else child = el if ok - @mark child, prefix, depth, true, rules, context, wrap ? node, wrapRules ? rules + @mark child, prefix, depth, true, rules, context, wrap ? node return else @@ -139,15 +142,14 @@ exports.createTreewalkParser = (parse, config, root) -> @addSocket bounds: bounds depth: depth - classes: padRules(wrapRules ? rules) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + parseContext: rules[0] @addBlock bounds: bounds depth: depth + 1 color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + shape: @getShape node, rules + parseContext: rules[rules.length - 1] when 'indent' # A lone indent needs to be wrapped in a block. @@ -156,8 +158,8 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: node.bounds depth: depth color: @getColor node, rules - classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + shape: @getShape node, rules + parseContext: rules[rules.length - 1] depth += 1 @@ -191,8 +193,7 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth prefix: prefix[oldPrefix.length...prefix.length] - classes: padRules(wrapRules ? rules) - parseContext: @applyRule(config.RULES[node.type], node).indentContext + indentContext: @applyRule(config.RULES[node.type], node).indentContext for child in node.children @mark child, prefix, depth + 2, false @@ -201,75 +202,28 @@ exports.createTreewalkParser = (parse, config, root) -> @addSocket bounds: node.bounds depth: depth - classes: padRules(wrapRules ? rules) - parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) + parseContext: rules[0] if config.empty? and not @opts.preserveEmpty and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.empty @flagToRemove node.bounds, depth + 1 - TreewalkParser.drop = (block, context, pred) -> - if context.type is 'socket' - if '__comment__' in block.classes - return helper.DISCOURAGE - for c in parseClasses(context) - if c in parseClasses(block) - return helper.ENCOURAGE - - # Check to see if we could paren-wrap this - if config.PAREN_RULES? and c of config.PAREN_RULES - for m in parseClasses(block) - if m of config.PAREN_RULES[c] - return helper.ENCOURAGE - return helper.DISCOURAGE - - else if context.type is 'indent' - if '__comment__' in block.classes - return helper.ENCOURAGE - - if context.parseContext in parseClasses(block) - return helper.ENCOURAGE - - return helper.DISCOURAGE - - else if context.type is 'document' - if '__comment__' in block.classes - return helper.ENCOURAGE - - if 'externalDeclaration' in parseClasses(block) or - 'translationUnit' in parseClasses(block) + if config.droppabilityGraph? + droppabilityGraph = new Graph(config.droppabilityGraph) + TreewalkParser.drop = (block, context, pred) -> + parseContext = context.indentContext ? context.parseContext + if helper.dfs(droppabilityGraph, parseContext, block.parseContext) return helper.ENCOURAGE + else + return helper.FORBID - return helper.DISCOURAGE - - return helper.DISCOURAGE - + else if config.drop? + TreewalkParser.drop = config.drop # Doesn't yet deal with parens TreewalkParser.parens = (leading, trailing, node, context)-> - # If we're moving to null, remove parens (where possible) - unless context? - if config.unParenWrap? - return config.unParenWrap leading, trailing, node, context - else - return - - - # If we already match types, we're fine - for c in parseClasses(context) - if c in parseClasses(node) - return - - # Otherwise, wrap according to the provided rule - for c in parseClasses(context) when c of config.PAREN_RULES - for m in parseClasses(node) when m of config.PAREN_RULES[c] - return config.PAREN_RULES[c][m] leading, trailing, node, context TreewalkParser.stringFixer = config.stringFixer TreewalkParser.getDefaultSelectionRange = config.getDefaultSelectionRange TreewalkParser.empty = config.empty return TreewalkParser - -PARSE_PREFIX = "__parse__" -padRules = (rules) -> rules.map (x) -> "#{PARSE_PREFIX}#{x}" -parseClasses = (node) -> node.classes.filter((x) -> x[...PARSE_PREFIX.length] is PARSE_PREFIX).map((x) -> x[PARSE_PREFIX.length..]) diff --git a/src/view.coffee b/src/view.coffee index 30c122fa..9c8bc3c1 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1974,8 +1974,7 @@ exports.View = class View @model.start.prev is @model.parent.start and @model.end.next is @model.parent.end) return @model.parent?.type isnt 'socket' else - return not ('mostly-value' in @model.classes or - 'value-only' in @model.classes) + return not (@model.shape in [helper.MOSTLY_VALUE, helper.VALUE_ONLY]) computeOwnDropArea: -> return unless @model.parent?.type in ['indent', 'document'] From cc52ddffdd64d72052cbb022629a6038aa518553 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 14 Jul 2016 15:24:48 -0400 Subject: [PATCH 28/60] Fix bug where you can't drag something if it matches the context exactly --- src/helper.coffee | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/helper.coffee b/src/helper.coffee index 869eee78..4a94abbf 100644 --- a/src/helper.coffee +++ b/src/helper.coffee @@ -251,16 +251,12 @@ exports.PairDict = class PairDict return false dfs = (graph, a, b, visited = {}) -> - console.log 'DFS', a + if a is b + return true visited[a] = true for out_edge of graph.vertices[a] - if out_edge is b - console.log 'AND', b - console.log '--SUCCESS--' - return true - else if dfs(graph, out_edge, b, visited) + if dfs(graph, out_edge, b, visited) return true - console.log '--DEAD END--' return false exports.dfs = dfs From 2d4cc64d0e585809074530e9fd9e30f6a26a17dc Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 14 Jul 2016 17:07:30 -0400 Subject: [PATCH 29/60] Add parenthesis rules --- src/antlr.coffee | 10 ++- src/controller.coffee | 14 ++-- src/helper.coffee | 6 +- src/languages/c.coffee | 151 ++++++++++++++++++++++------------------- src/model.coffee | 4 +- src/parser.coffee | 27 ++------ src/treewalk.coffee | 69 +++++++++++-------- 7 files changed, 154 insertions(+), 127 deletions(-) diff --git a/src/antlr.coffee b/src/antlr.coffee index f186cc74..949e2c95 100644 --- a/src/antlr.coffee +++ b/src/antlr.coffee @@ -101,10 +101,16 @@ exports.createANTLRParser = (name, config, root) -> droppabilityGraph = ANTLR_PARSER_COLLECTION["#{name}DroppabilityGraph"] if droppabilityGraph? config.droppabilityGraph = {} + config.parenGraph = {} for rule, edges of droppabilityGraph config.droppabilityGraph[rule] ={} + config.parenGraph[rule] = {} for outEdge in edges when outEdge isnt 0 - config.droppabilityGraph[rule][outEdge] = 1 - console.log 'set droppability graph', droppabilityGraph + config.droppabilityGraph[rule][outEdge] = 0 + config.parenGraph[rule][outEdge] = 0 + + for dest of config.PAREN_RULES + for source of config.PAREN_RULES[dest] + config.parenGraph[dest][source] = 1 return treewalk.createTreewalkParser parse, config, root diff --git a/src/controller.coffee b/src/controller.coffee index a8e89030..c1dd6801 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -131,7 +131,7 @@ class Session # ## Document initialization # We start of with an empty document - @tree = new model.Document() + @tree = new model.Document(@mode.rootContext) # Line markings @markedLines = {} @@ -1192,11 +1192,14 @@ Editor::prepareNode = (node, context) -> else trailing = node.getTrailingText() - [leading, trailing] = @session.mode.parens leading, trailing, node.getReader(), - context?.getReader?() ? null + [leading, trailing, parseContext] = @session.mode.parens( + leading, trailing, + node.getReader(), context?.getReader?() ? null + ) node.setLeadingText leading; node.setTrailingText trailing + node.parseContext = parseContext # At population-time, we will # want to set up a few fields. @@ -1921,7 +1924,10 @@ hook 'mouseup', 0, (point, event, state) -> # Add the undo operation associated # with creating this floating block - newDocument = new model.Document({roundedSingletons: true}) + newDocument = new model.Document( + (@draggingBlock.parent?.indentContext ? @draggingBlock.parseContext), + {roundedSingletons: true} + ) newDocument.insert newDocument.start, @draggingBlock @pushUndo new FloatingOperation @session.floatingBlocks.length, newDocument, renderPoint, 'create' diff --git a/src/helper.coffee b/src/helper.coffee index 4a94abbf..f41669b5 100644 --- a/src/helper.coffee +++ b/src/helper.coffee @@ -251,9 +251,13 @@ exports.PairDict = class PairDict return false dfs = (graph, a, b, visited = {}) -> + if visited[a] + return false + visited[a] = true + if a is b return true - visited[a] = true + for out_edge of graph.vertices[a] if dfs(graph, out_edge, b, visited) return true diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 2ac8f79d..d5625607 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -51,78 +51,95 @@ RULES = { 'Constant': 'socket' } -COLOR_RULES = [ - ['jumpStatement', 'return'] # e.g. `return 0;` - ['declaration', 'control'], # e.g. `int a;` - ['specialMethodCall', 'command'], # e.g. `a(b);` - ['equalityExpression', 'value'] # e.g. `a == b` - ['additiveExpression', 'value'], # e.g. `a + b` - ['multiplicativeExpression', 'value'], # e.g. `a * b` - ['postfixExpression', 'command'], # e.g. `a(b, c);` OR `a++` - ['iterationStatement', 'control'], # e.g. `for (int i = 0; i < 10; i++) { }` - ['selectionStatement', 'control'], # e.g. if `(a) { } else { }` OR `switch (a) { }` - ['assignmentExpression', 'command'], # e.g. `a = b;` OR `a = b` - ['relationalExpression', 'value'], # e.g. `a < b` - ['initDeclarator', 'command'], # e.g. `a = b` when inside `int a = b;` - ['blockItemList', 'control'], # List of commands - ['compoundStatement', 'control'], # List of commands inside braces - ['externalDeclaration', 'control'], # e.g. `int a = b` when global - ['structDeclaration', 'command'], # e.g. `struct a { }` - ['declarationSpecifier', 'control'], # e.g. `int` when in `int a = b;` - ['statement', 'command'], # Any statement, like `return 0;` - ['functionDefinition', 'control'], # e.g. `int myMethod() { }` - ['expressionStatement', 'command'], # Statement that consists of an expression, like `a = b;` - ['expression', 'value'], # Any expression, like `a + b` - ['parameterDeclaration', 'command'], # e.g. `int a` when in `int myMethod(int a) { }` - ['unaryExpression', 'value'], # e.g. `sizeof(a)` - ['typeName', 'value'], # e.g. `int` - ['initializer', 'value'], # e.g. `{a, b, c}` when in `int x[] = {a, b, c};` - ['castExpression', 'value'] # e.g. `(b)a` -] - -SHAPE_RULES = [ - ['blockItem', helper.BLOCK_ONLY], # Any statement, like `return 0;` - ['expression', helper.VALUE_ONLY], # Any expression, like `a + b` - ['postfixExpression', helper.BLOCK_ONLY], # e.g. `a(b, c);` OR `a++` - ['equalityExpression', helper.VALUE_ONLY], # e.g. `a == b` - ['logicalAndExpression', helper.VALUE_ONLY], # e.g. `a && b` - ['logicalOrExpression', helper.VALUE_ONLY], # e.g. `a || b` - ['iterationStatement', helper.BLOCK_ONLY], # e.g. `for (int i = 0; i < 10; i++) { }` - ['selectionStatement', helper.BLOCK_ONLY], # e.g. if `(a) { } else { }` OR `switch (a) { }` - ['assignmentExpression', helper.BLOCK_ONLY], # e.g. `a = b;` OR `a = b` - ['relationalExpression', helper.VALUE_ONLY], # e.g. `a < b` - ['initDeclarator', helper.BLOCK_ONLY], # e.g. `a = b` when inside `int a = b;` - ['externalDeclaration', helper.BLOCK_ONLY], # e.g. `int a = b` when global - ['structDeclaration', helper.BLOCK_ONLY], # e.g. `struct a { }` - ['declarationSpecifier', helper.BLOCK_ONLY], # e.g. `int` when in `int a = b;` - ['statement', helper.BLOCK_ONLY], # Any statement, like `return 0;` - ['functionDefinition', helper.BLOCK_ONLY], # e.g. `int myMethod() { }` - ['expressionStatement', helper.BLOCK_ONLY], # Statement that consists of an expression, like `a = b;` - ['additiveExpression', helper.VALUE_ONLY], # e.g. `a + b` - ['multiplicativeExpression', helper.VALUE_ONLY], # e.g. `a * b` - ['declaration', helper.BLOCK_ONLY], # e.g. `int a;` - ['parameterDeclaration', helper.BLOCK_ONLY], # e.g. `int a` when in `int myMethod(int a) { }` - ['unaryExpression', helper.VALUE_ONLY], # e.g. `sizeof(a)` - ['typeName', helper.VALUE_ONLY], # e.g. `int` - ['initializer', helper.VALUE_ONLY], # e.g. `{a, b, c}` when in `int x[] = {a, b, c};` - ['castExpression', helper.VALUE_ONLY] # e.g. `(b)a` -] +COLOR_RULES = { + 'jumpStatement': 'return' # e.g. `return 0;` + 'declaration': 'control', # e.g. `int a;` + 'specialMethodCall': 'command', # e.g. `a(b);` + 'equalityExpression': 'value' # e.g. `a == b` + 'additiveExpression': 'value', # e.g. `a + b` + 'multiplicativeExpression': 'value', # e.g. `a * b` + 'postfixExpression': 'command', # e.g. `a(b, c);` OR `a++` + 'iterationStatement': 'control', # e.g. `for (int i = 0; i < 10; i++) { }` + 'selectionStatement': 'control', # e.g. if `(a) { } else { }` OR `switch (a) { }` + 'assignmentExpression': 'command', # e.g. `a = b;` OR `a = b` + 'relationalExpression': 'value', # e.g. `a < b` + 'initDeclarator': 'command', # e.g. `a = b` when inside `int a = b;` + 'blockItemList': 'control', # List of commands + 'compoundStatement': 'control', # List of commands inside braces + 'externalDeclaration': 'control', # e.g. `int a = b` when global + 'structDeclaration': 'command', # e.g. `struct a { }` + 'declarationSpecifier': 'control', # e.g. `int` when in `int a = b;` + 'statement': 'command', # Any statement, like `return 0;` + 'functionDefinition': 'control', # e.g. `int myMethod() { }` + 'expressionStatement': 'command', # Statement that consists of an expression, like `a = b;` + 'expression': 'value', # Any expression, like `a + b` + 'parameterDeclaration': 'command', # e.g. `int a` when in `int myMethod(int a) { }` + 'unaryExpression': 'value', # e.g. `sizeof(a)` + 'typeName': 'value', # e.g. `int` + 'initializer': 'value', # e.g. `{a, b, c}` when in `int x[] = {a, b, c};` + 'castExpression': 'value' # e.g. `(b)a` +} + +SHAPE_RULES = { + 'blockItem': helper.BLOCK_ONLY, # Any statement, like `return 0;` + 'expression': helper.VALUE_ONLY, # Any expression, like `a + b` + 'postfixExpression': helper.BLOCK_ONLY, # e.g. `a(b, c);` OR `a++` + 'equalityExpression': helper.VALUE_ONLY, # e.g. `a == b` + 'logicalAndExpression': helper.VALUE_ONLY, # e.g. `a && b` + 'logicalOrExpression': helper.VALUE_ONLY, # e.g. `a || b` + 'iterationStatement': helper.BLOCK_ONLY, # e.g. `for (int i = 0; i < 10; i++) { }` + 'selectionStatement': helper.BLOCK_ONLY, # e.g. if `(a) { } else { }` OR `switch (a) { }` + 'assignmentExpression': helper.BLOCK_ONLY, # e.g. `a = b;` OR `a = b` + 'relationalExpression': helper.VALUE_ONLY, # e.g. `a < b` + 'initDeclarator': helper.BLOCK_ONLY, # e.g. `a = b` when inside `int a = b;` + 'externalDeclaration': helper.BLOCK_ONLY, # e.g. `int a = b` when global + 'structDeclaration': helper.BLOCK_ONLY, # e.g. `struct a { }` + 'declarationSpecifier': helper.BLOCK_ONLY, # e.g. `int` when in `int a = b;` + 'statement': helper.BLOCK_ONLY, # Any statement, like `return 0;` + 'functionDefinition': helper.BLOCK_ONLY, # e.g. `int myMethod() { }` + 'expressionStatement': helper.BLOCK_ONLY, # Statement that consists of an expression, like `a = b;` + 'additiveExpression': helper.VALUE_ONLY, # e.g. `a + b` + 'multiplicativeExpression': helper.VALUE_ONLY, # e.g. `a * b` + 'declaration': helper.BLOCK_ONLY, # e.g. `int a;` + 'parameterDeclaration': helper.BLOCK_ONLY, # e.g. `int a` when in `int myMethod(int a) { }` + 'unaryExpression': helper.VALUE_ONLY, # e.g. `sizeof(a)` + 'typeName': helper.VALUE_ONLY, # e.g. `int` + 'initializer': helper.VALUE_ONLY, # e.g. `{a, b, c}` when in `int x[ = {a, b, c};` + 'castExpression': helper.VALUE_ONLY # e.g. `(b)a` +} config = { RULES, COLOR_RULES, SHAPE_RULES } ADD_PARENS = (leading, trailing, node, context) -> - leading '(' + leading() - trailing trailing() + ')' + leading = '(' + leading + trailing = trailing + ')' + + return [leading, trailing] + +ADD_SEMICOLON = (leading, trailing, node, context) -> + while leading.match(/^\s*\(/) and trailing.match(/\)\s*$/) + leading = leading.replace /^\s*\(/, '' + trailing = trailing.replace /\)\s*$/, '' + trailing = trailing + ';' + + return [leading, trailing] + +REMOVE_SEMICOLON = (leading, trailing, node, context) -> + trailing = trailing.replace /\s*;\s*$/, '' + + return [leading, trailing] config.PAREN_RULES = { 'primaryExpression': { 'expression': ADD_PARENS - 'additiveExpression': ADD_PARENS - 'multiplicativeExpression': ADD_PARENS - 'assignmentExpression': ADD_PARENS - 'postfixExpression': ADD_PARENS + }, + 'expressionStatement': { + 'expression': ADD_SEMICOLON + } + 'expression': { + 'expressionStatement': REMOVE_SEMICOLON } } @@ -285,15 +302,7 @@ config.stringFixer = (string) -> config.empty = '__0_droplet__' config.emptyIndent = '' - -# TODO Implement removing parentheses at some point -#config.unParenWrap = (leading, trailing, node, context) -> -# while true -# if leading().match(/^\s*\(/)? and trailing().match(/\)\s*/)? -# leading leading().replace(/^\s*\(\s*/, '') -# trailing trailing().replace(/\s*\)\s*$/, '') -# else -# break +config.rootContext = 'translationUnit' # DEBUG config.unParenWrap = null diff --git a/src/model.coffee b/src/model.coffee index a46b9e67..c9f818af 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -1079,6 +1079,8 @@ exports.Socket = class Socket extends Container _serialize_header: -> " "" exports.Document = class Document extends Container - constructor: (@opts = {}, @indentContext = null) -> + constructor: (@indentContext, @opts = {}) -> @start = new DocumentStartToken this @end = new DocumentEndToken this diff --git a/src/parser.coffee b/src/parser.coffee index c96dea33..5b27515a 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -95,6 +95,8 @@ exports.Parser = class Parser # parenWrapped: Boolean # } addBlock: (opts) -> + unless opts.parseContext? + debugger block = new model.Block opts.precedence, opts.color, opts.shape, @@ -326,7 +328,7 @@ exports.Parser = class Parser indentDepth = 0 stack = [] - document = new model.Document(); head = document.start + document = new model.Document(@rootContext); head = document.start currentlyCommented = false @@ -639,6 +641,7 @@ exports.wrapParser = (CustomParser) -> @emptyIndent = CustomParser.emptyIndent @startComment = CustomParser.startComment ? '/*' @endComment = CustomParser.endComment ? '*/' + @rootContext = CustomParser.rootContext @startSingleLineComment = CustomParser.startSingleLineComment @getDefaultSelectionRange = CustomParser.getDefaultSelectionRange ? getDefaultSelectionRange @@ -650,6 +653,7 @@ exports.wrapParser = (CustomParser) -> parser.endComment = @endComment parser.empty = @empty parser.emptyIndent = @emptyIndent + parser.rootContext = @rootContext return parser stringFixer: (string) -> @@ -664,26 +668,7 @@ exports.wrapParser = (CustomParser) -> return @createParser(text)._parse opts parens: (leading, trailing, node, context) -> - # leadingFn is always a getter/setter for leading - leadingFn = (value) -> - if value? - leading = value - return leading - - # trailingFn may either get/set leading or trailing; - # will point to leading if leading is the only token, - # but will point to trailing otherwise. - if trailing? - trailingFn = (value) -> - if value? - trailing = value - return trailing - else - trailingFn = leadingFn - - CustomParser.parens leadingFn, trailingFn, node, context - - return [leading, trailing] + return CustomParser.parens leading, trailing, node, context drop: (block, context, pred, next) -> CustomParser.drop block, context, pred, next diff --git a/src/treewalk.coffee b/src/treewalk.coffee index bef9cdbf..348a2d53 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -49,35 +49,27 @@ exports.createTreewalkParser = (parse, config, root) -> detNode: (node) -> if node.blockified then 'block' else @det(node) - getColor: (node, rules) -> + getColor: (node) -> color = config.COLOR_CALLBACK?(@opts, node) if color? return color - # Apply the static rules set given in config - rulesSet = {} - rules.forEach (el) -> rulesSet[el] = true + else if node.type of config.COLOR_RULES + return config.COLOR_RULES[node.type] - for colorRule in config.COLOR_RULES - if colorRule[0] of rulesSet - return colorRule[1] - - return 'comment' + else + return 'comment' getShape: (node, rules) -> shape = config.SHAPE_CALLBACK?(@opts, node) if shape? return shape - # Apply the static rules set given in config - rulesSet = {} - rules.forEach (el) -> rulesSet[el] = true + else if node.type of config.SHAPE_RULES + return config.SHAPE_RULES[node.type] - for shapeRule in config.SHAPE_RULES - if shapeRule[0] of rulesSet - return shapeRule[1] - - return helper.ANY_DROP + else + return helper.ANY_DROP mark: (node, prefix, depth, pass, rules, context, wrap) -> unless pass @@ -112,8 +104,8 @@ exports.createTreewalkParser = (parse, config, root) -> @addBlock bounds: bounds depth: depth + 1 - color: @getColor node, rules - shape: @getShape node, rules + color: @getColor node + shape: @getShape node parseContext: rules[rules.length - 1] when 'parens' @@ -147,8 +139,8 @@ exports.createTreewalkParser = (parse, config, root) -> @addBlock bounds: bounds depth: depth + 1 - color: @getColor node, rules - shape: @getShape node, rules + color: @getColor node + shape: @getShape node parseContext: rules[rules.length - 1] when 'indent' @@ -157,8 +149,8 @@ exports.createTreewalkParser = (parse, config, root) -> @addBlock bounds: node.bounds depth: depth - color: @getColor node, rules - shape: @getShape node, rules + color: @getColor node + shape: @getShape node parseContext: rules[rules.length - 1] depth += 1 @@ -209,20 +201,43 @@ exports.createTreewalkParser = (parse, config, root) -> if config.droppabilityGraph? droppabilityGraph = new Graph(config.droppabilityGraph) + parenGraph = new Graph(config.parenGraph) + TreewalkParser.drop = (block, context, pred) -> parseContext = context.indentContext ? context.parseContext - if helper.dfs(droppabilityGraph, parseContext, block.parseContext) + if helper.dfs(parenGraph, parseContext, block.parseContext) return helper.ENCOURAGE else return helper.FORBID + TreewalkParser.parens = (leading, trailing, node, context) -> + if context is null + return [leading, trailing, node.parseContext] + + parseContext = context.indentContext ? context.parseContext + if helper.dfs(droppabilityGraph, parseContext, node.parseContext) + return [leading, trailing, node.parseContext] + + else + path = parenGraph.shortestPath(parseContext, node.parseContext, {reverse: true}) + console.log 'Paren wrap required in path', path + for element, i in path when i > 0 + if config.PAREN_RULES[path[i]]?[path[i - 1]]? + + console.log 'Applying paren to form', path[i], 'from', path[i - 1] + + [leading, trailing] = config.PAREN_RULES[path[i]][path[i - 1]](leading, trailing, node, context) + + node.parseContext = path[i] + + return [leading, trailing, node.parseContext] + else if config.drop? TreewalkParser.drop = config.drop - - # Doesn't yet deal with parens - TreewalkParser.parens = (leading, trailing, node, context)-> + TreewalkParser.parens = config.parens ? -> TreewalkParser.stringFixer = config.stringFixer + TreewalkParser.rootContext = config.rootContext TreewalkParser.getDefaultSelectionRange = config.getDefaultSelectionRange TreewalkParser.empty = config.empty From c997d11636eb7df4837665d8436aaf35d13b5e57 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 14 Jul 2016 17:31:07 -0400 Subject: [PATCH 30/60] Rewrite parser priorities for sizeof() to avoid weird paren case and also hit common use case --- antlr/C.g4 | 4 ++-- antlr/CParser.js | 50 ++++++++++++++++++++++----------------------- src/treewalk.coffee | 2 ++ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/antlr/C.g4 b/antlr/C.g4 index a759bedc..a6e42086 100644 --- a/antlr/C.g4 +++ b/antlr/C.g4 @@ -78,8 +78,8 @@ unaryExpression | '++' unaryExpression | '--' unaryExpression | unaryOperator castExpression - | 'sizeof' unaryExpression | 'sizeof' '(' typeName ')' + | 'sizeof' unaryExpression | '_Alignof' '(' typeName ')' | '&&' Identifier // GCC extension address of label ; @@ -601,8 +601,8 @@ unaryExpression_DropletFile | '++' unaryExpression EOF | '--' unaryExpression EOF | unaryOperator castExpression EOF - | 'sizeof' unaryExpression EOF | 'sizeof' '(' typeName ')' EOF + | 'sizeof' unaryExpression EOF | '_Alignof' '(' typeName ')' EOF | '&&' Identifier // GCC extension address of label EOF ; diff --git a/antlr/CParser.js b/antlr/CParser.js index c0a6cca3..4fc940bf 100644 --- a/antlr/CParser.js +++ b/antlr/CParser.js @@ -340,12 +340,12 @@ var serializedATN = ["\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd", "\2\2\2\u01de\u01df\3\2\2\2\u01df\r\3\2\2\2\u01e0\u01de\3\2\2\2\u01e1", "\u01f8\5\n\6\2\u01e2\u01e3\7J\2\2\u01e3\u01f8\5\16\b\2\u01e4\u01e5\7", "L\2\2\u01e5\u01f8\5\16\b\2\u01e6\u01e7\5\20\t\2\u01e7\u01e8\5\22\n\2", - "\u01e8\u01f8\3\2\2\2\u01e9\u01ea\7)\2\2\u01ea\u01f8\5\16\b\2\u01eb\u01ec", - "\7)\2\2\u01ec\u01ed\7=\2\2\u01ed\u01ee\5|?\2\u01ee\u01ef\7>\2\2\u01ef", - "\u01f8\3\2\2\2\u01f0\u01f1\7\64\2\2\u01f1\u01f2\7=\2\2\u01f2\u01f3\5", - "|?\2\u01f3\u01f4\7>\2\2\u01f4\u01f8\3\2\2\2\u01f5\u01f6\7R\2\2\u01f6", + "\u01e8\u01f8\3\2\2\2\u01e9\u01ea\7)\2\2\u01ea\u01eb\7=\2\2\u01eb\u01ec", + "\5|?\2\u01ec\u01ed\7>\2\2\u01ed\u01f8\3\2\2\2\u01ee\u01ef\7)\2\2\u01ef", + "\u01f8\5\16\b\2\u01f0\u01f1\7\64\2\2\u01f1\u01f2\7=\2\2\u01f2\u01f3", + "\5|?\2\u01f3\u01f4\7>\2\2\u01f4\u01f8\3\2\2\2\u01f5\u01f6\7R\2\2\u01f6", "\u01f8\7k\2\2\u01f7\u01e1\3\2\2\2\u01f7\u01e2\3\2\2\2\u01f7\u01e4\3", - "\2\2\2\u01f7\u01e6\3\2\2\2\u01f7\u01e9\3\2\2\2\u01f7\u01eb\3\2\2\2\u01f7", + "\2\2\2\u01f7\u01e6\3\2\2\2\u01f7\u01e9\3\2\2\2\u01f7\u01ee\3\2\2\2\u01f7", "\u01f0\3\2\2\2\u01f7\u01f5\3\2\2\2\u01f8\17\3\2\2\2\u01f9\u01fa\t\2", "\2\2\u01fa\21\3\2\2\2\u01fb\u0208\5\16\b\2\u01fc\u01fd\7=\2\2\u01fd", "\u01fe\5|?\2\u01fe\u01ff\7>\2\2\u01ff\u0200\5\22\n\2\u0200\u0208\3\2", @@ -719,13 +719,13 @@ var serializedATN = ["\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd", "\u0644\5\16\b\2\u0644\u0645\7\2\2\3\u0645\u0661\3\2\2\2\u0646\u0647", "\7L\2\2\u0647\u0648\5\16\b\2\u0648\u0649\7\2\2\3\u0649\u0661\3\2\2\2", "\u064a\u064b\5\20\t\2\u064b\u064c\5\22\n\2\u064c\u064d\7\2\2\3\u064d", - "\u0661\3\2\2\2\u064e\u064f\7)\2\2\u064f\u0650\5\16\b\2\u0650\u0651\7", - "\2\2\3\u0651\u0661\3\2\2\2\u0652\u0653\7)\2\2\u0653\u0654\7=\2\2\u0654", - "\u0655\5|?\2\u0655\u0656\7>\2\2\u0656\u0657\7\2\2\3\u0657\u0661\3\2", - "\2\2\u0658\u0659\7\64\2\2\u0659\u065a\7=\2\2\u065a\u065b\5|?\2\u065b", + "\u0661\3\2\2\2\u064e\u064f\7)\2\2\u064f\u0650\7=\2\2\u0650\u0651\5|", + "?\2\u0651\u0652\7>\2\2\u0652\u0653\7\2\2\3\u0653\u0661\3\2\2\2\u0654", + "\u0655\7)\2\2\u0655\u0656\5\16\b\2\u0656\u0657\7\2\2\3\u0657\u0661\3", + "\2\2\2\u0658\u0659\7\64\2\2\u0659\u065a\7=\2\2\u065a\u065b\5|?\2\u065b", "\u065c\7>\2\2\u065c\u065d\7\2\2\3\u065d\u0661\3\2\2\2\u065e\u065f\7", "R\2\2\u065f\u0661\7k\2\2\u0660\u063f\3\2\2\2\u0660\u0642\3\2\2\2\u0660", - "\u0646\3\2\2\2\u0660\u064a\3\2\2\2\u0660\u064e\3\2\2\2\u0660\u0652\3", + "\u0646\3\2\2\2\u0660\u064a\3\2\2\2\u0660\u064e\3\2\2\2\u0660\u0654\3", "\2\2\2\u0660\u0658\3\2\2\2\u0660\u065e\3\2\2\2\u0661\u00bb\3\2\2\2\u0662", "\u066a\7P\2\2\u0663\u066a\7M\2\2\u0664\u066a\7I\2\2\u0665\u066a\7K\2", "\2\u0666\u066a\7V\2\2\u0667\u0668\7U\2\2\u0668\u066a\7\2\2\3\u0669\u0662", @@ -2501,19 +2501,19 @@ CParser.prototype.unaryExpression = function() { this.state = 487; this.match(CParser.Sizeof); this.state = 488; - this.unaryExpression(); + this.match(CParser.LeftParen); + this.state = 489; + this.typeName(); + this.state = 490; + this.match(CParser.RightParen); break; case 6: this.enterOuterAlt(localctx, 6); - this.state = 489; - this.match(CParser.Sizeof); - this.state = 490; - this.match(CParser.LeftParen); - this.state = 491; - this.typeName(); this.state = 492; - this.match(CParser.RightParen); + this.match(CParser.Sizeof); + this.state = 493; + this.unaryExpression(); break; case 7: @@ -11419,21 +11419,21 @@ CParser.prototype.unaryExpression_DropletFile = function() { this.state = 1612; this.match(CParser.Sizeof); this.state = 1613; - this.unaryExpression(); + this.match(CParser.LeftParen); this.state = 1614; + this.typeName(); + this.state = 1615; + this.match(CParser.RightParen); + this.state = 1616; this.match(CParser.EOF); break; case 6: this.enterOuterAlt(localctx, 6); - this.state = 1616; - this.match(CParser.Sizeof); - this.state = 1617; - this.match(CParser.LeftParen); this.state = 1618; - this.typeName(); + this.match(CParser.Sizeof); this.state = 1619; - this.match(CParser.RightParen); + this.unaryExpression(); this.state = 1620; this.match(CParser.EOF); break; diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 348a2d53..b8c6c08b 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -191,6 +191,8 @@ exports.createTreewalkParser = (parse, config, root) -> @mark child, prefix, depth + 2, false else if context? and @detNode(context) is 'block' if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) + if rules[0] is 'unaryExpression' + debugger @addSocket bounds: node.bounds depth: depth From 6faf5562ecff2c694d5308d686faac93ada1575a Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 14 Jul 2016 17:42:18 -0400 Subject: [PATCH 31/60] Flesh out enough more colors that the palette works --- src/languages/c.coffee | 5 ++++- src/parser.coffee | 2 +- src/treewalk.coffee | 10 ++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index d5625607..709658be 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -52,12 +52,15 @@ RULES = { } COLOR_RULES = { - 'jumpStatement': 'return' # e.g. `return 0;` + 'jumpStatement': 'return', # e.g. `return 0;` + 'specifierQualifierList': 'command',# e.g `int a;` when inside `struct {}` 'declaration': 'control', # e.g. `int a;` 'specialMethodCall': 'command', # e.g. `a(b);` 'equalityExpression': 'value' # e.g. `a == b` 'additiveExpression': 'value', # e.g. `a + b` 'multiplicativeExpression': 'value', # e.g. `a * b` + 'logicalAndExpression': 'value', # e.g. `a && b` + 'logicalOrExpression': 'value', # e.g. `a || b` 'postfixExpression': 'command', # e.g. `a(b, c);` OR `a++` 'iterationStatement': 'control', # e.g. `for (int i = 0; i < 10; i++) { }` 'selectionStatement': 'control', # e.g. if `(a) { } else { }` OR `switch (a) { }` diff --git a/src/parser.coffee b/src/parser.coffee index 5b27515a..2f7767a6 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -237,7 +237,7 @@ exports.Parser = class Parser if sockets? for socketPosition in sockets - socket = new model.Socket '', 0, true + socket = new model.Socket '', 0, true, null, '__comment__' socket.setParent block padText = text[lastPosition...socketPosition[0]] diff --git a/src/treewalk.coffee b/src/treewalk.coffee index b8c6c08b..b32965ec 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -206,6 +206,11 @@ exports.createTreewalkParser = (parse, config, root) -> parenGraph = new Graph(config.parenGraph) TreewalkParser.drop = (block, context, pred) -> + if block.parseContext is '__comment__' and context.type in ['indent', 'document'] + return helper.ENCOURAGE + else if context.parseContext is '__comment__' + return helper.DISCOURAGE + parseContext = context.indentContext ? context.parseContext if helper.dfs(parenGraph, parseContext, block.parseContext) return helper.ENCOURAGE @@ -213,7 +218,7 @@ exports.createTreewalkParser = (parse, config, root) -> return helper.FORBID TreewalkParser.parens = (leading, trailing, node, context) -> - if context is null + if context is null or node.parseContext is '__comment__' or context.parseContext is '__comment__' return [leading, trailing, node.parseContext] parseContext = context.indentContext ? context.parseContext @@ -222,12 +227,9 @@ exports.createTreewalkParser = (parse, config, root) -> else path = parenGraph.shortestPath(parseContext, node.parseContext, {reverse: true}) - console.log 'Paren wrap required in path', path for element, i in path when i > 0 if config.PAREN_RULES[path[i]]?[path[i - 1]]? - console.log 'Applying paren to form', path[i], 'from', path[i - 1] - [leading, trailing] = config.PAREN_RULES[path[i]][path[i - 1]](leading, trailing, node, context) node.parseContext = path[i] From 0f4bd2d68d41c338d10adcf1a82c820df0e2b7df Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Fri, 15 Jul 2016 11:31:29 -0400 Subject: [PATCH 32/60] Add node contexts for paren-unwrapping purposes --- package.json | 1 + src/languages/c.coffee | 21 ++++--------- src/model.coffee | 15 +++++++-- src/parser.coffee | 29 +++++++++++++++-- src/treewalk.coffee | 70 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 108 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 4f6d59af..937c44c2 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "dependencies": { "acorn": "^1.2.2", "antlr4": "latest", + "json-stable-stringify": "^1.0.1", "node-dijkstra": "^1.1.3", "parse5": "latest", "sax": "^1.1.1" diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 709658be..ce322ed3 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -116,23 +116,14 @@ config = { } ADD_PARENS = (leading, trailing, node, context) -> - leading = '(' + leading - trailing = trailing + ')' - - return [leading, trailing] + leading '(' + leading() + trailing trailing() + ')' ADD_SEMICOLON = (leading, trailing, node, context) -> - while leading.match(/^\s*\(/) and trailing.match(/\)\s*$/) - leading = leading.replace /^\s*\(/, '' - trailing = trailing.replace /\)\s*$/, '' - trailing = trailing + ';' - - return [leading, trailing] + trailing trailing() + ';' REMOVE_SEMICOLON = (leading, trailing, node, context) -> - trailing = trailing.replace /\s*;\s*$/, '' - - return [leading, trailing] + trailing trailing().replace /\s*;\s*$/, '' config.PAREN_RULES = { 'primaryExpression': { @@ -141,8 +132,8 @@ config.PAREN_RULES = { 'expressionStatement': { 'expression': ADD_SEMICOLON } - 'expression': { - 'expressionStatement': REMOVE_SEMICOLON + 'postfixExpression': { + 'specialMethodCall': REMOVE_SEMICOLON } } diff --git a/src/model.coffee b/src/model.coffee index c9f818af..aff82092 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -3,6 +3,7 @@ # Copyright (c) 2014 Anthony Bau (dab1998@gmail.com) # MIT License helper = require './helper.coffee' +stableStringify = require 'json-stable-stringify' YES = -> yes NO = -> no @@ -12,6 +13,14 @@ FORBID = default: helper.FORBID DEFAULT_STRINGIFY_OPTS = {preserveEmpty: true} +# A NodeContext represents the default (bottom-most) paren-wrap state that a block +# can revert to when paren-wrapping. e.g. in C, the 'blockItem' node (myfun()); would have nodeContext 'postfixExpression', 'myfun()', 'myfun()', whie +# a++ would have nodeContext 'postfixExpression', '', '++' +exports.NodeContext = class NodeContext + constructor: (@type, @prefix, @suffix) -> + +COMMENT_CONTEXT = new NodeContext '__comment__', '', '' + _id = 0 # Getter/setter utility function @@ -507,6 +516,7 @@ exports.Container = class Container extends List shape: @shape indentContext: @indentContext parseContext: @parseContext + nodeContext: @nodeContext } setParent: (parent) -> @@ -984,7 +994,7 @@ exports.BlockEndToken = class BlockEndToken extends EndToken serialize: -> "" exports.Block = class Block extends Container - constructor: (@precedence = 0, @color = 'blank', @shape = helper.ANY_DROP, @parseContext, @buttons = {}) -> + constructor: (@precedence = 0, @color = 'blank', @shape = helper.ANY_DROP, @parseContext = '__comment__', @nodeContext = COMMENT_CONTEXT, @buttons = {}) -> @start = new BlockStartToken this @end = new BlockEndToken this @@ -1011,7 +1021,8 @@ exports.Block = class Block extends Container @precedence}\" color=\"#{ @color}\" shape=\"#{ @shape}\" parseContext=\"#{ - @parseContext}\" + @parseContext}\" nodeContext=\"#{ + stableStringify(@nodeContext)}\" >" _serialize_footer: -> "" diff --git a/src/parser.coffee b/src/parser.coffee index 2f7767a6..f09fe29b 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -95,12 +95,11 @@ exports.Parser = class Parser # parenWrapped: Boolean # } addBlock: (opts) -> - unless opts.parseContext? - debugger block = new model.Block opts.precedence, opts.color, opts.shape, opts.parseContext, + opts.nodeContext, opts.buttons @addMarkup block, opts.bounds, opts.depth @@ -668,7 +667,31 @@ exports.wrapParser = (CustomParser) -> return @createParser(text)._parse opts parens: (leading, trailing, node, context) -> - return CustomParser.parens leading, trailing, node, context + # We do this function thing so that if leading and trailing are the same + # (i.e. there is only one text token), parser adapter functions can still treat + # it as if they are two different things. + + # leadingFn is always a getter/setter for leading + leadingFn = (value) -> + if value? + leading = value + return leading + + # trailingFn may either get/set leading or trailing; + # will point to leading if leading is the only token, + # but will point to trailing otherwise. + if trailing? + trailingFn = (value) -> + if value? + trailing = value + return trailing + else + trailingFn = leadingFn + + context = CustomParser.parens leadingFn, trailingFn, node, context + + return [leading, trailing, context] + drop: (block, context, pred, next) -> CustomParser.drop block, context, pred, next diff --git a/src/treewalk.coffee b/src/treewalk.coffee index b32965ec..689032e8 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -71,6 +71,55 @@ exports.createTreewalkParser = (parse, config, root) -> else return helper.ANY_DROP + firstElement: (node) -> + if node.children.length is 0 + if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) + return node + else + return null + else + for child in node.children + if child.children.length > 1 and @detNode(child) isnt 'skip' + return child + + element = @firstElement child + if element? + return element + return null + + lastElement: (node) -> + if node.children.length is 0 + if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) + return node + else + return null + else + for child in node.children by -1 + if child.children.length > 1 and @detNode(child) isnt 'skip' + return child + + element = @lastElement child + if element? + return element + return null + + prefix: (node) -> + firstElement = @firstElement node + if firstElement? + helper.clipLines @lines, node.bounds.start, firstElement.bounds.start + else + helper.clipLines @lines, node.bounds.start, node.bounds.end + + suffix: (node) -> + lastElement = @lastElement node + if lastElement? + helper.clipLines @lines, lastElement.bounds.end, node.bounds.end + else + helper.clipLines @lines, node.bounds.start, node.bounds.end + + getNodeContext: (node) -> + new model.NodeContext node.type, @prefix(node), @suffix(node) + mark: (node, prefix, depth, pass, rules, context, wrap) -> unless pass context = node.parent @@ -106,6 +155,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node shape: @getShape node + nodeContext: @getNodeContext node parseContext: rules[rules.length - 1] when 'parens' @@ -141,6 +191,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node shape: @getShape node + nodeContext: @getNodeContext node parseContext: rules[rules.length - 1] when 'indent' @@ -151,6 +202,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth color: @getColor node shape: @getShape node + nodeContext: @getNodeContext node parseContext: rules[rules.length - 1] depth += 1 @@ -191,8 +243,6 @@ exports.createTreewalkParser = (parse, config, root) -> @mark child, prefix, depth + 2, false else if context? and @detNode(context) is 'block' if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) - if rules[0] is 'unaryExpression' - debugger @addSocket bounds: node.bounds depth: depth @@ -212,29 +262,33 @@ exports.createTreewalkParser = (parse, config, root) -> return helper.DISCOURAGE parseContext = context.indentContext ? context.parseContext - if helper.dfs(parenGraph, parseContext, block.parseContext) + if helper.dfs(parenGraph, parseContext, block.nodeContext.type) return helper.ENCOURAGE else return helper.FORBID TreewalkParser.parens = (leading, trailing, node, context) -> if context is null or node.parseContext is '__comment__' or context.parseContext is '__comment__' - return [leading, trailing, node.parseContext] + return node.parseContext parseContext = context.indentContext ? context.parseContext if helper.dfs(droppabilityGraph, parseContext, node.parseContext) - return [leading, trailing, node.parseContext] + return node.parseContext else - path = parenGraph.shortestPath(parseContext, node.parseContext, {reverse: true}) + path = parenGraph.shortestPath(parseContext, node.nodeContext.type, {reverse: true}) + + leading node.nodeContext.prefix + trailing node.nodeContext.suffix + for element, i in path when i > 0 if config.PAREN_RULES[path[i]]?[path[i - 1]]? - [leading, trailing] = config.PAREN_RULES[path[i]][path[i - 1]](leading, trailing, node, context) + config.PAREN_RULES[path[i]][path[i - 1]](leading, trailing, node, context) node.parseContext = path[i] - return [leading, trailing, node.parseContext] + return node.parseContext else if config.drop? TreewalkParser.drop = config.drop From e6e6d9fffe88fdf77650481aad4832e05750fb16 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Fri, 15 Jul 2016 12:18:06 -0400 Subject: [PATCH 33/60] Fix nodeContext annotations for trailingText --- src/model.coffee | 22 +++++-------- src/parser.coffee | 54 +++++++++++++++++--------------- src/treewalk.coffee | 76 +++++++++++++++------------------------------ 3 files changed, 61 insertions(+), 91 deletions(-) diff --git a/src/model.coffee b/src/model.coffee index aff82092..9c30f5bd 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -512,7 +512,6 @@ exports.Container = class Container extends List { id: @id type: @type - precedence: @precedence shape: @shape indentContext: @indentContext parseContext: @parseContext @@ -994,7 +993,7 @@ exports.BlockEndToken = class BlockEndToken extends EndToken serialize: -> "" exports.Block = class Block extends Container - constructor: (@precedence = 0, @color = 'blank', @shape = helper.ANY_DROP, @parseContext = '__comment__', @nodeContext = COMMENT_CONTEXT, @buttons = {}) -> + constructor: (@color = 'blank', @shape = helper.ANY_DROP, @parseContext = '__comment__', @nodeContext = COMMENT_CONTEXT, @buttons = {}) -> @start = new BlockStartToken this @end = new BlockEndToken this @@ -1012,13 +1011,12 @@ exports.Block = class Block extends Container return null _cloneEmpty: -> - clone = new Block @precedence, @color, @shape, @parseContext, @buttons + clone = new Block @color, @shape, @parseContext, @nodeContext, @buttons clone.currentlyParenWrapped = @currentlyParenWrapped return clone - _serialize_header: -> " " @start.next is @end or @start.next.type is 'text' - _cloneEmpty: -> new Socket @emptyString, @precedence, @handwritten, @dropdown, @parseContext + _cloneEmpty: -> new Socket @emptyString, @handwritten, @dropdown, @parseContext - _serialize_header: -> " " new Document(@opts) + _cloneEmpty: -> new Document(@indentContext, @opts) firstChild: -> return @_firstChild() - _serialize_header: -> "" + _serialize_header: -> "" _serialize_footer: -> "" diff --git a/src/parser.coffee b/src/parser.coffee index f09fe29b..af006622 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -7,6 +7,18 @@ helper = require './helper.coffee' model = require './model.coffee' +exports.PreNodeContext = class PreNodeContext + constructor: (@type, @preParenLength, @postParenLength) -> + + apply: (node) -> + trailingText = node.getTrailingText() + trailingText = trailingText[0...trailingText.length - @postParenLength] + + leadingText = node.getLeadingText() + leadingText = leadingText[@preParenLength...leadingText.length] + + return new model.NodeContext @type, leadingText, trailingText + sax = require 'sax' _extend = (opts, defaults) -> @@ -52,11 +64,17 @@ exports.Parser = class Parser # Generate a document from the markup document = @applyMarkup opts - @detectParenWrap document - # Correct parent tree document.correctParentTree() + # Add node context annotations from PreNodeContext + # annotations + head = document.start + until head is document.end + if head.type is 'blockStart' and head.container._preNodeContext? + head.container.nodeContext = head.container._preNodeContext.apply head.container + head = head.next + # Strip away blocks flagged to be removed # (for `` hack and error recovery) if opts.preserveEmpty @@ -66,21 +84,6 @@ exports.Parser = class Parser markRoot: -> - isParenWrapped: (block) -> - (block.start.next.type is 'text' and - block.start.next.value[0] is '(' and - block.end.prev.type is 'text' and - block.end.prev.value[block.end.prev.value.length - 1] is ')') - - detectParenWrap: (document) -> - head = document.start - until head is document.end - head = head.next - if head.type is 'blockStart' and - @isParenWrapped head.container - head.container.currentlyParenWrapped = true - return document - # ## addBlock ## # addBlock takes { # bounds: { @@ -95,13 +98,14 @@ exports.Parser = class Parser # parenWrapped: Boolean # } addBlock: (opts) -> - block = new model.Block opts.precedence, - opts.color, + block = new model.Block opts.color, opts.shape, opts.parseContext, - opts.nodeContext, + null opts.buttons + block._preNodeContext = opts.nodeContext + @addMarkup block, opts.bounds, opts.depth # flagToRemove, used for removing the placeholders that @@ -127,7 +131,7 @@ exports.Parser = class Parser # accepts: shallow_dict # } addSocket: (opts) -> - socket = new model.Socket opts.empty ? @empty, opts.precedence, + socket = new model.Socket opts.empty ? @empty, false, opts.dropdown, opts.parseContext @@ -236,7 +240,7 @@ exports.Parser = class Parser if sockets? for socketPosition in sockets - socket = new model.Socket '', 0, true, null, '__comment__' + socket = new model.Socket '', true, null, '__comment__' socket.setParent block padText = text[lastPosition...socketPosition[0]] @@ -273,7 +277,7 @@ exports.Parser = class Parser helper.connect head, block.end else - socket = new model.Socket '', 0, true + socket = new model.Socket '', true textToken = new model.TextToken text textToken.setParent socket @@ -538,10 +542,10 @@ exports.parseXML = (xml) -> attributes = node.attributes switch node.name when 'block' - container = new model.Block attributes.precedence, attributes.color, + container = new model.Block attributes.color, attributes.shape, attributes.parseContext when 'socket' - container = new model.Socket '', attributes.precedence, attributes.handritten, attributes.parseContext + container = new model.Socket '', attributes.handritten, attributes.parseContext when 'indent' container = new model.Indent '', attributes.prefix, attributes.indentContext when 'document' diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 689032e8..65234555 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -71,54 +71,14 @@ exports.createTreewalkParser = (parse, config, root) -> else return helper.ANY_DROP - firstElement: (node) -> - if node.children.length is 0 - if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) - return node - else - return null - else - for child in node.children - if child.children.length > 1 and @detNode(child) isnt 'skip' - return child - - element = @firstElement child - if element? - return element - return null - - lastElement: (node) -> - if node.children.length is 0 - if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) - return node - else - return null + getNodeContext: (node, wrap) -> + if wrap? + new parser.PreNodeContext(node.type, + helper.clipLines(@lines, wrap.bounds.start, node.bounds.start).length, + helper.clipLines(@lines, node.bounds.end, wrap.bounds.end).length + ) else - for child in node.children by -1 - if child.children.length > 1 and @detNode(child) isnt 'skip' - return child - - element = @lastElement child - if element? - return element - return null - - prefix: (node) -> - firstElement = @firstElement node - if firstElement? - helper.clipLines @lines, node.bounds.start, firstElement.bounds.start - else - helper.clipLines @lines, node.bounds.start, node.bounds.end - - suffix: (node) -> - lastElement = @lastElement node - if lastElement? - helper.clipLines @lines, lastElement.bounds.end, node.bounds.end - else - helper.clipLines @lines, node.bounds.start, node.bounds.end - - getNodeContext: (node) -> - new model.NodeContext node.type, @prefix(node), @suffix(node) + return new parser.PreNodeContext node.type, 0, 0 mark: (node, prefix, depth, pass, rules, context, wrap) -> unless pass @@ -155,7 +115,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node shape: @getShape node - nodeContext: @getNodeContext node + nodeContext: @getNodeContext node, wrap parseContext: rules[rules.length - 1] when 'parens' @@ -191,7 +151,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node shape: @getShape node - nodeContext: @getNodeContext node + nodeContext: @getNodeContext node, wrap parseContext: rules[rules.length - 1] when 'indent' @@ -202,7 +162,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth color: @getColor node shape: @getShape node - nodeContext: @getNodeContext node + nodeContext: @getNodeContext node, warp parseContext: rules[rules.length - 1] depth += 1 @@ -268,13 +228,27 @@ exports.createTreewalkParser = (parse, config, root) -> return helper.FORBID TreewalkParser.parens = (leading, trailing, node, context) -> + # Comments never get paren-wrapped if context is null or node.parseContext is '__comment__' or context.parseContext is '__comment__' return node.parseContext parseContext = context.indentContext ? context.parseContext - if helper.dfs(droppabilityGraph, parseContext, node.parseContext) + + # Check to see if we can unwrap all our parentheses + if helper.dfs(droppabilityGraph, parseContext, node.nodeContext.type) + leading node.nodeContext.prefix + trailing node.nodeContext.suffix + + return node.nodeContext.type + + # Otherwise, for performance reasons, + # check to see if we can drop without modifying our parentheses + if node.parseContext isnt node.nodeContext and helper.dfs(droppabilityGraph, parseContext, node.parseContext) return node.parseContext + # Otherwise, do a full paren-wrap traversal. We find the shortest rule-inheritance path + # from the bottom-most type of the block to the top-most type of the socket, applying + # any paren rules we encounter along the way. else path = parenGraph.shortestPath(parseContext, node.nodeContext.type, {reverse: true}) From c8f26ee5ef50e901509b00047124877a9e40ee21 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Fri, 15 Jul 2016 14:40:49 -0400 Subject: [PATCH 34/60] I actually don't know what changed --- src/parser.coffee | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/parser.coffee b/src/parser.coffee index af006622..46947f6e 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -614,17 +614,6 @@ stripFlaggedBlocks = (document) -> head = head.next Parser.parens = (leading, trailing, node, context) -> - if context is null or context.type isnt 'socket' or - context?.precedence < node.precedence - while true - if leading().match(/^\s*\(/)? and trailing().match(/\)\s*/)? - leading leading().replace(/^\s*\(\s*/, '') - trailing trailing().replace(/^\s*\)\s*/, '') - else - break - else - leading '(' + leading() - trailing trailing() + ')' Parser.drop = (block, context, pred, next) -> if block.type is 'document' and context.type is 'socket' From c28dc8590ec0d04b08822024bac79595519a1d39 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Fri, 15 Jul 2016 14:56:27 -0400 Subject: [PATCH 35/60] Update build to report errors --- Gruntfile.coffee | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Gruntfile.coffee b/Gruntfile.coffee index d51a29e8..03353794 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -210,17 +210,17 @@ module.exports = (grunt) -> w.on 'update', -> console.log 'File changed...' stream = fs.createWriteStream 'dist/droplet-full.js' - try - w.bundle().pipe stream - stream.once 'close', -> - console.log 'Rebuilt.' - lrserver.changed { - body: { - files: ['dist/droplet-full.js'] - } + + w.bundle().on('error', (e) -> + console.log 'ERROR' + console.log '-----' + console.log e + ).pipe(stream).once 'close', -> + console.log 'Rebuilt.' + lrserver.changed { + body: { + files: ['dist/droplet-full.js'] } - catch e - console.log 'BUILD FAILED.' - console.log e.stack + } grunt.registerTask 'testserver', ['connect:testserver', 'watchify'] From 5972ee5212d173ee93e702658109e7919210ab59 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 18 Jul 2016 11:00:30 -0400 Subject: [PATCH 36/60] Move JavaScript to the new infrastructure, for the most part --- Gruntfile.coffee | 4 +- src/languages/javascript.coffee | 231 ++++++++++++++++---------------- 2 files changed, 122 insertions(+), 113 deletions(-) diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 03353794..34031b94 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -193,7 +193,9 @@ module.exports = (grunt) -> b.require './src/main.coffee' b.transform coffeeify - w = watchify(b) + w = watchify(b, { + poll: true + }) # Compile once through first stream = fs.createWriteStream 'dist/droplet-full.js' diff --git a/src/languages/javascript.coffee b/src/languages/javascript.coffee index 9ca83128..527185c6 100644 --- a/src/languages/javascript.coffee +++ b/src/languages/javascript.coffee @@ -134,14 +134,35 @@ OPERATOR_PRECEDENCES = { '||': 14 } -CLASS_EXCEPTIONS = { - 'ForStatement': ['ends-with-brace', 'block-only'] - 'FunctionDeclaration': ['ends-with-brace', 'block-only'] - 'IfStatement': ['ends-with-brace', 'block-only'] - 'WhileStatement': ['ends-with-brace', 'block-only'] - 'DoWhileStatement': ['ends-with-brace', 'block-only'] - 'SwitchStatement': ['ends-with-brace', 'block-only'] - 'AssignmentExpression': ['mostly-block'] +PRECEDENCE = { + 'AssignStatement': 16 + 'CallExpression': 2 + 'NewExpression': 2 + 'MemberExpression': 1 + 'Expression': NEVER_PAREN + 'Lvalue': NEVER_PAREN + 'IfTest': NEVER_PAREN + 'ForEachLHS': NEVER_PAREN + 'ForEachRHS': 10 + 'ForInit': NEVER_PAREN + 'ForUpdate': 10 + 'Callee': NEVER_PAREN # Actually so? + 'CalleeObject': NEVER_PAREN # Actually so? +} + +for operator, precedence of OPERATOR_PRECEDENCES + PRECEDENCE['Operator' + operator] = precedence + +getPrecedence = (type) -> + PRECEDENCE[type] ? 0 + +SEMICOLON_EXCEPTIONS = { + 'ForStatement': true + 'FunctionDeclaration': true + 'IfStatement': true + 'WhileStatement': true + 'DoWhileStatement': true + 'SwitchStatement': true } DEFAULT_INDENT_DEPTH = ' ' @@ -199,48 +220,27 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser return null getAcceptsRule: (node) -> default: helper.NORMAL - getClasses: (node) -> - if node.type of CLASS_EXCEPTIONS - return CLASS_EXCEPTIONS[node.type].concat([node.type]) - else - if node.type is 'CallExpression' or node.type is 'NewExpression' or node.type is 'Identifier' - known = @lookupKnownName node - if not known or (known.fn.value and known.fn.command) - return [node.type, 'any-drop'] - if known.fn.value - return [node.type, 'mostly-value'] - else - return [node.type, 'mostly-block'] - if node.type.match(/Expression$/)? - return [node.type, 'mostly-value'] - else if node.type.match(/Declaration$/)? - return [node.type, 'block-only'] - else if node.type.match(/Statement$/)? - return [node.type, 'mostly-block'] - else - return [node.type, 'any-drop'] - - getPrecedence: (node) -> - switch node.type - when 'BinaryExpression', 'LogicalExpression' - return OPERATOR_PRECEDENCES[node.operator] - when 'AssignStatement' - return 16 - when 'UnaryExpression' - if node.prefix - return OPERATOR_PRECEDENCES[node.operator] ? 4 - else - return OPERATOR_PRECEDENCES[node.operator] ? 3 - when 'CallExpression' - return 2 - when 'NewExpression' - return 2 - when 'MemberExpression' - return 1 - when 'ExpressionStatement' - return @getPrecedence node.expression + getShape: (node) -> + if node.type is 'CallExpression' or node.type is 'NewExpression' or node.type is 'Identifier' + known = @lookupKnownName node + if not known or (known.fn.value and known.fn.command) + return helper.ANY_DROP + if known.fn.value + return helper.MOSTLY_VALUE else - return 0 + return helper.MOSTLY_BLOCK + else if node.type in ['ForStatement', 'FunctionDeclaration', 'IfStatement', 'WhileStatement', 'DoWhileStatement', 'SwitchStatement'] + return helper.BLOCK_ONLY + else if node.type is 'AssignExpression' + return helper.MOSTLY_BLOCK + else if node.type.match(/Expression$/)? + return helper.MOSTLY_VALUE + else if node.type.match(/Declaration$/)? + return helper.BLOCK_ONLY + else if node.type.match(/Statement$/)? + return helper.MOSTLY_BLOCK + else + return helper.ANY_DROP lookupCategory: (node) -> switch node.type @@ -267,8 +267,6 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser category = @lookupCategory node return category?.color or 'command' - getSocketLevel: (node) -> helper.ANY_DROP - getBounds: (node) -> # If we are a statement, scan # to find the semicolon @@ -431,7 +429,7 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser when 'FunctionDeclaration' @jsBlock node, depth, bounds @mark indentDepth, node.body, depth + 1, null - @jsSocketAndMark indentDepth, node.id, depth + 1, null, null, ['no-drop'] + @jsSocketAndMark indentDepth, node.id, depth + 1, 'Identifier', null if node.params.length > 0 @addSocket { bounds: { @@ -439,9 +437,8 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser end: @getBounds(node.params[node.params.length - 1]).end } depth: depth + 1 - precedence: 0 + parseContext: '__comment__' dropdown: null - classes: ['no-drop'] empty: '' } else unless @opts.lockZeroParamFunctions @@ -460,16 +457,15 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser } }, depth, - precedence: 0, + parseContext: '__comment__' dropdown: null, - classes: ['forbid-all', '__function_param__'] empty: '' } when 'FunctionExpression' @jsBlock node, depth, bounds @mark indentDepth, node.body, depth + 1, null if node.id? - @jsSocketAndMark indentDepth, node.id, depth + 1, null, null, ['no-drop'] + @jsSocketAndMark indentDepth, node.id, depth + 1, 'Identifier', null if node.params.length > 0 @addSocket { bounds: { @@ -477,9 +473,7 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser end: @getBounds(node.params[node.params.length - 1]).end } depth: depth + 1 - precedence: 0 - dropdown: null - classes: ['no-drop'] + parseContext: '__comment__' empty: '' } else unless @opts.lockZeroParamFunctions @@ -505,20 +499,20 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser depth, precedence: 0, dropdown: null, - classes: ['forbid-all', '__function_param__'] + parseContext: '__comment__' empty: '' } when 'AssignmentExpression' @jsBlock node, depth, bounds - @jsSocketAndMark indentDepth, node.left, depth + 1, NEVER_PAREN - @jsSocketAndMark indentDepth, node.right, depth + 1, NEVER_PAREN + @jsSocketAndMark indentDepth, node.left, depth + 1, 'Lvalue' + @jsSocketAndMark indentDepth, node.right, depth + 1, 'Expression' when 'ReturnStatement' @jsBlock node, depth, bounds if node.argument? @jsSocketAndMark indentDepth, node.argument, depth + 1, null when 'IfStatement', 'ConditionalExpression' @jsBlock node, depth, bounds, {addButton: '+'} - @jsSocketAndMark indentDepth, node.test, depth + 1, NEVER_PAREN + @jsSocketAndMark indentDepth, node.test, depth + 1, 'Expression' @jsSocketAndMark indentDepth, node.consequent, depth + 1, null # As long as the else fits the "else-if" pattern, @@ -536,9 +530,9 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser when 'ForInStatement' @jsBlock node, depth, bounds if node.left? - @jsSocketAndMark indentDepth, node.left, depth + 1, NEVER_PAREN, null, ['foreach-lhs'] + @jsSocketAndMark indentDepth, node.left, depth + 1, 'ForEachLHS', null, ['foreach-lhs'] if node.right? - @jsSocketAndMark indentDepth, node.right, depth + 1, 10 + @jsSocketAndMark indentDepth, node.right, depth + 1, 'ForEachRHS' @mark indentDepth, node.body, depth + 1 when 'BreakStatement', 'ContinueStatement' @jsBlock node, depth, bounds @@ -558,11 +552,11 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser else if node.init? - @jsSocketAndMark indentDepth, node.init, depth + 1, NEVER_PAREN, null, ['for-statement-init'] + @jsSocketAndMark indentDepth, node.init, depth + 1, 'ForInit', null, ['for-statement-init'] if node.test? - @jsSocketAndMark indentDepth, node.test, depth + 1, 10 + @jsSocketAndMark indentDepth, node.test, depth + 1, 'Expression' if node.update? - @jsSocketAndMark indentDepth, node.update, depth + 1, 10, null, ['for-statement-update'] + @jsSocketAndMark indentDepth, node.update, depth + 1, 'ForUpdate', null, ['for-statement-update'] @mark indentDepth, node.body, depth + 1 when 'BlockStatement' @@ -577,13 +571,13 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser @mark indentDepth, statement, depth + 1, null when 'BinaryExpression' @jsBlock node, depth, bounds - @jsSocketAndMark indentDepth, node.left, depth + 1, OPERATOR_PRECEDENCES[node.operator] - @jsSocketAndMark indentDepth, node.right, depth + 1, OPERATOR_PRECEDENCES[node.operator] + @jsSocketAndMark indentDepth, node.left, depth + 1, 'Operator' + node.operator + @jsSocketAndMark indentDepth, node.right, depth + 1, 'Operator' + node.operator when 'UnaryExpression' unless node.operator in ['-', '+'] and node.argument.type in ['Identifier', 'Literal'] @jsBlock node, depth, bounds - @jsSocketAndMark indentDepth, node.argument, depth + 1, @getPrecedence node + @jsSocketAndMark indentDepth, node.argument, depth + 1, null when 'ExpressionStatement' @mark indentDepth, node.expression, depth + 1, @getBounds node when 'Identifier' @@ -614,11 +608,11 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser @jsBlock node, depth, bounds, blockOpts if not known - @jsSocketAndMark indentDepth, node.callee, depth + 1, NEVER_PAREN + @jsSocketAndMark indentDepth, node.callee, depth + 1, 'Callee' else if known.anyobj and node.callee.type is 'MemberExpression' - @jsSocketAndMark indentDepth, node.callee.object, depth + 1, NEVER_PAREN, null, null, known?.fn?.objectDropdown + @jsSocketAndMark indentDepth, node.callee.object, depth + 1, 'CalleeObject', null, null, known?.fn?.objectDropdown for argument, i in node.arguments - @jsSocketAndMark indentDepth, argument, depth + 1, NEVER_PAREN, null, null, known?.fn?.dropdown?[i] + @jsSocketAndMark indentDepth, argument, depth + 1, 'Expression', null, null, known?.fn?.dropdown?[i] if not known and argCount is 0 and not @opts.lockZeroParamFunctions # Create a special socket that can be used for inserting the first parameter # (NOTE: this socket may not be visible if the bounds start/end are the same) @@ -663,11 +657,11 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser when 'VariableDeclarator' @jsSocketAndMark indentDepth, node.id, depth if node.init? - @jsSocketAndMark indentDepth, node.init, depth, NEVER_PAREN + @jsSocketAndMark indentDepth, node.init, depth, 'Lvalue' when 'LogicalExpression' @jsBlock node, depth, bounds - @jsSocketAndMark indentDepth, node.left, depth + 1, @getPrecedence node - @jsSocketAndMark indentDepth, node.right, depth + 1, @getPrecedence node + @jsSocketAndMark indentDepth, node.left, depth + 1, 'Operator' + node.operator + @jsSocketAndMark indentDepth, node.right, depth + 1, 'Operator' + node.operator when 'WhileStatement', 'DoWhileStatement' @jsBlock node, depth, bounds @jsSocketAndMark indentDepth, node.body, depth + 1 @@ -720,22 +714,44 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser console.log 'Unrecognized', node jsBlock: (node, depth, bounds, buttons) -> + bounds ?= @getBounds node + @addBlock - bounds: bounds ? @getBounds node + bounds: bounds depth: depth - precedence: @getPrecedence node color: @getColor node - classes: @getClasses node - socketLevel: @getSocketLevel node + shape: @getShape node buttons: buttons - jsSocketAndMark: (indentDepth, node, depth, precedence, bounds, classes, dropdown, empty) -> + parseContext: 'program' + nodeContext: @getNodeContext node, bounds + + getType: (node) -> + if node.type in ['BinaryExpression', 'LogicalExpression', 'UnaryExpression', 'UpdateExpression'] + return 'Operator' + node.operator + else + return node.type + + + getNodeContext: (node, bounds, type) -> + type ?= @getType node + + innerBounds = @getBounds node + prefix = helper.clipLines @lines, bounds.start, innerBounds.start + suffix = helper.clipLines @lines, innerBounds.end, bounds.end + + return new parser.PreNodeContext type, prefix.length, suffix.length + + jsSocketAndMark: (indentDepth, node, depth, type, bounds, classes, dropdown, empty) -> unless node.type is 'BlockStatement' + bounds ?= @getBounds node + @addSocket - bounds: bounds ? @getBounds node + bounds: bounds depth: depth - precedence: precedence - classes: classes ? [] + + parseContext: type ? 'program' + dropdown: dropdown empty: empty @@ -743,11 +759,11 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser JavaScriptParser.parens = (leading, trailing, node, context) -> # Don't attempt to paren wrap comments - return if '__comment__' in node.classes + return if '__comment__' is node.parseContext if context?.type is 'socket' or - (not context? and 'mostly-value' in node.classes or 'value-only' in node.classes) or - 'ends-with-brace' in node.classes or + (not context? and helper.MOSTLY_VALUE is node.shape or helper.VALUE_ONLY is node.shape) or + SEMICOLON_EXCEPTIONS[node.nodeContext.type] or node.type is 'document' trailing trailing().replace(/;?\s*$/, '') else @@ -761,46 +777,37 @@ JavaScriptParser.parens = (leading, trailing, node, context) -> break unless context is null or context.type isnt 'socket' or - context.precedence > node.precedence + getPrecedence(context.parseContext) > getPrecedence(node.nodeContext.type) + console.log context.parseContext, node.nodeContext.type, getPrecedence(context.parseContext), getPrecedence(node.nodeContext.type) leading '(' + leading() trailing trailing() + ')' JavaScriptParser.drop = (block, context, pred) -> - if context.type is 'socket' - if 'lvalue' in context.classes - if 'Value' in block.classes and block.properties?.length > 0 - return helper.ENCOURAGE - else - return helper.FORBID + if context.parseContext is '__comment__' + return helper.FORBID - else if 'no-drop' in context.classes - return helper.FORBID - - else if 'property-access' in context.classes - if 'works-as-method-call' in block.classes + if context.type is 'socket' + if context.parseContext in ['Lvalue', 'ForEachLHS'] + if block.nodeContext.type is 'ObjectExpression' return helper.ENCOURAGE else return helper.FORBID - else if 'value-only' in block.classes or - 'mostly-value' in block.classes or - 'any-drop' in block.classes or - 'for-statement-init' in context.classes or - ('mostly-block' in block.classes and - 'for-statement-update' in context.classes) + else if block.shape in [helper.VALUE_ONLY, helper.MOSTLY_VALUE, helper.ANY_DROP] or + context.parseContext is 'ForInit' or + (block.shape is helper.MOSTLY_BLOCK and + context.parseContext is 'ForUpdate') return helper.ENCOURAGE - else if 'mostly-block' in block.classes + else if block.shape is helper.MOSTLY_BLOCK return helper.DISCOURAGE else if context.type in ['indent', 'document'] - if 'block-only' in block.classes or - 'mostly-block' in block.classes or - 'any-drop' in block.classes or + if block.shape in [helper.BLOCK_ONLY, helper.MOSTLY_BLOCK, helper.ANY_DROP] or block.type is 'document' return helper.ENCOURAGE - else if 'mostly-value' in block.classes + else if block.shape is helper.MOSTLY_VALUE return helper.DISCOURAGE return helper.DISCOURAGE From 1281efbe60f795daf39b0f4b8cf2f3e1ca412ba4 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 18 Jul 2016 14:08:12 -0400 Subject: [PATCH 37/60] Move CoffeeScript over to new infrastructure as well for the most part --- src/languages/coffee.coffee | 228 ++++++++++++++++---------------- src/languages/javascript.coffee | 5 +- 2 files changed, 118 insertions(+), 115 deletions(-) diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index 6fdc9770..21ebfd23 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -146,19 +146,24 @@ OPERATOR_PRECEDENCES = '**': 7 '%%': 7 -YES = -> yes -NO = -> no +PRECEDENCES = { + 'Semicolon': -2 + 'Range': 100 + 'Arr': 100 + 'For': -3 + 'While': -3 +} -spacestring = (n) -> (' ' for [0...Math.max(0, n)]).join('') +for operator, precedence of OPERATOR_PRECEDENCES + PRECEDENCES['Operator' + operator] = precedence -getClassesFor = (node) -> - classes = [] +getPrecedence = (type) -> + PRECEDENCES[type] ? 0 - classes.push node.nodeType() - if node.nodeType() is 'Call' and (not node.do) and (not node.isNew) - classes.push 'works-as-method-call' +YES = -> yes +NO = -> no - return classes +spacestring = (n) -> (' ' for [0...Math.max(0, n)]).join('') annotateCsNodes = (tree) -> tree.eachChild (child) -> @@ -210,7 +215,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Mark all the nodes # in the block. for node in nodes - @mark node, 3, 0, null, 0 + @mark node, 3, null, 0 # Deal with semicoloned lines # at the root level @@ -323,9 +328,8 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @addSocket { bounds: @boundCombine @getBounds(node.params[0]), @getBounds(node.params[node.params.length - 1]) depth, - precedence: 0, dropdown: null, - classes: ['forbid-all', '__function_param__'] + parseContext: '__comment__' empty: '' } @@ -346,16 +350,15 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser } }, depth, - precedence: 0, dropdown: null, - classes: ['forbid-all', '__function_param__'] + parseContext: '__comment__' empty: '' } - @mark node.body, depth, 0, null, indentDepth + @mark node.body, depth, null, indentDepth # ## mark ## # Mark a single node. The main recursive function. - mark: (node, depth, precedence, wrappingParen, indentDepth) -> + mark: (node, depth, wrappingParen, indentDepth) -> switch node.nodeType() @@ -415,7 +418,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Mark children. We do this at depth + 3 to # make room for semicolon wrappers where necessary. for expr in node.expressions - @mark expr, depth + 3, 0, null, indentDepth + @mark expr, depth + 3, null, indentDepth # Wrap semicolons. @wrapSemicolons node.expressions, depth @@ -430,18 +433,18 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser when 'Parens' if node.body? unless node.body.nodeType() is 'Block' - @mark node.body, depth + 1, 0, (wrappingParen ? node), indentDepth + @mark node.body, depth + 1, (wrappingParen ? node), indentDepth else if node.body.unwrap() is node.body # We are filled with some things # connected by semicolons; wrap them all, - @csBlock node, depth, -2, null, MOSTLY_BLOCK + @csBlock node, depth, 'Semicolon', null, MOSTLY_BLOCK for expr in node.body.expressions - @csSocketAndMark expr, depth + 1, -2, indentDepth + @csSocketAndMark expr, depth + 1, 'Expression', indentDepth else - @mark node.body.unwrap(), depth + 1, 0, (wrappingParen ? node), indentDepth + @mark node.body.unwrap(), depth + 1, (wrappingParen ? node), indentDepth # ### Op ### # Color VALUE, sockets @first and (sometimes) @second @@ -469,61 +472,61 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser node.first?.base?.nodeType?() is 'Literal' return - @csBlock node, depth, OPERATOR_PRECEDENCES[node.operator], wrappingParen, VALUE_ONLY + @csBlock node, depth, 'Operator' + node.operator, wrappingParen, VALUE_ONLY - @csSocketAndMark node.first, depth + 1, OPERATOR_PRECEDENCES[node.operator], indentDepth + @csSocketAndMark node.first, depth + 1, 'Operator' + node.operator, indentDepth if node.second? - @csSocketAndMark node.second, depth + 1, OPERATOR_PRECEDENCES[node.operator], indentDepth + @csSocketAndMark node.second, depth + 1, 'Operator' + node.operator, indentDepth # ### Existence ### # Color VALUE, socket @expression, precedence 100 when 'Existence' - @csBlock node, depth, 100, wrappingParen, VALUE_ONLY - @csSocketAndMark node.expression, depth + 1, 101, indentDepth + @csBlock node, depth, 'Existence', wrappingParen, VALUE_ONLY + @csSocketAndMark node.expression, depth + 1, 'Existence', indentDepth # ### In ### # Color VALUE, sockets @object and @array, precedence 100 when 'In' - @csBlock node, depth, 0, wrappingParen, VALUE_ONLY - @csSocketAndMark node.object, depth + 1, 0, indentDepth - @csSocketAndMark node.array, depth + 1, 0, indentDepth + @csBlock node, depth, 'In', wrappingParen, VALUE_ONLY + @csSocketAndMark node.object, depth + 1, 'In', indentDepth + @csSocketAndMark node.array, depth + 1, 'In', indentDepth # ### Value ### # Completely pass through to @base; we do not care # about this node. when 'Value' if node.properties? and node.properties.length > 0 - @csBlock node, depth, 0, wrappingParen, MOSTLY_VALUE + @csBlock node, depth, 'PropertyAccess', wrappingParen, MOSTLY_VALUE @csSocketAndMark node.base, depth + 1, 0, indentDepth for property in node.properties if property.nodeType() is 'Access' - @csSocketAndMark property.name, depth + 1, -2, indentDepth, PROPERTY_ACCESS + @csSocketAndMark property.name, depth + 1, 'Identifier', indentDepth, PROPERTY_ACCESS else if property.nodeType() is 'Index' - @csSocketAndMark property.index, depth + 1, 0, indentDepth + @csSocketAndMark property.index, depth + 1, 'Expression', indentDepth # Fake-remove backticks hack else if node.base.nodeType() is 'Literal' and (node.base.value is '' or node.base.value is @empty) fakeBlock = - @csBlock node.base, depth, 0, wrappingParen, ANY_DROP + @csBlock node.base, depth, '__flag_to_remove__', wrappingParen, ANY_DROP fakeBlock.flagToRemove = true # Preserved-error backticks hack else if node.base.nodeType() is 'Literal' and /^#/.test(node.base.value) - @csBlock node.base, depth, 0, wrappingParen, ANY_DROP + @csBlock node.base, depth, '__flag_to_strip__', wrappingParen, ANY_DROP errorSocket = @csSocket node.base, depth + 1, -2 errorSocket.flagToStrip = { left: 2, right: 1 } else - @mark node.base, depth + 1, 0, wrappingParen, indentDepth + @mark node.base, depth + 1, wrappingParen, indentDepth # ### Keywords ### when 'Literal' if node.value in STATEMENT_KEYWORDS # handle break and continue - @csBlock node, depth, 0, wrappingParen, BLOCK_ONLY + @csBlock node, depth, 'Keyword', wrappingParen, BLOCK_ONLY else # otherwise, leave it as a white block 0 @@ -548,7 +551,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser classes = MOSTLY_BLOCK else classes = ANY_DROP - @csBlock node, depth, 0, wrappingParen, classes + @csBlock node, depth, 'Call', wrappingParen, classes variableBounds = @getBounds(node.variable) hasCallParen = (@lines[variableBounds.end.line][variableBounds.end.column] == '(') @@ -559,11 +562,11 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser else if not known # In the 'advanced' case where the methodname should be # editable, treat the whole (x.y.fn) as an expression to socket. - @csSocketAndMark node.variable, depth + 1, 0, indentDepth + @csSocketAndMark node.variable, depth + 1, 'Callee', indentDepth else if known.anyobj and node.variable.properties?.length > 0 # In the 'beginner' case of a simple method call with a # simple base object variable, let the variable be socketed. - @csSocketAndMark node.variable.base, depth + 1, 0, indentDepth + @csSocketAndMark node.variable.base, depth + 1, 'PropertyAccess', indentDepth if not known and node.args.length is 0 and not node.do # The only way we can have zero arguments in CoffeeScript @@ -582,13 +585,12 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @addSocket { bounds: {start, end} depth, - precedence: 0, dropdown: null, - classes: ['mostly-value'] + parseContext: 'Expression' empty: '' } else - @csBlock node, depth, 0, wrappingParen, ANY_DROP + @csBlock node, depth, 'Call', wrappingParen, ANY_DROP unless node.do for arg, index in node.args @@ -609,40 +611,40 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Function definition. Color VALUE, sockets @params, # and indent @body. when 'Code' - @csBlock node, depth, 0, wrappingParen, VALUE_ONLY + @csBlock node, depth, 'Function', wrappingParen, VALUE_ONLY @addCode node, depth + 1, indentDepth # ### Assign ### # Color COMMAND, sockets @variable and @value. when 'Assign' - @csBlock node, depth, 0, wrappingParen, MOSTLY_BLOCK - @csSocketAndMark node.variable, depth + 1, 0, indentDepth, LVALUE + @csBlock node, depth, 'Assign', wrappingParen, MOSTLY_BLOCK + @csSocketAndMark node.variable, depth + 1, 'Lvalue', indentDepth, LVALUE if node.value.nodeType() is 'Code' @addCode node.value, depth + 1, indentDepth else - @csSocketAndMark node.value, depth + 1, 0, indentDepth + @csSocketAndMark node.value, depth + 1, 'FunctionBody', indentDepth # ### For ### # Color CONTROL, options sockets @index, @source, @name, @from. # Indent/socket @body. when 'For' - @csBlock node, depth, -3, wrappingParen, MOSTLY_BLOCK + @csBlock node, depth, 'For', wrappingParen, MOSTLY_BLOCK for childName in ['source', 'from', 'guard', 'step'] - if node[childName]? then @csSocketAndMark node[childName], depth + 1, 0, indentDepth + if node[childName]? then @csSocketAndMark node[childName], depth + 1, 'ForModifier', indentDepth for childName in ['index', 'name'] - if node[childName]? then @csSocketAndMark node[childName], depth + 1, 0, indentDepth, FORBID_ALL + if node[childName]? then @csSocketAndMark node[childName], depth + 1, 'Lvalue', indentDepth, FORBID_ALL - @mark node.body, depth + 1, 0, null, indentDepth + @mark node.body, depth + 1, null, indentDepth # ### Range ### # Color VALUE, sockets @from and @to. when 'Range' - @csBlock node, depth, 100, wrappingParen, VALUE_ONLY - @csSocketAndMark node.from, depth, 0, indentDepth - @csSocketAndMark node.to, depth, 0, indentDepth + @csBlock node, depth, 'Range', wrappingParen, VALUE_ONLY + @csSocketAndMark node.from, depth, 'Expression', indentDepth + @csSocketAndMark node.to, depth, 'Expression', indentDepth # ### If ### # Color CONTROL, socket @condition. @@ -651,7 +653,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Special case: "unless" keyword; in this case # we want to skip the Op that wraps the condition. when 'If' - @csBlock node, depth, 0, wrappingParen, MOSTLY_BLOCK, {addButton: '+'} + @csBlock node, depth, 'If', wrappingParen, MOSTLY_BLOCK, {addButton: '+'} # Check to see if we are an "unless". # We will deem that we are an unless if: @@ -675,9 +677,9 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser else ### - @csSocketAndMark node.rawCondition, depth + 1, 0, indentDepth + @csSocketAndMark node.rawCondition, depth + 1, 'If', indentDepth - @mark node.body, depth + 1, 0, null, indentDepth + @mark node.body, depth + 1, null, indentDepth currentNode = node @@ -685,14 +687,14 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser if currentNode.isChain currentNode = currentNode.elseBodyNode() @csSocketAndMark currentNode.rawCondition, depth + 1, 0, indentDepth - @mark currentNode.body, depth + 1, 0, null, indentDepth + @mark currentNode.body, depth + 1, null, indentDepth else if currentNode.elseBody? # Artificially "mark" the line containing the "else" # token, so that the following body can be single-line # if necessary. @flagLineAsMarked currentNode.elseToken.first_line - @mark currentNode.elseBody, depth + 1, 0, null, indentDepth + @mark currentNode.elseBody, depth + 1, null, indentDepth currentNode = null else @@ -701,71 +703,71 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # ### Arr ### # Color VALUE, sockets @objects. when 'Arr' - @csBlock node, depth, 100, wrappingParen, VALUE_ONLY + @csBlock node, depth, 'Arr', wrappingParen, VALUE_ONLY if node.objects.length > 0 @csIndentAndMark indentDepth, node.objects, depth + 1 for object in node.objects if object.nodeType() is 'Value' and object.base.nodeType() is 'Literal' and object.properties?.length in [0, undefined] - @csBlock object, depth + 2, 100, null, VALUE_ONLY + @csBlock object, depth + 2, 'Value', null, VALUE_ONLY # ### Return ### # Color RETURN, optional socket @expression. when 'Return' - @csBlock node, depth, 0, wrappingParen, BLOCK_ONLY + @csBlock node, depth, 'Return', wrappingParen, BLOCK_ONLY if node.expression? - @csSocketAndMark node.expression, depth + 1, 0, indentDepth + @csSocketAndMark node.expression, depth + 1, 'Expression', indentDepth # ### While ### # Color CONTROL. Socket @condition, socket/indent @body. when 'While' - @csBlock node, depth, -3, wrappingParen, MOSTLY_BLOCK - @csSocketAndMark node.rawCondition, depth + 1, 0, indentDepth - if node.guard? then @csSocketAndMark node.guard, depth + 1, 0, indentDepth - @mark node.body, depth + 1, 0, null, indentDepth + @csBlock node, depth, 'While', wrappingParen, MOSTLY_BLOCK + @csSocketAndMark node.rawCondition, depth + 1, 'Expression', indentDepth + if node.guard? then @csSocketAndMark node.guard, depth + 1, 'Expression', indentDepth + @mark node.body, depth + 1, null, indentDepth # ### Switch ### # Color CONTROL. Socket @subject, optional sockets @cases[x][0], # indent/socket @cases[x][1]. indent/socket @otherwise. when 'Switch' - @csBlock node, depth, 0, wrappingParen, MOSTLY_BLOCK + @csBlock node, depth, 'Switch', wrappingParen, MOSTLY_BLOCK - if node.subject? then @csSocketAndMark node.subject, depth + 1, 0, indentDepth + if node.subject? then @csSocketAndMark node.subject, depth + 1, 'Expression', indentDepth for switchCase in node.cases if switchCase[0].constructor is Array for condition in switchCase[0] - @csSocketAndMark condition, depth + 1, 0, indentDepth # (condition) + @csSocketAndMark condition, depth + 1, 'Expression', indentDepth # (condition) else - @csSocketAndMark switchCase[0], depth + 1, 0, indentDepth # (condition) - @mark switchCase[1], depth + 1, 0, null, indentDepth # (body) + @csSocketAndMark switchCase[0], depth + 1, 'Expression', indentDepth # (condition) + @mark switchCase[1], depth + 1, null, indentDepth # (body) if node.otherwise? - @mark node.otherwise, depth + 1, 0, null, indentDepth + @mark node.otherwise, depth + 1, null, indentDepth # ### Class ### # Color CONTROL. Optional sockets @variable, @parent. Optional indent/socket # @obdy. when 'Class' - @csBlock node, depth, 0, wrappingParen, ANY_DROP + @csBlock node, depth, 'Class', wrappingParen, ANY_DROP - if node.variable? then @csSocketAndMark node.variable, depth + 1, 0, indentDepth, FORBID_ALL - if node.parent? then @csSocketAndMark node.parent, depth + 1, 0, indentDepth + if node.variable? then @csSocketAndMark node.variable, depth + 1, 'Identifier', indentDepth, FORBID_ALL + if node.parent? then @csSocketAndMark node.parent, depth + 1, 'Expression', indentDepth - if node.body? then @mark node.body, depth + 1, 0, null, indentDepth + if node.body? then @mark node.body, depth + 1, null, indentDepth # ### Obj ### # Color VALUE. Optional sockets @property[x].variable, @property[x].value. # TODO: This doesn't quite line up with what we want it to be visually; # maybe our View architecture is wrong. when 'Obj' - @csBlock node, depth, 0, wrappingParen, VALUE_ONLY + @csBlock node, depth, 'Obj', wrappingParen, VALUE_ONLY for property in node.properties if property.nodeType() is 'Assign' - @csSocketAndMark property.variable, depth + 1, 0, indentDepth, FORBID_ALL - @csSocketAndMark property.value, depth + 1, 0, indentDepth + @csSocketAndMark property.variable, depth + 1, 'Identifier', indentDepth, FORBID_ALL + @csSocketAndMark property.value, depth + 1, 'Expression', indentDepth handleButton: (text, button, oldBlock) -> @@ -949,18 +951,21 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser return container + getNodeContext: (type, node, wrappingParen) -> + return new parser.PreNodeContext type, 0, 0 # TODO use wrappingParen properly + # ## csBlock ## - # A general utility function for adding an ICE editor + # A general utility function for adding an Droplet editor # block around a given node. - csBlock: (node, depth, precedence, wrappingParen, classes = [], buttons) -> + csBlock: (node, depth, type, wrappingParen, buttons) -> @addBlock { bounds: @getBounds (wrappingParen ? node) depth: depth precedence: precedence color: @getColor(node) - classes: getClassesFor(node).concat classes - parenWrapped: wrappingParen? buttons: buttons + + nodeContext: @getNodeContext type, node, wrappingParen } # Add an indent node and guess @@ -999,18 +1004,19 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # ## csSocket ## # A similar utility function for adding sockets. - csSocket: (node, depth, precedence, classes = [], dropdown, empty) -> + csSocket: (node, depth, type, dropdown, empty) -> @addSocket { bounds: @getBounds node - depth, precedence, dropdown, empty - classes: getClassesFor(node).concat classes + depth, + parseContext: type + dropdown, empty } # ## csSocketAndMark ## # Adds a socket for a node, and recursively @marks it. - csSocketAndMark: (node, depth, precedence, indentDepth, classes, dropdown, empty) -> - socket = @csSocket node, depth, precedence, classes, dropdown, empty - @mark node, depth + 1, precedence, null, indentDepth + csSocketAndMark: (node, depth, type, indentDepth, classes, dropdown, empty) -> + socket = @csSocket node, depth, type, classes, dropdown, empty + @mark node, depth + 1, null, indentDepth return socket # ## wrapSemicolonLine ## @@ -1024,15 +1030,15 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @addBlock { bounds: surroundingBounds depth: depth + 1 - precedence: -2 + parseContext: 'program' + nodeContext: new parser.PreNodeContext('semicolon', 0, 0), # TODO Determine parenthesis wrapping etc. for more rigorous paren-wrapping mechanics color: @opts.categories['command'].color - socketLevel: ANY_DROP - classes: ['semicolon'] + shape: ANY_DROP } # Add sockets for each expression for child in expressions - @csSocket child, depth + 2, -2 + @csSocket child, depth + 2, 'semicolon' # ## wrapSemicolons ## # If there are mutliple expressions we have on the same line, @@ -1134,47 +1140,40 @@ CoffeeScriptParser.endComment = '###' CoffeeScriptParser.startSingleLineComment = '# ' CoffeeScriptParser.drop = (block, context, pred) -> - if context.type is 'socket' - if 'forbid-all' in context.classes - return helper.FORBID - - if 'lvalue' in context.classes - if 'Value' in block.classes and block.properties?.length > 0 - return helper.ENCOURAGE - else - return helper.FORBID + if context.parseContext is '__comment__' + return helper.FORBID - else if 'property-access' in context.classes - if 'works-as-method-call' in block.classes + if context.type is 'socket' + # TODO forbid-all replacements + # + if context.parseContext is 'Lvalue' + if block.nodeContext.type is 'PropertyAccess' return helper.ENCOURAGE else return helper.FORBID - else if 'value-only' in block.classes or - 'mostly-value' in block.classes or - 'any-drop' in block.classes + else if block.shape in [helper.VALUE_ONLY, helper.MOSTLY_VALUE, helper.ANY_DROP] return helper.ENCOURAGE - else if 'mostly-block' in block.classes + else if block.shape is helper.MOSTLY_BLOCK return helper.DISCOURAGE else if context.type in ['indent', 'document'] - if 'block-only' in block.classes or - 'mostly-block' in block.classes or - 'any-drop' in block.classes or + if block.shape in [helper.BLOCK_ONLY, helper.MOSTLY_BLOCK, helper.ANY_DROP] or block.type is 'document' return helper.ENCOURAGE - else if 'mostly-value' in block.classes + else if block.shape is helper.MOSTLY_VALUE return helper.DISCOURAGE return helper.DISCOURAGE CoffeeScriptParser.parens = (leading, trailing, node, context) -> # Don't attempt to paren wrap comments - return if '__comment__' in node.classes + return if '__comment__' is node.parseContext trailing trailing().replace /\s*,\s*$/, '' + # Remove existing parentheses while true if leading().match(/^\s*\(/)? and trailing().match(/\)\s*/)? @@ -1183,8 +1182,9 @@ CoffeeScriptParser.parens = (leading, trailing, node, context) -> else break if context is null or context.type isnt 'socket' or - context.precedence < node.precedence + getPrecedence(context.parseContext) < getPrecedence(node.nodeContext.type) else + console.log 'adding as the result of', context.parseContext, node.nodeContext.type, getPrecedence(context.parseContext), getPrecedence(node.nodeContext.type) leading '(' + leading() trailing trailing() + ')' diff --git a/src/languages/javascript.coffee b/src/languages/javascript.coffee index 527185c6..f737eb7b 100644 --- a/src/languages/javascript.coffee +++ b/src/languages/javascript.coffee @@ -787,7 +787,10 @@ JavaScriptParser.drop = (block, context, pred) -> return helper.FORBID if context.type is 'socket' - if context.parseContext in ['Lvalue', 'ForEachLHS'] + if context.parseContext is 'Identifier' + return helper.FORBID + + else if context.parseContext in ['Lvalue', 'ForEachLHS'] if block.nodeContext.type is 'ObjectExpression' return helper.ENCOURAGE else From 0fd6abecd4817f0c1d3830797e89ef460c069045 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 18 Jul 2016 14:18:05 -0400 Subject: [PATCH 38/60] Handle buttons and such --- src/languages/coffee.coffee | 38 ++++++++++++++++----------------- src/languages/javascript.coffee | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index 21ebfd23..24d2b39e 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -11,14 +11,13 @@ parser = require '../parser.coffee' {CoffeeScript} = require '../../vendor/coffee-script.js' -ANY_DROP = ['any-drop'] -BLOCK_ONLY = ['block-only'] -MOSTLY_BLOCK = ['mostly-block'] -MOSTLY_VALUE = ['mostly-value'] -VALUE_ONLY = ['value-only'] -LVALUE = ['lvalue'] -FORBID_ALL = ['forbid-all'] -PROPERTY_ACCESS = ['prop-access'] +{ + ANY_DROP + BLOCK_ONLY + MOSTLY_BLOCK + MOSTLY_VALUE + VALUE_ONLY +} = helper KNOWN_FUNCTIONS = 'alert' : {} @@ -501,7 +500,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @csSocketAndMark node.base, depth + 1, 0, indentDepth for property in node.properties if property.nodeType() is 'Access' - @csSocketAndMark property.name, depth + 1, 'Identifier', indentDepth, PROPERTY_ACCESS + @csSocketAndMark property.name, depth + 1, 'Identifier', indentDepth else if property.nodeType() is 'Index' @csSocketAndMark property.index, depth + 1, 'Expression', indentDepth @@ -603,9 +602,9 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # of a function call will be melded into the parent block. @addCode arg, depth + 1, indentDepth else if not known and hasCallParen and index is 0 and node.args.length is 1 - @csSocketAndMark arg, depth + 1, precedence, indentDepth, null, known?.fn?.dropdown?[index], '' + @csSocketAndMark arg, depth + 1, precedence, indentDepth, known?.fn?.dropdown?[index], '' else - @csSocketAndMark arg, depth + 1, precedence, indentDepth, null, known?.fn?.dropdown?[index] + @csSocketAndMark arg, depth + 1, precedence, indentDepth, known?.fn?.dropdown?[index] # ### Code ### # Function definition. Color VALUE, sockets @params, @@ -618,7 +617,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Color COMMAND, sockets @variable and @value. when 'Assign' @csBlock node, depth, 'Assign', wrappingParen, MOSTLY_BLOCK - @csSocketAndMark node.variable, depth + 1, 'Lvalue', indentDepth, LVALUE + @csSocketAndMark node.variable, depth + 1, 'Lvalue', indentDepth if node.value.nodeType() is 'Code' @addCode node.value, depth + 1, indentDepth @@ -635,7 +634,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser if node[childName]? then @csSocketAndMark node[childName], depth + 1, 'ForModifier', indentDepth for childName in ['index', 'name'] - if node[childName]? then @csSocketAndMark node[childName], depth + 1, 'Lvalue', indentDepth, FORBID_ALL + if node[childName]? then @csSocketAndMark node[childName], depth + 1, 'Lvalue', indentDepth @mark node.body, depth + 1, null, indentDepth @@ -752,7 +751,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser when 'Class' @csBlock node, depth, 'Class', wrappingParen, ANY_DROP - if node.variable? then @csSocketAndMark node.variable, depth + 1, 'Identifier', indentDepth, FORBID_ALL + if node.variable? then @csSocketAndMark node.variable, depth + 1, 'Identifier', indentDepth if node.parent? then @csSocketAndMark node.parent, depth + 1, 'Expression', indentDepth if node.body? then @mark node.body, depth + 1, null, indentDepth @@ -766,12 +765,12 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser for property in node.properties if property.nodeType() is 'Assign' - @csSocketAndMark property.variable, depth + 1, 'Identifier', indentDepth, FORBID_ALL + @csSocketAndMark property.variable, depth + 1, 'Identifier', indentDepth @csSocketAndMark property.value, depth + 1, 'Expression', indentDepth handleButton: (text, button, oldBlock) -> - if button is 'add-button' and 'If' in oldBlock.classes + if button is 'add-button' and oldBlock.nodeContext.type is 'If' # Parse to find the last "else" or "else if" node = CoffeeScript.nodes(text, { locations: true @@ -957,13 +956,14 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # ## csBlock ## # A general utility function for adding an Droplet editor # block around a given node. - csBlock: (node, depth, type, wrappingParen, buttons) -> + csBlock: (node, depth, type, wrappingParen, shape, buttons) -> @addBlock { bounds: @getBounds (wrappingParen ? node) depth: depth precedence: precedence color: @getColor(node) buttons: buttons + shape: shape nodeContext: @getNodeContext type, node, wrappingParen } @@ -1014,8 +1014,8 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # ## csSocketAndMark ## # Adds a socket for a node, and recursively @marks it. - csSocketAndMark: (node, depth, type, indentDepth, classes, dropdown, empty) -> - socket = @csSocket node, depth, type, classes, dropdown, empty + csSocketAndMark: (node, depth, type, indentDepth, dropdown, empty) -> + socket = @csSocket node, depth, type, dropdown, empty @mark node, depth + 1, null, indentDepth return socket diff --git a/src/languages/javascript.coffee b/src/languages/javascript.coffee index f737eb7b..d15a9eab 100644 --- a/src/languages/javascript.coffee +++ b/src/languages/javascript.coffee @@ -349,7 +349,7 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser } handleButton: (text, button, oldBlock) -> - if button is 'add-button' and 'IfStatement' in oldBlock.classes + if button is 'add-button' and oldBlock.nodeContext.type is 'IfStatement' # Parse to find the last "else" or "else if" node = acorn.parse(text, { locations: true @@ -382,7 +382,7 @@ exports.JavaScriptParser = class JavaScriptParser extends parser.Parser return text + ''' else { __ }''' - else if 'CallExpression' in oldBlock.classes + else if oldBlock.nodeContext.type is 'CallExpression' # Parse to find the last "else" or "else if" node = acorn.parse(text, { line: 0 From 8cb7f3f3efbf63698937ca0e39b4547afab10f1e Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Mon, 18 Jul 2016 19:13:15 -0400 Subject: [PATCH 39/60] Fix all tests but one, which requires new infrastructure --- src/languages/coffee.coffee | 2 +- src/languages/html.coffee | 30 +- src/model.coffee | 94 +- src/treewalk.coffee | 3 +- test/data/c-freeze-populator.js | 5305 ++++++++++++++++++++++++++++++- test/data/parserSuccess.js | 103 +- test/src/cstest.coffee | 954 ++++-- test/src/ctest.coffee | 18 +- test/src/htmltest.coffee | 866 +++-- test/src/jstest.coffee | 1423 ++++++--- test/src/tests.coffee | 18 +- test/src/uitest.coffee | 6 +- 12 files changed, 7712 insertions(+), 1110 deletions(-) diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index 24d2b39e..a7cf9329 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -1000,7 +1000,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser csIndentAndMark: (indentDepth, nodes, depth) -> trueDepth = @csIndent indentDepth, nodes[0], nodes[nodes.length - 1], depth for node in nodes - @mark node, depth + 1, 0, null, trueDepth + @mark node, depth + 1, null, trueDepth # ## csSocket ## # A similar utility function for adding sockets. diff --git a/src/languages/html.coffee b/src/languages/html.coffee index 3fc50d44..ad82c4cf 100644 --- a/src/languages/html.coffee +++ b/src/languages/html.coffee @@ -201,11 +201,11 @@ exports.HTMLParser = class HTMLParser extends parser.Parser @lines = @text.split '\n' - getPrecedence: (node) -> 1 + getNodeContext: (node) -> new parser.PreNodeContext node.type, 0 ,0 - getClasses: (node) -> - classes = [node.nodeName] - return classes + getParseContext: (node) -> node.type + + getIndentContext: (node) -> node.type getButtons: (node) -> buttons = {} @@ -417,27 +417,29 @@ exports.HTMLParser = class HTMLParser extends parser.Parser return bounds - getSocketLevel: (node) -> helper.ANY_DROP + getShape: (node) -> helper.ANY_DROP htmlBlock: (node, depth, bounds) -> @addBlock bounds: bounds ? @getBounds node depth: depth - precedence: @getPrecedence node color: @getColor node - classes: @getClasses node - socketLevel: @getSocketLevel node parseContext: node.nodeName buttons: @getButtons node + parseContext: @getParseContext node + nodeContext: @getNodeContext node + shape: @getShape node + htmlSocket: (node, depth, precedence, bounds, classes, noDropdown) -> @addSocket bounds: bounds ? @getBounds node depth: depth precedence: precedence - classes: classes ? @getClasses node dropdown: if noDropdown then null else @getDropdown node + parseContext: @getParseContext node + getIndentPrefix: (bounds, indentDepth, depth) -> if bounds.end.line - bounds.start.line < 1 return DEFAULT_INDENT_DEPTH @@ -563,7 +565,7 @@ exports.HTMLParser = class HTMLParser extends parser.Parser bounds: indentBounds depth: depth prefix: prefix - classes: @getClasses node + indentContext: @getIndentContext node lastChild = null else unless TAGS[node.nodeName]?.content is 'optional' or @@ -599,10 +601,10 @@ HTMLParser.parens = (leading, trailing, node, context) -> HTMLParser.drop = (block, context, pred, next) -> - blockType = block.classes[0] - contextType = context.classes[0] - predType = pred?.classes[0] - nextType = next?.classes[0] + blockType = block.parseContext + contextType = context.indentContext ? context.parseContext + predType = pred?.parseContext + nextType = next?.parseContext check = (blockType, allowList, forbidList = []) -> if blockType in allowList and blockType not in forbidList diff --git a/src/model.coffee b/src/model.coffee index 9c30f5bd..78244799 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -628,13 +628,19 @@ exports.Container = class Container extends List # Simple debugging output representation # of the tokens in this Container. Like XML. serialize: -> - str = @_serialize_header() + result = [@_serialize_header()] @traverseOneLevel (child) -> - str += child.serialize() - str += @_serialize_footer() + result = result.concat child.serialize() + result.push @_serialize_footer() - _serialize_header: "" - _serialize_header: "" + return result + + _serialize_header: { + type: 'start' + } + _serialize_header: { + type: 'end' + } # ## contents ## # Get a cloned version of a @@ -1016,13 +1022,21 @@ exports.Block = class Block extends Container return clone - _serialize_header: -> "" - _serialize_footer: -> "" + _serialize_header: -> { + type: 'blockStart' + color: @color + shape: @shape + parseContext: @parseContext + nodeContext: { + type: @nodeContext.type + prefix: @nodeContext.prefix + suffix: @nodeContext.suffix + } + } + + _serialize_footer: -> { + type: 'blockEnd' + } # Socket # ================== @@ -1082,17 +1096,16 @@ exports.Socket = class Socket extends Container _cloneEmpty: -> new Socket @emptyString, @handwritten, @dropdown, @parseContext - _serialize_header: -> "" + _serialize_header: -> { + type: 'socketStart' + parseContext: @parseContext + handwritten: @handwritten + dropdown: @dropdown? + } - _serialize_footer: -> "" + _serialize_footer: -> { + type: 'socketEnd' + } # Indent # ================== @@ -1108,7 +1121,6 @@ exports.IndentEndToken = class IndentEndToken extends EndToken if opts.preserveEmpty and @prev.prev is @container.start return @container.emptyString else '' - serialize: -> "" exports.Indent = class Indent extends Container constructor: (@emptyString, @prefix = '', @indentContext = null) -> @@ -1124,12 +1136,15 @@ exports.Indent = class Indent extends Container _cloneEmpty: -> new Indent @emptyString, @prefix, @indentContext firstChild: -> return @_firstChild() - _serialize_header: -> "" - _serialize_footer: -> "" + _serialize_header: -> { + type: 'indentStart' + prefix: @prefix + indentContext: @indentContext + } + + _serialize_footer: -> { + type: 'indentEnd' + } # Document @@ -1137,11 +1152,9 @@ exports.Indent = class Indent extends Container exports.DocumentStartToken = class DocumentStartToken extends StartToken constructor: (@container) -> super; @type = 'documentStart' - serialize: -> "" exports.DocumentEndToken = class DocumentEndToken extends EndToken constructor: (@container) -> super; @type = 'documentEnd' - serialize: -> "" exports.Document = class Document extends Container constructor: (@indentContext, @opts = {}) -> @@ -1155,8 +1168,14 @@ exports.Document = class Document extends Container _cloneEmpty: -> new Document(@indentContext, @opts) firstChild: -> return @_firstChild() - _serialize_header: -> "" - _serialize_footer: -> "" + _serialize_header: -> { + type: 'documentStart' + indentContext: @indentContext + } + + _serialize_footer: -> { + type: 'documentEnd' + } # Text @@ -1173,14 +1192,19 @@ exports.TextToken = class TextToken extends Token @notifyChange() stringify: -> @_value - serialize: -> helper.escapeXMLText @_value + serialize: -> @_value clone: -> new TextToken @_value exports.NewlineToken = class NewlineToken extends Token constructor: (@specialIndent) -> super; @type = 'newline' stringify: -> '\n' + (@specialIndent ? @getIndent()) - serialize: -> '\n' + + serialize: -> { + type: 'newline' + specialIndent: @specialIndent + } + clone: -> new NewlineToken @specialIndent # Utility function for traversing all diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 65234555..6c6cdff5 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -208,7 +208,8 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth parseContext: rules[0] - if config.empty? and not @opts.preserveEmpty and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.empty + if config.EMPTY_STRINGS? and not @opts.preserveEmpty and + helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.EMPTY_STRINGSconfig.empty @flagToRemove node.bounds, depth + 1 if config.droppabilityGraph? diff --git a/test/data/c-freeze-populator.js b/test/data/c-freeze-populator.js index fd2b743f..e1262b0d 100644 --- a/test/data/c-freeze-populator.js +++ b/test/data/c-freeze-populator.js @@ -1,87 +1,5224 @@ window.FREEZE_DATA = {}; -window.FREEZE_DATA.freezeTest = "#include &lt;stdio.h&gt;\n" + - "#include &lt;stdlib.h&gt;\n" + - "#define MAXLEN 100\n" + - "\n" + - "// Linked list\n" + - "struct List {\n" + - "long long data;\n" + - "struct List *next;\n" + - "struct List *prev;\n" + - "};\n" + - "typedef struct List List;\n" + - "\n" + - "// Memoryless swap\n" + - "void swap(long long *a, long long *b) {\n" + - "*a ^= *b;\n" + - "*b ^= *a;\n" + - "*a ^= *b;\n" + - "}\n" + - "\n" + - "// Test if sorted\n" + - "int sorted(List *head, int (*fn)(long long, long long)) {\n" + - "for (List *cursor = head; cursor && cursor-&gt;next; cursor = cursor-&gt;next) {\n" + - "if (!fn(cursor-&gt;data, cursor-&gt;next-&gt;data)) {\n" + - "return 0;\n" + - "}\n" + - "}\n" + - "return 1;\n" + - "}\n" + - "\n" + - "// Bubble sort\n" + - "void sort(List *head, int (*fn)(long long, long long)) {\n" + - "while (!sorted(head, fn)) {\n" + - "for (List *cursor = head; cursor && cursor-&gt;next; cursor = cursor-&gt;next) {\n" + - "if (!fn(cursor-&gt;data, cursor-&gt;next-&gt;data))\n" + - " swap(&cursor-&gt;data, &cursor-&gt;next-&gt;data);\n" + - "}\n" + - "}\n" + - "}\n" + - "\n" + - "// Comparator\n" + - "int comparator(long long a, long long b) {\n" + - "return (a &gt; b);\n" + - "}\n" + - "\n" + - "// Main\n" + - "int main(int n, char *args[]) {\n" + - "// Arbitrary array initializer just o test that syntax\n" + - "int arbitraryArray[] = {1, 2, 3, 4, 5};\n" + - "int length;\n" + - "scanf("%d", &length);\n" + - "if (length &gt; MAXLEN) {\n" + - "puts("Error: list is too large");\n" + - "return 1;\n" + - "}\n" + - "List *head = (List*)malloc(sizeof(List));\n" + - "scanf("%d", &head-&gt;data);\n" + - "head-&gt;prev = NULL;\n" + - "List *cursor = head;\n" + - "int temp;\n" + - "for (int i = 0; i &lt; length - 1; i++) {\n" + - "cursor-&gt;next = (List*)malloc(sizeof(List));\n" + - "cursor = cursor-&gt;next;\n" + - "scanf("%d", &temp);\n" + - "cursor-&gt;data = (long long)temp;\n" + - "}\n" + - "sort(head, comparator);\n" + - "for (cursor = head; cursor; cursor = cursor-&gt;next) {\n" + - "printf("%d ", cursor-&gt;data);\n" + - "}\n" + - "puts("\\n" + - "");\n" + - "return 0;\n" + - "}"; +window.FREEZE_DATA.freezeTest = [ + { + "indentContext": "translationUnit", + "type": "documentStart" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "#include <", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + "stdio.h", + { + "type": "socketEnd" + }, + ">", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "#include <", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + "stdlib.h", + { + "type": "socketEnd" + }, + ">", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "#define ", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + "MAXLEN", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + "100", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Linked list", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "struct ", + "suffix": "};", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "struct ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " {", + { + "indentContext": "structDeclaration", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long ", + "suffix": "", + "type": "specifierQualifierList" + }, + "parseContext": "structDeclaration", + "shape": 0, + "type": "blockStart" + }, + "long ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "specifierQualifierList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long ", + "suffix": "", + "type": "specifierQualifierList" + }, + "parseContext": "specifierQualifierList", + "shape": 0, + "type": "blockStart" + }, + "long ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "specifierQualifierList", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "struct ", + "suffix": ";", + "type": "structDeclaration" + }, + "parseContext": "structDeclaration", + "shape": 1, + "type": "blockStart" + }, + "struct ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "struct ", + "suffix": ";", + "type": "structDeclaration" + }, + "parseContext": "structDeclaration", + "shape": 1, + "type": "blockStart" + }, + "struct ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "prev", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "};", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "typedef struct ", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "typedef struct ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifier", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Memoryless swap", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "void ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "void ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "swap", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long long *", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "long long *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long long *", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "long long *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ^= ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ^= ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ^= ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Test if sorted", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "sorted", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "int (*", + "suffix": ")", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "int (*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "fn", + { + "type": "socketEnd" + }, + ")(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "long long", + "suffix": "long long", + "type": "declarationSpecifiers2" + }, + "parseContext": "declarationSpecifiers2", + "shape": 0, + "type": "blockStart" + }, + "long long", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "long long", + "suffix": "long long", + "type": "declarationSpecifiers2" + }, + "parseContext": "declarationSpecifiers2", + "shape": 0, + "type": "blockStart" + }, + "long long", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "for (", + "suffix": "}", + "type": "iterationStatement" + }, + "parseContext": "iterationStatement", + "shape": 1, + "type": "blockStart" + }, + "for (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declaration", + "type": "socketStart" + }, + { + "color": "control", + "nodeContext": { + "prefix": "", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "logicalAndExpression" + }, + "parseContext": "logicalAndExpression", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "logicalAndExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " && ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "inclusiveOrExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "; ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "assignmentExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "if (", + "suffix": "}", + "type": "selectionStatement" + }, + "parseContext": "selectionStatement", + "shape": 1, + "type": "blockStart" + }, + "if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "!", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "!", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "fn", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "1", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Bubble sort", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "void ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "void ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "sort", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "int (*", + "suffix": ")", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "int (*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "fn", + { + "type": "socketEnd" + }, + ")(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "long long", + "suffix": "long long", + "type": "declarationSpecifiers2" + }, + "parseContext": "declarationSpecifiers2", + "shape": 0, + "type": "blockStart" + }, + "long long", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "long long", + "suffix": "long long", + "type": "declarationSpecifiers2" + }, + "parseContext": "declarationSpecifiers2", + "shape": 0, + "type": "blockStart" + }, + "long long", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "while (", + "suffix": "}", + "type": "iterationStatement" + }, + "parseContext": "iterationStatement", + "shape": 1, + "type": "blockStart" + }, + "while (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "!", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "!", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "sorted", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "fn", + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "for (", + "suffix": "}", + "type": "iterationStatement" + }, + "parseContext": "iterationStatement", + "shape": 1, + "type": "blockStart" + }, + "for (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declaration", + "type": "socketStart" + }, + { + "color": "control", + "nodeContext": { + "prefix": "", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "logicalAndExpression" + }, + "parseContext": "logicalAndExpression", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "logicalAndExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " && ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "inclusiveOrExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "; ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "assignmentExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "if (", + "suffix": "", + "type": "selectionStatement" + }, + "parseContext": "selectionStatement", + "shape": 1, + "type": "blockStart" + }, + "if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "!", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "!", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "fn", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "specialIndent": undefined, + "type": "newline" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "statement", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "swap", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "&", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "&", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "&", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "&", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Comparator", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "comparator", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long long ", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "long long ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarator", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long long ", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "long long ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarator", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "relationalExpression" + }, + "parseContext": "primaryExpression", + "shape": 4, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "relationalExpression", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " > ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "shiftExpression", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Main", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "main", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "int ", + "suffix": "", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarator", + "type": "socketStart" + }, + "n", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "parameterDeclaration", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "char *", + "suffix": "[]", + "type": "parameterDeclaration" + }, + "parseContext": "parameterDeclaration", + "shape": 1, + "type": "blockStart" + }, + "char *", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "args", + { + "type": "socketEnd" + }, + "[]", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "//", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " Arbitrary array initializer just o test that syntax", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "arbitraryArray", + { + "type": "socketEnd" + }, + "[] = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "{", + "suffix": "}", + "type": "initializer" + }, + "parseContext": "initializer", + "shape": 4, + "type": "blockStart" + }, + "{", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializerList", + "type": "socketStart" + }, + "1", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "2", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "3", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "4", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "5", + { + "type": "socketEnd" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifier", + "type": "socketStart" + }, + "length", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "scanf(", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + "scanf(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "\"%d\"", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "&", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "&", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "length", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "if (", + "suffix": "}", + "type": "selectionStatement" + }, + "parseContext": "selectionStatement", + "shape": 1, + "type": "blockStart" + }, + "if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "relationalExpression" + }, + "parseContext": "relationalExpression", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "relationalExpression", + "type": "socketStart" + }, + "length", + { + "type": "socketEnd" + }, + " > ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "shiftExpression", + "type": "socketStart" + }, + "MAXLEN", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "puts(", + "suffix": ");", + "type": "specialMethodCall" + }, + "parseContext": "specialMethodCall", + "shape": 0, + "type": "blockStart" + }, + "puts(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "\"Error: list is too large\"", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "1", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "(", + "suffix": "", + "type": "castExpression" + }, + "parseContext": "castExpression", + "shape": 4, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "typeName", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "*", + "type": "typeName" + }, + "parseContext": "typeName", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "specifierQualifierList", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + "*", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "malloc", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "sizeof(", + "suffix": ")", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "sizeof(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "typeName", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "scanf(", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + "scanf(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "\"%d\"", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "&", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "&", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "prev", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "NULL", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifiers", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "*", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + "*", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarationSpecifier", + "type": "socketStart" + }, + "temp", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "for (", + "suffix": "}", + "type": "iterationStatement" + }, + "parseContext": "iterationStatement", + "shape": 1, + "type": "blockStart" + }, + "for (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "declaration", + "type": "socketStart" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": ";", + "type": "declaration" + }, + "parseContext": "declaration", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initDeclaratorList", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "initDeclarator" + }, + "parseContext": "initDeclarator", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "declarator", + "type": "socketStart" + }, + "i", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "initializer", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "relationalExpression" + }, + "parseContext": "relationalExpression", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "relationalExpression", + "type": "socketStart" + }, + "i", + { + "type": "socketEnd" + }, + " < ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "shiftExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "additiveExpression" + }, + "parseContext": "additiveExpression", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "additiveExpression", + "type": "socketStart" + }, + "length", + { + "type": "socketEnd" + }, + " - ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "multiplicativeExpression", + "type": "socketStart" + }, + "1", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "; ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "++", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "i", + { + "type": "socketEnd" + }, + "++", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "(", + "suffix": "", + "type": "castExpression" + }, + "parseContext": "castExpression", + "shape": 4, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "typeName", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "", + "suffix": "*", + "type": "typeName" + }, + "parseContext": "typeName", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "specifierQualifierList", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + "*", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "malloc", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "sizeof(", + "suffix": ")", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "sizeof(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "typeName", + "type": "socketStart" + }, + "List", + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "scanf(", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + "scanf(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "\"%d\"", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "&", + "suffix": "", + "type": "unaryExpression" + }, + "parseContext": "unaryExpression", + "shape": 4, + "type": "blockStart" + }, + "&", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "temp", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "value", + "nodeContext": { + "prefix": "(", + "suffix": "", + "type": "castExpression" + }, + "parseContext": "castExpression", + "shape": 4, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "typeName", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "long long", + "suffix": "long long", + "type": "specifierQualifierList" + }, + "parseContext": "specifierQualifierList", + "shape": 0, + "type": "blockStart" + }, + "long long", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "dropdown": false, + "handwritten": false, + "parseContext": "castExpression", + "type": "socketStart" + }, + "temp", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "sort", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "comparator", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "control", + "nodeContext": { + "prefix": "for (", + "suffix": "}", + "type": "iterationStatement" + }, + "parseContext": "iterationStatement", + "shape": 1, + "type": "blockStart" + }, + "for (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "assignmentExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "head", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "; ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "; ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "assignmentExpression" + }, + "parseContext": "assignmentExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "unaryExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + " = ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "next", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "printf(", + "suffix": ")", + "type": "postfixExpression" + }, + "parseContext": "expressionStatement", + "shape": 1, + "type": "blockStart" + }, + "printf(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "argumentExpressionList", + "type": "socketStart" + }, + "\"%d \"", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + { + "color": "command", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "postfixExpression" + }, + "parseContext": "postfixExpression", + "shape": 1, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "postfixExpression", + "type": "socketStart" + }, + "cursor", + { + "type": "socketEnd" + }, + "->", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Identifier", + "type": "socketStart" + }, + "data", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "puts(", + "suffix": ");", + "type": "specialMethodCall" + }, + "parseContext": "specialMethodCall", + "shape": 0, + "type": "blockStart" + }, + "puts(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "\"\\n\"", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } +]; -window.FREEZE_DATA.commentConsolidation = "int main() {\n" + - "puts("Hello"); /* start\n" + - "middle\n" + - "end */ puts("Hi"); /* interrupt */ /* start\n" + - "end */ puts("Goodbye"); /* interrupt */ // end of line\n" + - "/* start again\n" + - "end again */ /* interrupt */ /* start\n" + - "end */\n" + - "/* interrupt */ // end of line\n" + - "return 0;\n" + - "}"; +window.FREEZE_DATA.commentConsolidation = [ + { + "indentContext": "translationUnit", + "type": "documentStart" + }, + { + "color": "control", + "nodeContext": { + "prefix": "int ", + "suffix": "}", + "type": "functionDefinition" + }, + "parseContext": "functionDefinition", + "shape": 1, + "type": "blockStart" + }, + "int ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "directDeclarator", + "type": "socketStart" + }, + "main", + { + "type": "socketEnd" + }, + "() {", + { + "indentContext": "blockItem", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "puts(", + "suffix": ");", + "type": "specialMethodCall" + }, + "parseContext": "specialMethodCall", + "shape": 0, + "type": "blockStart" + }, + "puts(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "\"Hello\"", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* start", + { + "specialIndent": undefined, + "type": "newline" + }, + "middle", + { + "specialIndent": undefined, + "type": "newline" + }, + "end */ ", + { + "type": "blockEnd" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "puts(", + "suffix": ");", + "type": "specialMethodCall" + }, + "parseContext": "specialMethodCall", + "shape": 0, + "type": "blockStart" + }, + "puts(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "\"Hi\"", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* interrupt */", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* start", + { + "specialIndent": undefined, + "type": "newline" + }, + "end */ ", + { + "type": "blockEnd" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "puts(", + "suffix": ");", + "type": "specialMethodCall" + }, + "parseContext": "specialMethodCall", + "shape": 0, + "type": "blockStart" + }, + "puts(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "assignmentExpression", + "type": "socketStart" + }, + "\"Goodbye\"", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* interrupt */", + { + "type": "blockEnd" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + " //", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " end of line", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + "/* start again", + { + "specialIndent": undefined, + "type": "newline" + }, + "end again */", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* interrupt */", + { + "type": "blockEnd" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + " /* start", + { + "specialIndent": undefined, + "type": "newline" + }, + "end */", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": 0, + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": 0, + "shape": "comment", + "type": "blockStart" + }, + "/* interrupt */", + { + "type": "blockEnd" + }, + { + "color": "comment", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "__comment__" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + " //", + { + "dropdown": false, + "handwritten": true, + "parseContext": "__comment__", + "type": "socketStart" + }, + " end of line", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "return", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "jumpStatement" + }, + "parseContext": "jumpStatement", + "shape": 0, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "expression", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } +] diff --git a/test/data/parserSuccess.js b/test/data/parserSuccess.js index fa705198..508fc4e3 100644 --- a/test/data/parserSuccess.js +++ b/test/data/parserSuccess.js @@ -1,102 +1 @@ -window.parserSuccessData = [ - { - "message": "Function call", - "str": "alert 10", - "expected": "alert 10<\/socket><\/block><\/document>" - }, - { - "message": "Variable assignment", - "str": "a = b", - "expected": "a<\/socket> = b<\/socket><\/block><\/document>" - }, - { - "message": "If statement, normal form", - "str": "if true\n alert 10", - "expected": "if true<\/socket>\nalert 10<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "Unless statement, normal form", - "str": "unless true\n alert 10", - "expected": "unless true<\/socket>\nalert 10<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "One-line if statement", - "str": "if a then b", - "expected": "if a<\/socket> then b<\/socket><\/block><\/document>" - }, - { - "message": "If-else statement, normal form", - "str": "if true\n alert 10\nelse\n alert 10", - "expected": "if true<\/socket>\nalert 10<\/socket><\/block><\/indent>\nelse\nalert 10<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "One-line if-else statement", - "str": "if a then b else c", - "expected": "if a<\/socket> then b<\/socket> else c<\/socket><\/block><\/document>" - }, - { - "message": "While statement, normal form", - "str": "while a\n alert 10", - "expected": "while a<\/socket>\nalert 10<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "One-line while statement", - "str": "while a then alert 10", - "expected": "while a<\/socket> then alert 10<\/socket><\/block><\/socket><\/block><\/document>" - }, - { - "message": "For-in, normal form", - "str": "for i in list\n alert 10", - "expected": "for i<\/socket> in list<\/socket>\nalert 10<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "One-line for-in", - "str": "for i in list then alert 10", - "expected": "for i<\/socket> in list<\/socket> then alert 10<\/socket><\/block><\/socket><\/block><\/document>" - }, - { - "message": "Inverted one-line for-in", - "str": "alert 10 for i in list", - "expected": "alert 10<\/socket><\/block><\/socket> for i<\/socket> in list<\/socket><\/block><\/document>" - }, - { - "message": "Semicolons at the root", - "str": "alert 10; prompt 10", - "expected": "alert 10<\/socket><\/block><\/socket>; prompt 10<\/socket><\/block><\/socket><\/block><\/document>" - }, - { - "message": "Semicolons with one-line block", - "str": "if a then b; c else d", - "expected": "if a<\/socket> then b<\/socket>; c<\/socket><\/block><\/socket> else d<\/socket><\/block><\/document>" - }, - { - "message": "Semicolons in sequence", - "str": "while a\n console.log hi\n alert 10; prompt 10\n console.log bye", - "expected": "while a<\/socket>\nconsole.log hi<\/socket><\/block>\nalert 10<\/socket><\/block><\/socket>; prompt 10<\/socket><\/block><\/socket><\/block>\nconsole.log bye<\/socket><\/block><\/indent><\/block><\/document>" - }, - { - "message": "Object literal, normal form", - "str": "foo {\n a: b,\n c: d\n}", - "expected": "foo<\/socket> {\n a<\/socket>: b<\/socket>,\n c<\/socket>: d<\/socket>\n}<\/block><\/socket><\/block><\/document>" - }, - { - "message": "Object literal, no braces or commas", - "str": "foo\n a: b\n c: d", - "expected": "foo<\/socket>\n a<\/socket>: b<\/socket>\n c<\/socket>: d<\/socket><\/block><\/socket><\/block><\/document>" - }, - { - "message": "String interpolation", - "str": "foo \"#{a}\"", - "expected": "foo<\/socket> "#{a}"<\/socket><\/block><\/document>" - }, - { - "message": "Range", - "str": "[1..10]", - "expected": "[1<\/socket>..10<\/socket>]<\/block><\/document>" - }, - { - "message": "Array", - "str": "[0, 1]", - "expected": "[0, <\/block>1<\/block><\/indent>]<\/block><\/document>" - } -] +window.parserSuccessData = [{"message":"Function call","str":"alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Variable assignment","str":"a = b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Assign","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," = ",{"type":"socketStart","parseContext":"FunctionBody","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"If statement, normal form","str":"if true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Unless statement, normal form","str":"unless true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"unless ","suffix":""}},"unless ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line if statement","str":"if a then b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"If-else statement, normal form","str":"if true\n alert 10\nelse\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"newline","specialIndent":undefined},"else",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line if-else statement","str":"if a then b else c","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"}," else ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"While statement, normal form","str":"while a\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line while statement","str":"while a then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"For-in, normal form","str":"for i in list\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line for-in","str":"for i in list then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Inverted one-line for-in","str":"alert 10 for i in list","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"","suffix":""}},{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons at the root","str":"alert 10; prompt 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons with one-line block","str":"if a then b; c else d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," else ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons in sequence","str":"while a\n console.log hi\n alert 10; prompt 10\n console.log bye","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"hi",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"bye",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Object literal, normal form","str":"foo {\n a: b,\n c: d\n}","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"{","suffix":"}"}},"{",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},",",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined},"}",{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Object literal, no braces or commas","str":"foo\n a: b\n c: d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"String interpolation","str":"foo \"#{a}\"","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"\"#{a}\"",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Range","str":"[1..10]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Range","prefix":"[","suffix":"]"}},"[",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"1",{"type":"socketEnd"},"..",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Array","str":"[0, 1]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Arr","prefix":"[","suffix":"]"}},"[",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"0, ","suffix":"0, "}},"0, ",{"type":"blockEnd"},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"1","suffix":"1"}},"1",{"type":"blockEnd"},{"type":"indentEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}];; diff --git a/test/src/cstest.coffee b/test/src/cstest.coffee index 9270f81e..f2d5926f 100644 --- a/test/src/cstest.coffee +++ b/test/src/cstest.coffee @@ -27,60 +27,169 @@ asyncTest 'Parser configurability', -> alert random 100 cosette 20 ''').serialize() - expectedSerialization = '''marius eponine 10\nalert random 100\ncosette 20''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "red", + "nodeContext": { + "prefix": "marius ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "marius ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "purplish", + "nodeContext": { + "prefix": "eponine ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 3, + "type": "blockStart" + }, + "eponine ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + "10", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "alert", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "random", + { + "type": "socketEnd" + }, + " ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + "100", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "cosette ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 0, + "type": "blockStart" + }, + "cosette ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + "20", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + customSerialization, + expectedSerialization, 'Custom known functions work') return start() @@ -109,69 +218,169 @@ asyncTest 'Dotted methods', -> }) customSerialization = customCoffee.parse( 'console.log Math.log log x.toString log.fd()\nfd()').serialize() - expectedSerialization = '''console.log Math.log log x.toString log.fd()\nfd()''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "console.log ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "console.log ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "Math.log ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 3, + "type": "blockStart" + }, + "Math.log ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "log ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 3, + "type": "blockStart" + }, + "log ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "PropertyAccess", + "type": "socketStart" + }, + "x", + { + "type": "socketEnd" + }, + ".toString ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ".fd()", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "PropertyAccess", + "type": "socketStart" + }, + "log", + { + "type": "socketEnd" + }, + ".fd()", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "fd()", + "suffix": "fd()", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "fd()", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Dotted known functions work') start() @@ -184,67 +393,166 @@ asyncTest 'Merged code blocks', -> console.log \'ouch\' ''' ).serialize() - expectedSerialization = '''x = (y) -> y * y\nalert 'clickme', ->\nconsole.log 'ouch' - ''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Assign" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Lvalue", + "type": "socketStart" + }, + "x", + { + "type": "socketEnd" + }, + " = (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "__comment__", + "type": "socketStart" + }, + "y", + { + "type": "socketEnd" + }, + ") -> ", + { + "dropdown": false, + "handwritten": false, + "parseContext": 0, + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator*" + }, + "parseContext": "__comment__", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator*", + "type": "socketStart" + }, + "y", + { + "type": "socketEnd" + }, + " * ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator*", + "type": "socketStart" + }, + "y", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "alert ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "alert ", + { + "dropdown": false, + "handwritten": false, + "parseContext": 0, + "type": "socketStart" + }, + "'clickme'", + { + "type": "socketEnd" + }, + ", ->", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "console.log ", + "suffix": "", + "type": "Call" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "console.log ", + { + "dropdown": false, + "handwritten": false, + "parseContext": -1, + "type": "socketStart" + }, + "'ouch'", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Merged code blocks work') return start() @@ -265,95 +573,205 @@ asyncTest 'Custom Colors', -> }) customSerialization = customCoffee.parse( 'return b != (a += [c + d][0])').serialize() - expectedSerialization = '''return b != (a += [c + d][0])''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "#222", + "nodeContext": { + "prefix": "return ", + "suffix": "", + "type": "Return" + }, + "parseContext": "__comment__", + "shape": 1, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator!==" + }, + "parseContext": "__comment__", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator!==", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + " != ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator!==", + "type": "socketStart" + }, + { + "color": "#777", + "nodeContext": { + "prefix": "(", + "suffix": ")", + "type": "Assign" + }, + "parseContext": "__comment__", + "shape": 2, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Lvalue", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " += ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "FunctionBody", + "type": "socketStart" + }, + { + "color": "#aaa", + "nodeContext": { + "prefix": "", + "suffix": "]", + "type": "PropertyAccess" + }, + "parseContext": "__comment__", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": 0, + "type": "socketStart" + }, + { + "color": "#666", + "nodeContext": { + "prefix": "[", + "suffix": "]", + "type": "Arr" + }, + "parseContext": "__comment__", + "shape": 4, + "type": "blockStart" + }, + "[", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "color": "#444", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator+" + }, + "parseContext": "__comment__", + "shape": 4, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator+", + "type": "socketStart" + }, + "c", + { + "type": "socketEnd" + }, + " + ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator+", + "type": "socketStart" + }, + "d", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + "]", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "[", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + "]", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + customSerialization, + expectedSerialization, 'Custom colors work') start() diff --git a/test/src/ctest.coffee b/test/src/ctest.coffee index 0fad1cc6..ac88ff22 100644 --- a/test/src/ctest.coffee +++ b/test/src/ctest.coffee @@ -161,7 +161,7 @@ asyncTest 'Parser: parser freeze test for C mode', -> } ''' - equal result.serialize(), FREEZE_DATA.freezeTest, 'Match C parser freeze file as of 2016-07-08' + deepEqual result.serialize(), FREEZE_DATA.freezeTest, 'Match C parser freeze file as of 2016-07-08' start() @@ -188,7 +188,7 @@ asyncTest 'Parser: parser freeze test comment consolidation', -> } ''' - equal result.serialize(), FREEZE_DATA.commentConsolidation, 'C comment consolidation' + deepEqual result.serialize(), FREEZE_DATA.commentConsolidation, 'C comment consolidation' start() @@ -291,6 +291,10 @@ asyncTest 'Controller: ANTLR reparse rules', -> palette: [] }) + # Note: this test very deliberately does not contain any unnecessary parentheses, + # because those get removed by high-level editor.reparse(). + # + # TODO: possibly add a second test testing that case. editor.setValue ''' #include #include @@ -333,12 +337,12 @@ asyncTest 'Controller: ANTLR reparse rules', -> // Comparator int comparator(long long a, long long b) { - return (a > b); + return a > b; } // Main int main(int n, char *args[]) { - // Arbitrary array initializer just o test that syntax + // Arbitrary array initializer just to test that syntax int arbitraryArray[] = {1, 2, 3, 4, 5}; int length; scanf("%d", &length); @@ -371,7 +375,7 @@ asyncTest 'Controller: ANTLR reparse rules', -> start() return - if head.type is 'blockStart' and head.container.stringify().length > 0 + if head.type is 'blockStart' and head.container.parseContext isnt '__comment__' and head.container.stringify().length > 0 before = head.prev oldLocalSerialize = head.container.serialize() @@ -381,8 +385,8 @@ asyncTest 'Controller: ANTLR reparse rules', -> newLocalSerialize = before.next.container.serialize() notEqual before.next.id, head.id, "Reparsing did indeed replace the block ('#{head.container.stringify()}', #{head.container.parseContext})." - equal oldLocalSerialize, newLocalSerialize, "Reparsing did not change the local structure ('#{head.container.stringify()}, #{head.container.parseContext}')." - equal oldSerialize, newSerialize, "Reparsing did not change the tree structure ('#{head.container.stringify()}, #{head.container.parseContext}')." + deepEqual oldLocalSerialize, newLocalSerialize, "Reparsing did not change the local structure ('#{head.container.stringify()}, #{head.container.parseContext}')." + deepEqual oldSerialize, newSerialize, "Reparsing did not change the tree structure ('#{head.container.stringify()}, #{head.container.parseContext}')." head = before.next diff --git a/test/src/htmltest.coffee b/test/src/htmltest.coffee index 7d5d5609..b4865582 100644 --- a/test/src/htmltest.coffee +++ b/test/src/htmltest.coffee @@ -15,60 +15,209 @@ asyncTest 'Basic Document parsing', -> ''').serialize() - expectedSerialization = '''&lt;!doctype html&gt; - &lt;html&gt; - &lt;head&gt; - &lt;title&gt;Hello&lt;/title&gt; - &lt;/head&gt; - &lt;body&gt; - Welcome to my page! - &lt;/body&gt; - &lt;/html&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "lightblue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "emptyTag" + }, + "parseContext": "emptyTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightblue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightblue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightblue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Hello", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "orange", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Welcome to my page!", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + customSerialization, + expectedSerialization, 'The parser is working in a basic sense') return start() @@ -82,33 +231,106 @@ asyncTest 'Removal of Empty nodes', ->

''').serialize() - expectedSerialization = '''&lt;html&gt; - &lt;p&gt; - Welcome to my world - &lt;/p&gt; - &lt;/html&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "lightblue", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "

", + "suffix": "

", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "

", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Welcome to my world", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "

", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'Artificial nodes are removed') return start() @@ -121,45 +343,149 @@ asyncTest 'Optional Closing tags', ->
  • Item2 ''').serialize() - expectedSerialization = '''&lt;ul&gt; - &lt;li&gt;Item1 - &lt;li&gt;Item2 - &lt;/ul&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "
      ", + "suffix": "
    ", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "
      ", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "
    • ", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "
    • ", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Item1", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "purple", + "nodeContext": { + "prefix": "
    • ", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "
    • ", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Item2", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "
    ", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Optional closing elements are closed properly') return start() @@ -171,21 +497,62 @@ asyncTest 'Attribute Sockets', -> ''').serialize() - expectedSerialization = '''&lt;body background="red"&gt; - - &lt;/body&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "orange", + "nodeContext": { + "prefix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": "", + "type": "newline" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Attributes are socketed') return start() @@ -197,21 +564,61 @@ asyncTest 'Scoket empty attribute values', -> ''').serialize() - expectedSerialization = '''&lt;body background = ""&gt; - - &lt;/body&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "orange", + "nodeContext": { + "prefix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": "", + "type": "newline" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + customSerialization, + expectedSerialization, 'Empty Attribute values are part of sockets') return start() @@ -226,21 +633,62 @@ asyncTest 'Check overrides', -> ''').serialize() - expectedSerialization = '''&lt;body background = ""&gt; - - &lt;/body&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + "", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": "", + "type": "newline" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Tag and category overrides work') return start() @@ -252,24 +700,74 @@ asyncTest 'Trailing Space', -> Hello ''').serialize() - expectedSerialization = '''&lt;body> - Hello - &lt;/body&gt;''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "orange", + "nodeContext": { + "prefix": " ", + "suffix": "", + "type": "blockTag" + }, + "parseContext": "blockTag", + "shape": 0, + "type": "blockStart" + }, + " ", + { + "indentContext": "blockTag", + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "lightgreen", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "text" + }, + "parseContext": "text", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "text", + "type": "socketStart" + }, + "Hello", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + customSerialization, + expectedSerialization, 'Trailing space is part of parent block') return start() diff --git a/test/src/jstest.coffee b/test/src/jstest.coffee index 38f8d4e6..be57302f 100644 --- a/test/src/jstest.coffee +++ b/test/src/jstest.coffee @@ -30,94 +30,242 @@ asyncTest 'JS dotted methods', -> ''' ).serialize() - expectedSerialization = '''x.pos(100);\nreturn console.log(Math.log(log(x.toString(~pos()))));''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "red", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 2, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "CalleeObject", + "type": "socketStart" + }, + "x", + { + "type": "socketEnd" + }, + ".pos(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "100", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "yellow", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "ReturnStatement" + }, + "parseContext": "program", + "shape": 2, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "console.log(", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 2, + "type": "blockStart" + }, + "console.log(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "Math.log(", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + "Math.log(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "log", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "CalleeObject", + "type": "socketStart" + }, + "x", + { + "type": "socketEnd" + }, + ".toString(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "~", + "suffix": "", + "type": "Operator~" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + "~", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "red", + "nodeContext": { + "prefix": "pos()", + "suffix": "pos()", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 2, + "type": "blockStart" + }, + "pos()", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'Dotted known functions work') start() @@ -138,89 +286,208 @@ asyncTest 'JS Custom Colors', -> }) customSerialization = customJS.parse( 'return b != (a += [c + d][0]);').serialize() - expectedSerialization = '''return b != (a += [c + d][0]);''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "#222", + "nodeContext": { + "prefix": "return ", + "suffix": ";", + "type": "ReturnStatement" + }, + "parseContext": "program", + "shape": 2, + "type": "blockStart" + }, + "return ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator!=" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator!=", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + " != ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator!=", + "type": "socketStart" + }, + { + "color": "#777", + "nodeContext": { + "prefix": "(", + "suffix": ")", + "type": "AssignmentExpression" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Lvalue", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " += ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "#666", + "nodeContext": { + "prefix": "", + "suffix": "]", + "type": "MemberExpression" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "#666", + "nodeContext": { + "prefix": "[", + "suffix": "]", + "type": "ArrayExpression" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + "[", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "#444", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator+" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator+", + "type": "socketStart" + }, + "c", + { + "type": "socketEnd" + }, + " + ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator+", + "type": "socketStart" + }, + "d", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "]", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + "[", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + "]", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ";", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'JS Custom colors work') start() @@ -229,31 +496,61 @@ asyncTest 'JS empty indents', -> code = 'if (__) {\n\n}' customSerialization = customJS.parse('if (__) {\n\n}') stringifiedJS = customSerialization.stringify() - strictEqual(stringifiedJS, code) + deepEqual(stringifiedJS, code) start() asyncTest 'JS LogicalExpressions', -> customJS = new JavaScript() customSerialization = customJS.parse( 'a && b').serialize() - expectedSerialization = '''a && b''' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator&&" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator&&", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " && ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator&&", + "type": "socketStart" + }, + "b", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + + deepEqual( + (customSerialization), + (expectedSerialization), 'Logical expression precedences are assigned.') start() @@ -261,59 +558,134 @@ asyncTest 'JS omits unary +/- for literals', -> customJS = new JavaScript() customSerialization = customJS.parse( 'foo(+1, -1, +a());').serialize() - expectedSerialization = - 'foo(' + - '+1, ' + - '-1, ' + - '+a()' + - ');' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "foo", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "+1", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "-1", + { + "type": "socketEnd" + }, + ", ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "+", + "suffix": "", + "type": "Operator+" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + "+", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": null, + "type": "socketStart" + }, + { + "type": "socketEnd" + }, + ")", + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'Unary literal +/- are not parsed, but unary nonliteral operators are') start() @@ -329,129 +701,327 @@ asyncTest 'JS Elif', -> ' fd(200);\n' + '}' ).serialize() - expectedSerialization = - 'if (' + - 'a == ' + - '0) {' + - '\nfd(0);' + - '\n} else if (' + - 'a == ' + - '1) {' + - '\nfd(' + - '100);' + - '\n} else if (' + - 'a == ' + - '2) {' + - '\nfd(' + - '200);\n' + - '}' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "orange", + "nodeContext": { + "prefix": "if (", + "suffix": "}", + "type": "IfStatement" + }, + "parseContext": "program", + "shape": 1, + "type": "blockStart" + }, + "if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator==" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " == ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "fd", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "0", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "} else if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator==" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " == ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "1", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "fd", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "100", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "} else if (", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + { + "color": "cyan", + "nodeContext": { + "prefix": "", + "suffix": "", + "type": "Operator==" + }, + "parseContext": "program", + "shape": 3, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "a", + { + "type": "socketEnd" + }, + " == ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Operator==", + "type": "socketStart" + }, + "2", + { + "type": "socketEnd" + }, + { + "type": "blockEnd" + }, + { + "type": "socketEnd" + }, + ") {", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "fd", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": "Expression", + "type": "socketStart" + }, + "200", + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'Combines if-else') start() @@ -466,36 +1036,95 @@ asyncTest 'JS beginner mode loops', -> } ''' ).serialize() - expectedSerialization = - 'for (var i = 0; i &lt; 10; i++) {\ngo();\n}' - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), + expectedSerialization = [ + { + "indentContext": undefined, + "type": "documentStart" + }, + { + "color": "green", + "nodeContext": { + "prefix": "for (var i = 0; i < ", + "suffix": "}", + "type": "ForStatement" + }, + "parseContext": "program", + "shape": 1, + "type": "blockStart" + }, + "for (var i = 0; i < ", + { + "dropdown": false, + "handwritten": false, + "parseContext": "program", + "type": "socketStart" + }, + "10", + { + "type": "socketEnd" + }, + "; i++) {", + { + "indentContext": null, + "prefix": " ", + "type": "indentStart" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + { + "color": "blue", + "nodeContext": { + "prefix": "", + "suffix": ")", + "type": "CallExpression" + }, + "parseContext": "program", + "shape": 0, + "type": "blockStart" + }, + { + "dropdown": false, + "handwritten": false, + "parseContext": "Callee", + "type": "socketStart" + }, + "go", + { + "type": "socketEnd" + }, + "(", + { + "dropdown": false, + "handwritten": false, + "parseContext": null, + "type": "socketStart" + }, + { + "type": "socketEnd" + }, + ");", + { + "type": "blockEnd" + }, + { + "type": "indentEnd" + }, + { + "specialIndent": undefined, + "type": "newline" + }, + "}", + { + "type": "blockEnd" + }, + { + "type": "documentEnd" + } + ] + deepEqual( + (customSerialization), + (expectedSerialization), 'Combines if-else') start() diff --git a/test/src/tests.coffee b/test/src/tests.coffee index 7bcc311c..670be146 100644 --- a/test/src/tests.coffee +++ b/test/src/tests.coffee @@ -17,28 +17,18 @@ c = new C() asyncTest 'Parser success', -> window.dumpObj = [] for testCase in parserSuccessData - strictEqual( - helper.xmlPrettyPrint(coffee.parse(testCase.str, wrapAtRoot: true).serialize()), - helper.xmlPrettyPrint(testCase.expected), + deepEqual( + coffee.parse(testCase.str, wrapAtRoot: true).serialize(), + testCase.expected, testCase.message ) window.dumpObj.push { message: testCase.message str: testCase.str - expected: helper.xmlPrettyPrint coffee.parse(testCase.str, wrapAtRoot: true).serialize() + expected: coffee.parse(testCase.str, wrapAtRoot: true).serialize() } start() -asyncTest 'XML parser unity', -> - for testCase in parserSuccessData - xml = coffee.parse(testCase.str, wrapAtRoot: true).serialize() - strictEqual( - helper.xmlPrettyPrint(parser.parseXML(xml).serialize()), - helper.xmlPrettyPrint(xml), - 'Parser unity for: ' + testCase.message - ) - start() - asyncTest 'View: compute children', -> view_ = new view.View() diff --git a/test/src/uitest.coffee b/test/src/uitest.coffee index 70066f0f..7d45d4a8 100644 --- a/test/src/uitest.coffee +++ b/test/src/uitest.coffee @@ -267,11 +267,11 @@ asyncTest 'Controller: does not throw on reparse error', -> editor.setEditorState(true) editor.setValue('var hello = function (a) {};') - simulate('mousedown', '.droplet-main-canvas', {dx: 220, dy: 30}) - simulate('mouseup', '.droplet-main-canvas', {dx: 220, dy: 30}) + simulate('mousedown', '.droplet-main-canvas', {dx: 15, dy: 15}) + simulate('mouseup', '.droplet-main-canvas', {dx: 15, dy: 15}) ok(editor.getCursor(), 'Has text focus') - equal(editor.getCursor().stringify(), 'a') + equal(editor.getCursor().stringify(), 'hello') $('.droplet-hidden-input').sendkeys('18n') From 73a376a4947fc880433dd9991e4d96a834e3b7ae Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 12:57:51 -0400 Subject: [PATCH 40/60] Clean up reparsing --- src/controller.coffee | 70 +++++++++++++++++++++++++++++++++--------- src/languages/c.coffee | 4 +++ src/model.coffee | 1 + src/parser.coffee | 1 + src/treewalk.coffee | 30 ++++++++++++++++-- src/view.coffee | 5 +-- 6 files changed, 93 insertions(+), 18 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index c1dd6801..c9bbe883 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1826,8 +1826,10 @@ hook 'mouseup', 1, (point, event, state) -> # # TODO "reparseable" property (or absent contexts), bubble up # TODO performance on large programs - if @lastHighlight.type is 'socket' - @reparse @draggingBlock.parent.parent + # + # TODO Consider whether to add this back? + #if @lastHighlight.type is 'socket' + # @reparse @draggingBlock.parent.parent # Now that we've done that, we can annul stuff. @endDrag() @@ -2014,6 +2016,26 @@ parseBlock = (mode, code, context = null) => block.setParent null return block +parseSocketBlock = (mode, code, context) => + contextCandidates = [context] + + if mode.getParenCandidates? + contextCandidates = contextCandidates.concat mode.getParenCandidates context + + for candidate in contextCandidates + try + block = mode.parse(code, {context: candidate, wrapAtRoot: false}).start.next.container + + if block? and block.type is 'block' + block.start.prev = block.end.next = null + block.setParent null + + return block + + else + return null + return null + Editor::setPalette = (paletteGroups) -> @paletteHeader.innerHTML = '' @session.paletteGroups = paletteGroups @@ -2386,6 +2408,29 @@ hook 'mousedown', 7, -> @hideDropdown() +Editor::reparseSocket = (socket, updates = []) -> + if socket.handwritten + return @reparse socket.parent, updates + + text = socket.textContent() + + # If our language mode has a string-fixing feature (in most languages, + # this will simply autoescape quoted "strings"), apply it + if @session.mode.stringFixer? + @populateSocket socket, @session.mode.stringFixer(text) + text = socket.textContent() + + block = parseSocketBlock(@session.mode, text, socket.parseContext) + if block? + @prepareNode block, socket + + replaceList = new model.List socket.start.next, socket.end.prev + + @replace replaceList, block, updates + + else + @reparse socket, updates + # If we can, try to reparse the focus # value. # @@ -2411,7 +2456,7 @@ hook 'mousedown', 7, -> # -> Fall back to raw reparsing the parent with unparenthesized text # -> Reparses function(a, b) {} with two paremeters. # -> Finsihed. -Editor::reparse = (list, recovery, updates = [], originalTrigger = list) -> +Editor::reparse = (list, updates = [], originalTrigger = list) -> # Don't reparse sockets. When we reparse sockets, # reparse them first, then try reparsing their parent and # make sure everything checks out. @@ -2429,12 +2474,12 @@ Editor::reparse = (list, recovery, updates = [], originalTrigger = list) -> # Try reparsing the parent after beforetextfocus. If it fails, # repopulate with the original text and try again. - unless @reparse list.parent, recovery, updates, originalTrigger + unless @reparse list.parent, updates, originalTrigger @populateSocket list, originalText originalUpdates.forEach (location, i) -> updates[i].count = location.count updates[i].type = location.type - @reparse list.parent, recovery, updates, originalTrigger + @reparse list.parent, updates, originalTrigger return parent = list.start.parent @@ -2463,7 +2508,7 @@ Editor::reparse = (list, recovery, updates = [], originalTrigger = list) -> # Attempt to bubble up to the parent if parent? - return @reparse parent, recovery, updates, originalTrigger + return @reparse parent, updates, originalTrigger else @session.view.getViewNodeFor(originalTrigger).mark {color: '#F00'} return false @@ -2473,10 +2518,6 @@ Editor::reparse = (list, recovery, updates = [], originalTrigger = list) -> # Exclude the document start and end tags newList = new model.List newList.start.next, newList.end.prev - # Prepare the new node for insertion - newList.traverseOneLevel (head) => - @prepareNode head, parent - @replace list, newList, updates @redrawMain() @@ -2515,7 +2556,7 @@ Editor::populateSocket = (socket, string) -> last = helper.connect last, new model.NewlineToken() last = helper.connect last, new model.TextToken line - @spliceIn (new model.List(first, last)), socket.start + @spliceIn new model.List(first, last), socket.start Editor::populateBlock = (block, string) -> newBlock = @session.mode.parse(string, wrapAtRoot: false).start.next.container @@ -3032,7 +3073,7 @@ Editor::setCursor = (destination, validate = (-> true), direction = 'after') -> if @cursorAtSocket() and not @session.cursor.is(destination) socket = @getCursor() if '__comment__' isnt socket.parseContext - @reparse socket, null, (if destination.document is @session.cursor.document then [destination.location] else []) + @reparseSocket socket, (if destination.document is @session.cursor.document then [destination.location] else []) # TODO proper socket insertion @hiddenInput.blur() @dropletElement.focus() @@ -3210,7 +3251,7 @@ hook 'keydown', 0, (event, state) -> if event.which is ENTER_KEY if not @cursorAtSocket() and not event.shiftKey and not event.ctrlKey and not event.metaKey # Construct the block; flag the socket as handwritten - newBlock = new model.Block(); newSocket = new model.Socket '', Infinity, true + newBlock = new model.Block(); newSocket = new model.Socket '', true newSocket.setParent newBlock helper.connect newBlock.start, newSocket.start helper.connect newSocket.end, newBlock.end @@ -3242,7 +3283,7 @@ hook 'keydown', 0, (event, state) -> newBlock.socketLevel = helper.BLOCK_ONLY newTextMarker = new model.TextToken @session.mode.startSingleLineComment newTextMarker.setParent newBlock - newSocket = new model.Socket '', 0, true + newSocket = new model.Socket '', true newSocket.parseContext = '__comment__' newSocket.setParent newBlock @@ -4222,6 +4263,7 @@ Editor::endDrag = -> @clearDrag() @draggingBlock = null @draggingOffset = null + @dragReplacing = false @lastHighlightPath?.deactivate?() @lastHighlight = @lastHighlightPath = null diff --git a/src/languages/c.coffee b/src/languages/c.coffee index ce322ed3..9d3d2354 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -295,6 +295,10 @@ config.stringFixer = (string) -> return string config.empty = '__0_droplet__' +config.EMPTY_STRINGS = { + 'Identifier': '__0_droplet__', + 'declaration': '__0_droplet__ __0_droplet__;' +} config.emptyIndent = '' config.rootContext = 'translationUnit' diff --git a/src/model.coffee b/src/model.coffee index 78244799..b59ef918 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -1098,6 +1098,7 @@ exports.Socket = class Socket extends Container _serialize_header: -> { type: 'socketStart' + emptyString: @emptyString parseContext: @parseContext handwritten: @handwritten dropdown: @dropdown? diff --git a/src/parser.coffee b/src/parser.coffee index 46947f6e..fb49cd02 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -636,6 +636,7 @@ exports.wrapParser = (CustomParser) -> @rootContext = CustomParser.rootContext @startSingleLineComment = CustomParser.startSingleLineComment @getDefaultSelectionRange = CustomParser.getDefaultSelectionRange ? getDefaultSelectionRange + @getParenCandidates = CustomParser.getParenCandidates # TODO kind of hacky assignation of @empty, # maybe change the api? diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 6c6cdff5..a89b0980 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -96,6 +96,21 @@ exports.createTreewalkParser = (parse, config, root) -> if node.children.length is 1 and @detNode(node) isnt 'indent' @mark node.children[0], prefix, depth, true, rules, context, wrap + # Check to see if this AST type is part of the special empty strings map. + # If so, check to see if it is the special empty string for its type, + # and null it out if it is. + # + # TODO this may be a place where we need to optimize performance. + else if context? and @detNode(context) is 'block' and config.EMPTY_STRINGS? and + node.type of config.EMPTY_STRINGS and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.EMPTY_STRINGS[node.type] + @addSocket + empty: config.EMPTY_STRINGS[node.type] + bounds: node.bounds + depth: depth + parseContext: rules[0] + + @flagToRemove node.bounds, depth + 1 + else if node.children.length > 0 switch @detNode node when 'block' @@ -106,6 +121,7 @@ exports.createTreewalkParser = (parse, config, root) -> if context? and @detNode(context) is 'block' @addSocket + empty: config.EMPTY_STRINGS?[rules[0]] ? config.empty bounds: bounds depth: depth parseContext: rules[0] @@ -201,15 +217,16 @@ exports.createTreewalkParser = (parse, config, root) -> for child in node.children @mark child, prefix, depth + 2, false + else if context? and @detNode(context) is 'block' if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) @addSocket + empty: config.EMPTY_STRINGS?[node.type] ? config.empty bounds: node.bounds depth: depth parseContext: rules[0] - if config.EMPTY_STRINGS? and not @opts.preserveEmpty and - helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.EMPTY_STRINGSconfig.empty + if config.EMPTY_STRINGS? and not @opts.preserveEmpty and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.empty @flagToRemove node.bounds, depth + 1 if config.droppabilityGraph? @@ -265,10 +282,19 @@ exports.createTreewalkParser = (parse, config, root) -> return node.parseContext + TreewalkParser.getParenCandidates = (context) -> + result = [] + for dest, sources of config.PAREN_RULES + if helper.dfs(parenGraph, context, dest) + for source of sources when source not in result + result.push source + return result + else if config.drop? TreewalkParser.drop = config.drop TreewalkParser.parens = config.parens ? -> + TreewalkParser.stringFixer = config.stringFixer TreewalkParser.rootContext = config.rootContext TreewalkParser.getDefaultSelectionRange = config.getDefaultSelectionRange diff --git a/src/view.coffee b/src/view.coffee index 9c8bc3c1..3f7be516 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -2120,8 +2120,10 @@ exports.View = class View not @changedBoundingBox return @path + @path.style.fillColor = '#FFF' + if @model.start.next.type is 'blockStart' - @path.style.fill = 'none' + @path.style.fillColor = 'none' # Otherwise, call super. else @@ -2134,7 +2136,6 @@ exports.View = class View @path.style.fillColor = 'none' else @path.style.cssClass = 'droplet-socket-path' - @path.style.fillColor = '#FFF' return @path From ef83eabb8a2b4e3def354867c1e3b7bba5e16a45 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 13:07:28 -0400 Subject: [PATCH 41/60] Clean up error handling --- src/controller.coffee | 16 ++++++++++++++-- src/draw.coffee | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index c9bbe883..8d14701d 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -2421,6 +2421,7 @@ Editor::reparseSocket = (socket, updates = []) -> text = socket.textContent() block = parseSocketBlock(@session.mode, text, socket.parseContext) + if block? @prepareNode block, socket @@ -2429,7 +2430,18 @@ Editor::reparseSocket = (socket, updates = []) -> @replace replaceList, block, updates else - @reparse socket, updates + # First see if the string just checks out normally + # but doesn't have a block + # + # TODO if performance becomes an issue, reuse parse from + # parseSocketBlock + try + # If it checks out, we're done + @session.mode.parse text, {wrapAtRoot: false, context: socket.parseContext} + @session.view.getViewNodeFor(socket).unmark() # If it was error-marked, note that it is no longer so. + catch e + # Otherwise, try reparsing the parent. + @reparse socket, updates # If we can, try to reparse the focus # value. @@ -2490,7 +2502,7 @@ Editor::reparse = (list, updates = [], originalTrigger = list) -> context = (list.start.container ? list.start.parent).parseContext try - newList = @session.mode.parse list.stringifyInPlace(),{ + newList = @session.mode.parse list.stringifyInPlace(), { wrapAtRoot: parent.type isnt 'socket' context: context } diff --git a/src/draw.coffee b/src/draw.coffee index 13cd0da6..979d16b3 100644 --- a/src/draw.coffee +++ b/src/draw.coffee @@ -562,7 +562,7 @@ exports.Draw = class Draw @darkPathElement.setAttribute 'visibility', 'visible' else @element.setAttribute 'stroke', @style.strokeColor - @backgroundPathElement.setAttribute 'line-width', @style.lineWidth + @element.setAttribute 'line-width', @style.lineWidth if @_updateFlag @_updateFlag = false From 68e639ef4a5513ec2e44a8e5115772ee351ed48a Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 13:55:29 -0400 Subject: [PATCH 42/60] Fix all the tests for the new serialization method --- test/data/c-freeze-populator.js | 711 +++++++++++++++++++++----------- test/data/parserSuccess.js | 24 +- test/src/cstest.coffee | 87 ++-- test/src/ctest.coffee | 6 +- test/src/htmltest.coffee | 27 +- test/src/jstest.coffee | 141 ++++--- 6 files changed, 668 insertions(+), 328 deletions(-) diff --git a/test/data/c-freeze-populator.js b/test/data/c-freeze-populator.js index e1262b0d..76d55eaf 100644 --- a/test/data/c-freeze-populator.js +++ b/test/data/c-freeze-populator.js @@ -21,7 +21,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "stdio.h", { @@ -51,7 +52,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "stdlib.h", { @@ -81,7 +83,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "MAXLEN", { @@ -92,7 +95,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "100", { @@ -139,7 +143,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Linked list", { @@ -168,7 +173,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -200,7 +206,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -218,7 +225,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -254,7 +262,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -265,7 +274,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -295,7 +305,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -306,7 +317,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "prev", { @@ -347,7 +359,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -358,7 +371,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -406,7 +420,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Memoryless swap", { @@ -435,7 +450,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "swap", { @@ -446,7 +462,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -464,7 +481,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -481,7 +499,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -499,7 +518,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -536,7 +556,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -554,7 +575,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -571,7 +593,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -589,7 +612,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -624,7 +648,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -642,7 +667,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -659,7 +685,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -677,7 +704,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -712,7 +740,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -730,7 +759,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -747,7 +777,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -765,7 +796,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -830,7 +862,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Test if sorted", { @@ -859,7 +892,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "sorted", { @@ -870,7 +904,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -887,7 +922,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -898,7 +934,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -915,7 +952,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -933,7 +971,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "fn", { @@ -944,7 +983,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "comment", @@ -969,7 +1009,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "comment", @@ -1022,7 +1063,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__ __0_droplet__;" }, { "color": "control", @@ -1039,7 +1081,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -1050,7 +1093,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1068,7 +1112,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1079,7 +1124,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -1103,7 +1149,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -1120,7 +1167,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "logicalAndExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1131,7 +1179,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "inclusiveOrExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1148,7 +1197,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1159,7 +1209,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -1182,7 +1233,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1199,7 +1251,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1210,7 +1263,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1227,7 +1281,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1238,7 +1293,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -1282,7 +1338,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -1300,7 +1357,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1317,7 +1375,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "fn", { @@ -1328,7 +1387,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1345,7 +1405,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1356,7 +1417,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -1373,7 +1435,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1390,7 +1453,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1407,7 +1471,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1418,7 +1483,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -1435,7 +1501,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -1486,7 +1553,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "0", { @@ -1538,7 +1606,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "1", { @@ -1597,7 +1666,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Bubble sort", { @@ -1626,7 +1696,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "sort", { @@ -1637,7 +1708,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1654,7 +1726,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -1665,7 +1738,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -1682,7 +1756,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1700,7 +1775,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "fn", { @@ -1711,7 +1787,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "comment", @@ -1736,7 +1813,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "comment", @@ -1789,7 +1867,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -1807,7 +1886,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1824,7 +1904,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "sorted", { @@ -1835,7 +1916,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -1846,7 +1928,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "fn", { @@ -1891,7 +1974,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__ __0_droplet__;" }, { "color": "control", @@ -1908,7 +1992,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -1919,7 +2004,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -1937,7 +2023,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -1948,7 +2035,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -1972,7 +2060,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -1989,7 +2078,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "logicalAndExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2000,7 +2090,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "inclusiveOrExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2017,7 +2108,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2028,7 +2120,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -2051,7 +2144,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2068,7 +2162,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2079,7 +2174,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2096,7 +2192,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2107,7 +2204,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -2151,7 +2249,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -2169,7 +2268,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2186,7 +2286,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "fn", { @@ -2197,7 +2298,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2214,7 +2316,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2225,7 +2328,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -2242,7 +2346,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2259,7 +2364,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2276,7 +2382,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2287,7 +2394,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -2304,7 +2412,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -2339,7 +2448,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "statement", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2356,7 +2466,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "swap", { @@ -2367,7 +2478,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -2385,7 +2497,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2402,7 +2515,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2413,7 +2527,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -2436,7 +2551,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -2454,7 +2570,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2471,7 +2588,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2488,7 +2606,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -2499,7 +2618,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -2516,7 +2636,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -2615,7 +2736,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Comparator", { @@ -2644,7 +2766,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "comparator", { @@ -2655,7 +2778,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2673,7 +2797,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -2690,7 +2815,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2708,7 +2834,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -2746,7 +2873,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -2764,7 +2892,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "a", { @@ -2775,7 +2904,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "b", { @@ -2841,7 +2971,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Main", { @@ -2870,7 +3001,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "main", { @@ -2881,7 +3013,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2899,7 +3032,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "n", { @@ -2916,7 +3050,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -2934,7 +3069,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "args", { @@ -2973,7 +3109,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " Arbitrary array initializer just o test that syntax", { @@ -3002,7 +3139,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3019,7 +3157,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "arbitraryArray", { @@ -3030,7 +3169,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3048,7 +3188,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializerList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "1", { @@ -3059,7 +3200,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "2", { @@ -3070,7 +3212,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "3", { @@ -3081,7 +3224,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "4", { @@ -3092,7 +3236,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "5", { @@ -3135,7 +3280,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "length", { @@ -3165,7 +3311,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"%d\"", { @@ -3176,7 +3323,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3194,7 +3342,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "length", { @@ -3230,7 +3379,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3247,7 +3397,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "length", { @@ -3258,7 +3409,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "MAXLEN", { @@ -3296,7 +3448,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"Error: list is too large\"", { @@ -3326,7 +3479,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "1", { @@ -3366,7 +3520,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -3377,7 +3532,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3395,7 +3551,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -3406,7 +3563,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3424,7 +3582,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "typeName", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3441,7 +3600,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -3459,7 +3619,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3476,7 +3637,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "malloc", { @@ -3487,7 +3649,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3505,7 +3668,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "typeName", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -3561,7 +3725,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"%d\"", { @@ -3572,7 +3737,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3590,7 +3756,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3607,7 +3774,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -3618,7 +3786,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -3659,7 +3828,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3676,7 +3846,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -3687,7 +3858,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "prev", { @@ -3704,7 +3876,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "NULL", { @@ -3733,7 +3906,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -3744,7 +3918,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3762,7 +3937,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -3773,7 +3949,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -3809,7 +3986,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "temp", { @@ -3839,7 +4017,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declaration", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__ __0_droplet__;" }, { "color": "control", @@ -3857,7 +4036,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initDeclaratorList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -3874,7 +4054,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "declarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "i", { @@ -3885,7 +4066,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "initializer", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "0", { @@ -3909,7 +4091,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3926,7 +4109,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "i", { @@ -3937,7 +4121,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -3954,7 +4139,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "additiveExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "length", { @@ -3965,7 +4151,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "multiplicativeExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "1", { @@ -3988,7 +4175,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4005,7 +4193,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "i", { @@ -4043,7 +4232,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4060,7 +4250,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4071,7 +4262,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -4088,7 +4280,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -4106,7 +4299,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "typeName", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -4123,7 +4317,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -4141,7 +4336,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4158,7 +4354,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "malloc", { @@ -4169,7 +4366,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -4187,7 +4385,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "typeName", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "List", { @@ -4236,7 +4435,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4247,7 +4447,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4264,7 +4465,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4275,7 +4477,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -4311,7 +4514,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"%d\"", { @@ -4322,7 +4526,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -4340,7 +4545,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "temp", { @@ -4375,7 +4581,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4392,7 +4599,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4403,7 +4611,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -4420,7 +4629,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "value", @@ -4438,7 +4648,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "typeName", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4463,7 +4674,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "castExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "temp", { @@ -4509,7 +4721,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "sort", { @@ -4520,7 +4733,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -4531,7 +4745,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "comparator", { @@ -4561,7 +4776,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4578,7 +4794,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4589,7 +4806,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "head", { @@ -4606,7 +4824,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4617,7 +4836,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4634,7 +4854,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4645,7 +4866,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4662,7 +4884,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4673,7 +4896,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "next", { @@ -4717,7 +4941,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"%d \"", { @@ -4728,7 +4953,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, { "color": "command", @@ -4745,7 +4971,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "cursor", { @@ -4756,7 +4983,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "Identifier", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "data", { @@ -4803,7 +5031,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"\\n\"", { @@ -4833,7 +5062,8 @@ window.FREEZE_DATA.freezeTest = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "0", { @@ -4880,7 +5110,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "main", { @@ -4912,7 +5143,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"Hello\"", { @@ -4963,7 +5195,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"Hi\"", { @@ -5024,7 +5257,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "\"Goodbye\"", { @@ -5065,7 +5299,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " end of line", { @@ -5168,7 +5403,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": true, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, " end of line", { @@ -5197,7 +5433,8 @@ window.FREEZE_DATA.commentConsolidation = [ "dropdown": false, "handwritten": false, "parseContext": "expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__0_droplet__" }, "0", { diff --git a/test/data/parserSuccess.js b/test/data/parserSuccess.js index 508fc4e3..04009927 100644 --- a/test/data/parserSuccess.js +++ b/test/data/parserSuccess.js @@ -1 +1,23 @@ -window.parserSuccessData = [{"message":"Function call","str":"alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Variable assignment","str":"a = b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Assign","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," = ",{"type":"socketStart","parseContext":"FunctionBody","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"If statement, normal form","str":"if true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Unless statement, normal form","str":"unless true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"unless ","suffix":""}},"unless ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line if statement","str":"if a then b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"If-else statement, normal form","str":"if true\n alert 10\nelse\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"newline","specialIndent":undefined},"else",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line if-else statement","str":"if a then b else c","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"}," else ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"While statement, normal form","str":"while a\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line while statement","str":"while a then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"For-in, normal form","str":"for i in list\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"One-line for-in","str":"for i in list then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Inverted one-line for-in","str":"alert 10 for i in list","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"","suffix":""}},{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," for ",{"type":"socketStart","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons at the root","str":"alert 10; prompt 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons with one-line block","str":"if a then b; c else d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," else ",{"type":"socketStart","parseContext":0,"handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Semicolons in sequence","str":"while a\n console.log hi\n alert 10; prompt 10\n console.log bye","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"hi",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"bye",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Object literal, normal form","str":"foo {\n a: b,\n c: d\n}","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"{","suffix":"}"}},"{",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},",",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined},"}",{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Object literal, no braces or commas","str":"foo\n a: b\n c: d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"String interpolation","str":"foo \"#{a}\"","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","parseContext":-1,"handwritten":false,"dropdown":false},"\"#{a}\"",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Range","str":"[1..10]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Range","prefix":"[","suffix":"]"}},"[",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"1",{"type":"socketEnd"},"..",{"type":"socketStart","parseContext":"Expression","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]},{"message":"Array","str":"[0, 1]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Arr","prefix":"[","suffix":"]"}},"[",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"0, ","suffix":"0, "}},"0, ",{"type":"blockEnd"},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"1","suffix":"1"}},"1",{"type":"blockEnd"},{"type":"indentEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}];; +window.parserSuccessData = [ +{"message":"Function call","str":"alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Variable assignment","str":"a = b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Assign","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," = ",{"type":"socketStart","emptyString":"``","parseContext":"FunctionBody","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"If statement, normal form","str":"if true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Unless statement, normal form","str":"unless true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"unless ","suffix":""}},"unless ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"One-line if statement","str":"if a then b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"If-else statement, normal form","str":"if true\n alert 10\nelse\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"newline","specialIndent":undefined},"else",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"One-line if-else statement","str":"if a then b else c","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"While statement, normal form","str":"while a\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"One-line while statement","str":"while a then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"For-in, normal form","str":"for i in list\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"One-line for-in","str":"for i in list then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Inverted one-line for-in","str":"alert 10 for i in list","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Semicolons at the root","str":"alert 10; prompt 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Semicolons with one-line block","str":"if a then b; c else d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Semicolons in sequence","str":"while a\n console.log hi\n alert 10; prompt 10\n console.log bye","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"hi",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"bye",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Object literal, normal form","str":"foo {\n a: b,\n c: d\n}","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"{","suffix":"}"}},"{",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},",",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined},"}",{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Object literal, no braces or commas","str":"foo\n a: b\n c: d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"String interpolation","str":"foo \"#{a}\"","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"\"#{a}\"",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Range","str":"[1..10]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Range","prefix":"[","suffix":"]"}},"[",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"1",{"type":"socketEnd"},"..",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}, +{"message":"Array","str":"[0, 1]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Arr","prefix":"[","suffix":"]"}},"[",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"0, ","suffix":"0, "}},"0, ",{"type":"blockEnd"},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"1","suffix":"1"}},"1",{"type":"blockEnd"},{"type":"indentEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}] + + diff --git a/test/src/cstest.coffee b/test/src/cstest.coffee index f2d5926f..3123a683 100644 --- a/test/src/cstest.coffee +++ b/test/src/cstest.coffee @@ -48,7 +48,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "purplish", @@ -66,7 +67,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "10", { @@ -100,7 +102,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "alert", { @@ -111,7 +114,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "blue", @@ -128,7 +132,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "random", { @@ -139,7 +144,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "100", { @@ -174,7 +180,8 @@ asyncTest 'Parser configurability', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "20", { @@ -239,7 +246,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "green", @@ -257,7 +265,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "green", @@ -275,7 +284,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "green", @@ -292,7 +302,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "PropertyAccess", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "x", { @@ -303,7 +314,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "blue", @@ -320,7 +332,8 @@ asyncTest 'Dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "PropertyAccess", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "log", { @@ -413,7 +426,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": "Lvalue", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "x", { @@ -424,7 +438,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": "__comment__", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "y", { @@ -435,7 +450,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": 0, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "green", @@ -452,7 +468,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": "Operator*", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "y", { @@ -463,7 +480,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": "Operator*", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "y", { @@ -498,7 +516,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": 0, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "'clickme'", { @@ -530,7 +549,8 @@ asyncTest 'Merged code blocks', -> "dropdown": false, "handwritten": false, "parseContext": -1, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "'ouch'", { @@ -594,7 +614,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "cyan", @@ -611,7 +632,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator!==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "b", { @@ -622,7 +644,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator!==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "#777", @@ -640,7 +663,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Lvalue", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "a", { @@ -651,7 +675,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "FunctionBody", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "#aaa", @@ -668,7 +693,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": 0, - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, { "color": "#666", @@ -702,7 +728,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator+", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "c", { @@ -713,7 +740,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator+", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "d", { @@ -737,7 +765,8 @@ asyncTest 'Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "``" }, "0", { diff --git a/test/src/ctest.coffee b/test/src/ctest.coffee index ac88ff22..dc2fa8c4 100644 --- a/test/src/ctest.coffee +++ b/test/src/ctest.coffee @@ -291,10 +291,6 @@ asyncTest 'Controller: ANTLR reparse rules', -> palette: [] }) - # Note: this test very deliberately does not contain any unnecessary parentheses, - # because those get removed by high-level editor.reparse(). - # - # TODO: possibly add a second test testing that case. editor.setValue ''' #include #include @@ -337,7 +333,7 @@ asyncTest 'Controller: ANTLR reparse rules', -> // Comparator int comparator(long long a, long long b) { - return a > b; + return (a > b); } // Main diff --git a/test/src/htmltest.coffee b/test/src/htmltest.coffee index b4865582..ed1ea50b 100644 --- a/test/src/htmltest.coffee +++ b/test/src/htmltest.coffee @@ -113,7 +113,8 @@ asyncTest 'Basic Document parsing', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Hello", { @@ -180,7 +181,8 @@ asyncTest 'Basic Document parsing', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Welcome to my page!", { @@ -293,7 +295,8 @@ asyncTest 'Removal of Empty nodes', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Welcome to my world", { @@ -401,7 +404,8 @@ asyncTest 'Optional Closing tags', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Item1", { @@ -452,7 +456,8 @@ asyncTest 'Optional Closing tags', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Item2", { @@ -518,7 +523,8 @@ asyncTest 'Attribute Sockets', -> "dropdown": false, "handwritten": false, "parseContext": "blockTag", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "background=\"red\"", { @@ -585,7 +591,8 @@ asyncTest 'Scoket empty attribute values', -> "dropdown": false, "handwritten": false, "parseContext": "blockTag", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "background = \"\"", { @@ -654,7 +661,8 @@ asyncTest 'Check overrides', -> "dropdown": false, "handwritten": false, "parseContext": "blockTag", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "background = \"\"", { @@ -741,7 +749,8 @@ asyncTest 'Trailing Space', -> "dropdown": false, "handwritten": false, "parseContext": "text", - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, "Hello", { diff --git a/test/src/jstest.coffee b/test/src/jstest.coffee index be57302f..d821f294 100644 --- a/test/src/jstest.coffee +++ b/test/src/jstest.coffee @@ -50,7 +50,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "CalleeObject", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "x", { @@ -61,7 +62,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "100", { @@ -91,7 +93,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "blue", @@ -109,7 +112,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "green", @@ -127,7 +131,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "blue", @@ -144,7 +149,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "log", { @@ -155,7 +161,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "green", @@ -172,7 +179,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "CalleeObject", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "x", { @@ -183,7 +191,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "green", @@ -201,7 +210,8 @@ asyncTest 'JS dotted methods', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "red", @@ -307,7 +317,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "cyan", @@ -324,7 +335,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator!=", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "b", { @@ -335,7 +347,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator!=", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "#777", @@ -353,7 +366,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Lvalue", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -364,7 +378,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "#666", @@ -381,7 +396,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "#666", @@ -399,7 +415,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "#444", @@ -416,7 +433,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator+", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "c", { @@ -427,7 +445,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "Operator+", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "d", { @@ -451,7 +470,8 @@ asyncTest 'JS Custom Colors', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "0", { @@ -523,7 +543,8 @@ asyncTest 'JS LogicalExpressions', -> "dropdown": false, "handwritten": false, "parseContext": "Operator&&", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -534,7 +555,8 @@ asyncTest 'JS LogicalExpressions', -> "dropdown": false, "handwritten": false, "parseContext": "Operator&&", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "b", { @@ -578,7 +600,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "foo", { @@ -589,7 +612,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "+1", { @@ -600,7 +624,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "-1", { @@ -611,7 +636,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "green", @@ -629,7 +655,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "blue", @@ -646,7 +673,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -657,7 +685,8 @@ asyncTest 'JS omits unary +/- for literals', -> "dropdown": false, "handwritten": false, "parseContext": null, - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, { "type": "socketEnd" @@ -722,7 +751,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "cyan", @@ -739,7 +769,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -750,7 +781,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "0", { @@ -787,7 +819,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "fd", { @@ -798,7 +831,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "0", { @@ -820,7 +854,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "cyan", @@ -837,7 +872,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -848,7 +884,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "1", { @@ -885,7 +922,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "fd", { @@ -896,7 +934,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "100", { @@ -918,7 +957,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, { "color": "cyan", @@ -935,7 +975,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "a", { @@ -946,7 +987,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Operator==", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "2", { @@ -983,7 +1025,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "fd", { @@ -994,7 +1037,8 @@ asyncTest 'JS Elif', -> "dropdown": false, "handwritten": false, "parseContext": "Expression", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "200", { @@ -1057,7 +1101,8 @@ asyncTest 'JS beginner mode loops', -> "dropdown": false, "handwritten": false, "parseContext": "program", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "10", { @@ -1088,7 +1133,8 @@ asyncTest 'JS beginner mode loops', -> "dropdown": false, "handwritten": false, "parseContext": "Callee", - "type": "socketStart" + "type": "socketStart", + "emptyString": "__" }, "go", { @@ -1099,7 +1145,8 @@ asyncTest 'JS beginner mode loops', -> "dropdown": false, "handwritten": false, "parseContext": null, - "type": "socketStart" + "type": "socketStart", + "emptyString": "" }, { "type": "socketEnd" From 395a7e640099aba3aab0dcf8b741f5150f47381d Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 14:02:16 -0400 Subject: [PATCH 43/60] Oops, finish merging --- src/parser.coffee | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/parser.coffee b/src/parser.coffee index a205c80a..f4335202 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -636,11 +636,7 @@ exports.wrapParser = (CustomParser) -> @rootContext = CustomParser.rootContext @startSingleLineComment = CustomParser.startSingleLineComment @getDefaultSelectionRange = CustomParser.getDefaultSelectionRange ? getDefaultSelectionRange -<<<<<<< HEAD @getParenCandidates = CustomParser.getParenCandidates -======= - @rootContext = CustomParser.rootContext ->>>>>>> 4f4900d4928083f5d3b770ee2cd4188e7ca91ccf # TODO kind of hacky assignation of @empty, # maybe change the api? From b2a6aff148b845d36d3ad0b086468a593c8c1b95 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 14:06:08 -0400 Subject: [PATCH 44/60] Add necessary droppability graph file --- antlr/CDroppabilityGraph.json | 301 ++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 antlr/CDroppabilityGraph.json diff --git a/antlr/CDroppabilityGraph.json b/antlr/CDroppabilityGraph.json new file mode 100644 index 00000000..c7041d75 --- /dev/null +++ b/antlr/CDroppabilityGraph.json @@ -0,0 +1,301 @@ +{ + "assignmentExpression": [ + "conditionalExpression" + ], + "typeSpecifier": [ + "atomicTypeSpecifier", + "typedefName", + "enumSpecifier", + "structOrUnionSpecifier" + ], + "gccDeclaratorExtension": [ + "gccAttributeSpecifier" + ], + "unaryOperator_DropletFile": [], + "structOrUnion_DropletFile": [], + "initializer": [ + "assignmentExpression" + ], + "selectionStatement_DropletFile": [], + "additiveExpression": [ + "multiplicativeExpression" + ], + "parameterTypeList": [ + "parameterList" + ], + "storageClassSpecifier_DropletFile": [], + "gccDeclaratorExtension_DropletFile": [], + "abstractDeclarator": [ + "pointer", + "directAbstractDeclarator" + ], + "externalDeclaration": [ + "declaration", + "functionDefinition" + ], + "enumerator": [ + "enumerationConstant" + ], + "structOrUnionSpecifier": [], + "alignmentSpecifier_DropletFile": [], + "declarationSpecifiers2": [ + "declarationSpecifier" + ], + "compoundStatement_DropletFile": [], + "declarationSpecifiers": [ + "declarationSpecifier" + ], + "translationUnit": [ + "externalDeclaration" + ], + "structOrUnionSpecifier_DropletFile": [], + "shiftExpression_DropletFile": [], + "initDeclarator_DropletFile": [], + "multiplicativeExpression": [ + "castExpression" + ], + "structDeclaratorList_DropletFile": [], + "exclusiveOrExpression_DropletFile": [], + "structOrUnion": [], + "enumerationConstant_DropletFile": [], + "expressionStatement_DropletFile": [], + "designation_DropletFile": [], + "abstractDeclarator_DropletFile": [], + "directDeclarator": [], + "jumpStatement": [], + "labeledStatement_DropletFile": [], + "unaryExpression": [ + "postfixExpression" + ], + "declarationSpecifier": [ + "typeQualifier", + "functionSpecifier", + "alignmentSpecifier", + "typeSpecifier", + "storageClassSpecifier" + ], + "typedefName": [], + "relationalExpression": [ + "shiftExpression" + ], + "structDeclarationList": [ + "structDeclaration" + ], + "primaryExpression_DropletFile": [], + "specialMethodCall_DropletFile": [], + "gccAttribute_DropletFile": [], + "blockItemList_DropletFile": [], + "genericSelection": [], + "logicalAndExpression_DropletFile": [], + "structDeclaration_DropletFile": [], + "enumSpecifier": [], + "statement_DropletFile": [], + "functionSpecifier_DropletFile": [], + "genericAssocList": [ + "genericAssociation" + ], + "designatorList_DropletFile": [], + "parameterDeclaration_DropletFile": [], + "declaration": [ + "staticAssertDeclaration" + ], + "parameterTypeList_DropletFile": [], + "iterationStatement": [], + "logicalOrExpression_DropletFile": [], + "declarationSpecifiers2_DropletFile": [], + "nestedParenthesesBlock_DropletFile": [ + 0 + ], + "declarator": [ + "directDeclarator" + ], + "compilationUnit": [], + "initDeclaratorList_DropletFile": [], + "exclusiveOrExpression": [ + "andExpression" + ], + "jumpStatement_DropletFile": [], + "specifierQualifierList": [ + "typeQualifier", + "typeSpecifier" + ], + "typeName": [ + "specifierQualifierList" + ], + "enumerationConstant": [], + "relationalExpression_DropletFile": [], + "genericAssociation": [], + "expression_DropletFile": [], + "declarator_DropletFile": [], + "iterationStatement_DropletFile": [], + "postfixExpression_DropletFile": [], + "structDeclaratorList": [ + "structDeclarator" + ], + "initializerList": [ + "initializer" + ], + "enumeratorList_DropletFile": [], + "gccAttributeSpecifier": [], + "externalDeclaration_DropletFile": [], + "typeQualifierList": [ + "typeQualifier" + ], + "primaryExpression": [ + "genericSelection" + ], + "structDeclarationsBlock_DropletFile": [], + "structDeclaration": [ + "staticAssertDeclaration" + ], + "inclusiveOrExpression": [ + "exclusiveOrExpression" + ], + "andExpression": [ + "equalityExpression" + ], + "designatorList": [ + "designator" + ], + "designation": [], + "structDeclarationsBlock": [], + "initDeclaratorList": [ + "initDeclarator" + ], + "logicalAndExpression": [ + "inclusiveOrExpression" + ], + "multiplicativeExpression_DropletFile": [], + "assignmentOperator": [], + "structDeclarationList_DropletFile": [], + "expression": [ + "assignmentExpression" + ], + "directAbstractDeclarator": [], + "specialMethodCall": [], + "structDeclarator_DropletFile": [], + "initDeclarator": [ + "declarator" + ], + "structDeclarator": [ + "declarator" + ], + "gccAttributeList_DropletFile": [], + "staticAssertDeclaration": [], + "compoundStatement": [], + "enumeratorList": [ + "enumerator" + ], + "assignmentExpression_DropletFile": [], + "directDeclarator_DropletFile": [], + "gccAttribute": [], + "statement": [ + "expressionStatement", + "selectionStatement", + "compoundStatement", + "jumpStatement", + "iterationStatement", + "labeledStatement" + ], + "typeQualifier": [], + "declaration_DropletFile": [], + "equalityExpression": [ + "relationalExpression" + ], + "typeQualifier_DropletFile": [], + "constantExpression_DropletFile": [], + "atomicTypeSpecifier_DropletFile": [], + "inclusiveOrExpression_DropletFile": [], + "storageClassSpecifier": [], + "blockItemList": [ + "blockItem" + ], + "gccAttributeSpecifier_DropletFile": [], + "gccAttributeList": [ + "gccAttribute" + ], + "declarationSpecifiers_DropletFile": [], + "postfixExpression": [ + "primaryExpression" + ], + "castExpression": [ + "unaryExpression" + ], + "andExpression_DropletFile": [], + "selectionStatement": [], + "genericSelection_DropletFile": [], + "shiftExpression": [ + "additiveExpression" + ], + "identifierList": [], + "parameterList_DropletFile": [], + "alignmentSpecifier": [], + "typeQualifierList_DropletFile": [], + "typeSpecifier_DropletFile": [], + "conditionalExpression": [ + "logicalOrExpression" + ], + "parameterDeclaration": [ + "declarationSpecifiers2" + ], + "translationUnit_DropletFile": [], + "functionSpecifier": [ + "gccAttributeSpecifier" + ], + "castExpression_DropletFile": [], + "functionDefinition": [], + "argumentExpressionList_DropletFile": [], + "genericAssocList_DropletFile": [], + "blockItem": [ + "specialMethodCall", + "declaration", + "statement" + ], + "designator_DropletFile": [], + "expressionStatement": [], + "pointer": [], + "atomicTypeSpecifier": [], + "constantExpression": [ + "conditionalExpression" + ], + "argumentExpressionList": [ + "assignmentExpression" + ], + "unaryOperator": [], + "additiveExpression_DropletFile": [], + "logicalOrExpression": [ + "logicalAndExpression" + ], + "declarationList": [ + "declaration" + ], + "declarationList_DropletFile": [], + "labeledStatement": [], + "directAbstractDeclarator_DropletFile": [], + "typeName_DropletFile": [], + "assignmentOperator_DropletFile": [], + "equalityExpression_DropletFile": [], + "blockItem_DropletFile": [], + "declarationSpecifier_DropletFile": [], + "identifierList_DropletFile": [], + "compilationUnit_DropletFile": [], + "enumerator_DropletFile": [], + "pointer_DropletFile": [], + "functionDefinition_DropletFile": [], + "conditionalExpression_DropletFile": [], + "typedefName_DropletFile": [], + "staticAssertDeclaration_DropletFile": [], + "unaryExpression_DropletFile": [], + "enumSpecifier_DropletFile": [], + "specifierQualifierList_DropletFile": [], + "initializerList_DropletFile": [], + "parameterList": [ + "parameterDeclaration" + ], + "genericAssociation_DropletFile": [], + "designator": [], + "initializer_DropletFile": [], + "nestedParenthesesBlock": [ + 0 + ] +} From a9838c3da04be29f9f4c8dbf47d36271961f9b0f Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 14:33:16 -0400 Subject: [PATCH 45/60] Fix coffee precedences --- src/controller.coffee | 2 +- src/languages/c.coffee | 2 +- src/languages/coffee.coffee | 18 +++++++++++------- src/treewalk.coffee | 2 -- test/data/c-freeze-populator.js | 4 ++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index dd6e551b..79de52a3 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -3284,7 +3284,7 @@ hook 'keydown', 0, (event, state) -> while head.type is 'newline' head = head.prev - newSocket.parseContext = head.parent.parseContext + newSocket.parseContext = head.container?.indentContext ? head.parent.parseContext @spliceIn newBlock, head #MUTATION diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 9d3d2354..e7ee2079 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -300,7 +300,7 @@ config.EMPTY_STRINGS = { 'declaration': '__0_droplet__ __0_droplet__;' } config.emptyIndent = '' -config.rootContext = 'translationUnit' +config.rootContext = 'externalDeclaration' # DEBUG config.unParenWrap = null diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index a7cf9329..e7ca08d4 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -146,11 +146,14 @@ OPERATOR_PRECEDENCES = '%%': 7 PRECEDENCES = { - 'Semicolon': -2 + 'Semicolon': -3 'Range': 100 'Arr': 100 - 'For': -3 - 'While': -3 + 'For': -4 + 'While': -4 + 'Expression' : 0 + 'Call': 0 + 'LastCallArg': -1 } for operator, precedence of OPERATOR_PRECEDENCES @@ -601,10 +604,12 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser # Inline function definitions that appear as the last arg # of a function call will be melded into the parent block. @addCode arg, depth + 1, indentDepth + else if last + @csSocketAndMark arg, depth + 1, 'LastCallArg', indentDepth, known?.fn?.dropdown?[index] else if not known and hasCallParen and index is 0 and node.args.length is 1 - @csSocketAndMark arg, depth + 1, precedence, indentDepth, known?.fn?.dropdown?[index], '' + @csSocketAndMark arg, depth + 1, 'Expression', indentDepth, known?.fn?.dropdown?[index], '' else - @csSocketAndMark arg, depth + 1, precedence, indentDepth, known?.fn?.dropdown?[index] + @csSocketAndMark arg, depth + 1, 'Expression', indentDepth, known?.fn?.dropdown?[index] # ### Code ### # Function definition. Color VALUE, sockets @params, @@ -1181,9 +1186,8 @@ CoffeeScriptParser.parens = (leading, trailing, node, context) -> trailing trailing().replace(/\s*\)\s*$/, '') else break - if context is null or context.type isnt 'socket' or + unless context is null or context.type isnt 'socket' or getPrecedence(context.parseContext) < getPrecedence(node.nodeContext.type) - else console.log 'adding as the result of', context.parseContext, node.nodeContext.type, getPrecedence(context.parseContext), getPrecedence(node.nodeContext.type) leading '(' + leading() trailing trailing() + ')' diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 3f08a2ba..a89b0980 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -300,6 +300,4 @@ exports.createTreewalkParser = (parse, config, root) -> TreewalkParser.getDefaultSelectionRange = config.getDefaultSelectionRange TreewalkParser.empty = config.empty - TreewalkParser.rootContext = root - return TreewalkParser diff --git a/test/data/c-freeze-populator.js b/test/data/c-freeze-populator.js index 76d55eaf..9b478ecb 100644 --- a/test/data/c-freeze-populator.js +++ b/test/data/c-freeze-populator.js @@ -2,7 +2,7 @@ window.FREEZE_DATA = {}; window.FREEZE_DATA.freezeTest = [ { - "indentContext": "translationUnit", + "indentContext": "externalDeclaration", "type": "documentStart" }, { @@ -5091,7 +5091,7 @@ window.FREEZE_DATA.freezeTest = [ window.FREEZE_DATA.commentConsolidation = [ { - "indentContext": "translationUnit", + "indentContext": "externalDeclaration", "type": "documentStart" }, { From b08dc644e8a9595b38e4dacdc7501837399a73a4 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 14:57:35 -0400 Subject: [PATCH 46/60] Fix the rest of the tests --- src/languages/coffee.coffee | 15 ++++++------- test/data/parserSuccess.js | 43 ++++++++++++++++++------------------- test/src/cstest.coffee | 28 ++++++++++++------------ 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index e7ca08d4..4acf259c 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -149,6 +149,7 @@ PRECEDENCES = { 'Semicolon': -3 'Range': 100 'Arr': 100 + 'PropertyAccess': 100 'For': -4 'While': -4 'Expression' : 0 @@ -389,7 +390,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser shouldBeOneLine = true if shouldBeOneLine - @csSocket node, depth, 0 + @csSocket node, depth, 'Block' # Otherwise, wrap in an indent. else @@ -482,13 +483,13 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @csSocketAndMark node.second, depth + 1, 'Operator' + node.operator, indentDepth # ### Existence ### - # Color VALUE, socket @expression, precedence 100 + # Color VALUE, socket @expression when 'Existence' @csBlock node, depth, 'Existence', wrappingParen, VALUE_ONLY @csSocketAndMark node.expression, depth + 1, 'Existence', indentDepth # ### In ### - # Color VALUE, sockets @object and @array, precedence 100 + # Color VALUE, sockets @object and @array when 'In' @csBlock node, depth, 'In', wrappingParen, VALUE_ONLY @csSocketAndMark node.object, depth + 1, 'In', indentDepth @@ -500,7 +501,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser when 'Value' if node.properties? and node.properties.length > 0 @csBlock node, depth, 'PropertyAccess', wrappingParen, MOSTLY_VALUE - @csSocketAndMark node.base, depth + 1, 0, indentDepth + @csSocketAndMark node.base, depth + 1, 'PropertyAccess', indentDepth for property in node.properties if property.nodeType() is 'Access' @csSocketAndMark property.name, depth + 1, 'Identifier', indentDepth @@ -599,7 +600,6 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser last = index is node.args.length - 1 # special case: the last argument slot of a function # gathers anything inside it, without parens needed. - precedence = if last then -1 else 0 if last and arg.nodeType() is 'Code' # Inline function definitions that appear as the last arg # of a function call will be melded into the parent block. @@ -627,7 +627,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser if node.value.nodeType() is 'Code' @addCode node.value, depth + 1, indentDepth else - @csSocketAndMark node.value, depth + 1, 'FunctionBody', indentDepth + @csSocketAndMark node.value, depth + 1, 'Expression', indentDepth # ### For ### # Color CONTROL, options sockets @index, @source, @name, @from. @@ -740,7 +740,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser if node.subject? then @csSocketAndMark node.subject, depth + 1, 'Expression', indentDepth for switchCase in node.cases - if switchCase[0].constructor is Array + if switchCase[0].constructor is rrray for condition in switchCase[0] @csSocketAndMark condition, depth + 1, 'Expression', indentDepth # (condition) else @@ -965,7 +965,6 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser @addBlock { bounds: @getBounds (wrappingParen ? node) depth: depth - precedence: precedence color: @getColor(node) buttons: buttons shape: shape diff --git a/test/data/parserSuccess.js b/test/data/parserSuccess.js index 04009927..ec657b85 100644 --- a/test/data/parserSuccess.js +++ b/test/data/parserSuccess.js @@ -1,23 +1,22 @@ window.parserSuccessData = [ -{"message":"Function call","str":"alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Variable assignment","str":"a = b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Assign","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," = ",{"type":"socketStart","emptyString":"``","parseContext":"FunctionBody","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"If statement, normal form","str":"if true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Unless statement, normal form","str":"unless true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"unless ","suffix":""}},"unless ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"One-line if statement","str":"if a then b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"If-else statement, normal form","str":"if true\n alert 10\nelse\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"newline","specialIndent":undefined},"else",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"One-line if-else statement","str":"if a then b else c","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"b",{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"While statement, normal form","str":"while a\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"One-line while statement","str":"while a then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"For-in, normal form","str":"for i in list\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"One-line for-in","str":"for i in list then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Inverted one-line for-in","str":"alert 10 for i in list","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Semicolons at the root","str":"alert 10; prompt 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Semicolons with one-line block","str":"if a then b; c else d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":0,"handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Semicolons in sequence","str":"while a\n console.log hi\n alert 10; prompt 10\n console.log bye","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"hi",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"bye",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Object literal, normal form","str":"foo {\n a: b,\n c: d\n}","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"{","suffix":"}"}},"{",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},",",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined},"}",{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Object literal, no braces or commas","str":"foo\n a: b\n c: d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"String interpolation","str":"foo \"#{a}\"","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":-1,"handwritten":false,"dropdown":false},"\"#{a}\"",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Range","str":"[1..10]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Range","prefix":"[","suffix":"]"}},"[",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"1",{"type":"socketEnd"},"..",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}, -{"message":"Array","str":"[0, 1]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Arr","prefix":"[","suffix":"]"}},"[",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"0, ","suffix":"0, "}},"0, ",{"type":"blockEnd"},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"1","suffix":"1"}},"1",{"type":"blockEnd"},{"type":"indentEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}] - - + {"message":"Function call","str":"alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Variable assignment","str":"a = b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Assign","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," = ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"If statement, normal form","str":"if true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Unless statement, normal form","str":"unless true\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"unless ","suffix":""}},"unless ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"One-line if statement","str":"if a then b","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"If-else statement, normal form","str":"if true\n alert 10\nelse\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"true",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"newline","specialIndent":undefined},"else",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"One-line if-else statement","str":"if a then b else c","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"While statement, normal form","str":"while a\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"One-line while statement","str":"while a then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"For-in, normal form","str":"for i in list\n alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"One-line for-in","str":"for i in list then alert 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"for ","suffix":""}},"for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Inverted one-line for-in","str":"alert 10 for i in list","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"For","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," for ",{"type":"socketStart","emptyString":"``","parseContext":"Lvalue","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}," in ",{"type":"socketStart","emptyString":"``","parseContext":"ForModifier","handwritten":false,"dropdown":false},"list",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Semicolons at the root","str":"alert 10; prompt 10","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Semicolons with one-line block","str":"if a then b; c else d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"If","prefix":"if ","suffix":""}},"if ",{"type":"socketStart","emptyString":"``","parseContext":"If","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"}," then ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"}," else ",{"type":"socketStart","emptyString":"``","parseContext":"Block","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Semicolons in sequence","str":"while a\n console.log hi\n alert 10; prompt 10\n console.log bye","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"orange","shape":2,"parseContext":"__comment__","nodeContext":{"type":"While","prefix":"while ","suffix":""}},"while ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},{"type":"indentStart","prefix":" ","indentContext":null},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"hi",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"program","nodeContext":{"type":"semicolon","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"alert ","suffix":""}},"alert ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},"; ",{"type":"socketStart","emptyString":"``","parseContext":"semicolon","handwritten":false,"dropdown":false},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"prompt ","suffix":""}},"prompt ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"newline","specialIndent":undefined},{"type":"blockStart","color":"blue","shape":2,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"console.log ","suffix":""}},"console.log ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"bye",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Object literal, normal form","str":"foo {\n a: b,\n c: d\n}","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"{","suffix":"}"}},"{",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},",",{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined},"}",{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Object literal, no braces or commas","str":"foo\n a: b\n c: d","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Obj","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"a",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"b",{"type":"socketEnd"},{"type":"newline","specialIndent":undefined}," ",{"type":"socketStart","emptyString":"``","parseContext":"Identifier","handwritten":false,"dropdown":false},"c",{"type":"socketEnd"},": ",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"d",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"String interpolation","str":"foo \"#{a}\"","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"blue","shape":0,"parseContext":"__comment__","nodeContext":{"type":"Call","prefix":"","suffix":""}},{"type":"socketStart","emptyString":"``","parseContext":"Callee","handwritten":false,"dropdown":false},"foo",{"type":"socketEnd"}," ",{"type":"socketStart","emptyString":"``","parseContext":"LastCallArg","handwritten":false,"dropdown":false},"\"#{a}\"",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Range","str":"[1..10]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Range","prefix":"[","suffix":"]"}},"[",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"1",{"type":"socketEnd"},"..",{"type":"socketStart","emptyString":"``","parseContext":"Expression","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]}, + {"message":"Array","str":"[0, 1]","expected":[{"type":"documentStart","indentContext":undefined},{"type":"blockStart","color":"teal","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Arr","prefix":"[","suffix":"]"}},"[",{"type":"indentStart","prefix":" ","indentContext":null},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"0, ","suffix":"0, "}},"0, ",{"type":"blockEnd"},{"type":"blockStart","color":"green","shape":4,"parseContext":"__comment__","nodeContext":{"type":"Value","prefix":"1","suffix":"1"}},"1",{"type":"blockEnd"},{"type":"indentEnd"},"]",{"type":"blockEnd"},{"type":"documentEnd"}]} +]; diff --git a/test/src/cstest.coffee b/test/src/cstest.coffee index 3123a683..1b50eadd 100644 --- a/test/src/cstest.coffee +++ b/test/src/cstest.coffee @@ -47,7 +47,7 @@ asyncTest 'Parser configurability', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -66,7 +66,7 @@ asyncTest 'Parser configurability', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -113,7 +113,7 @@ asyncTest 'Parser configurability', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -143,7 +143,7 @@ asyncTest 'Parser configurability', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -179,7 +179,7 @@ asyncTest 'Parser configurability', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -245,7 +245,7 @@ asyncTest 'Dotted methods', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -264,7 +264,7 @@ asyncTest 'Dotted methods', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -283,7 +283,7 @@ asyncTest 'Dotted methods', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -313,7 +313,7 @@ asyncTest 'Dotted methods', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -449,7 +449,7 @@ asyncTest 'Merged code blocks', -> { "dropdown": false, "handwritten": false, - "parseContext": 0, + "parseContext": "Block", "type": "socketStart", "emptyString": "``" }, @@ -515,7 +515,7 @@ asyncTest 'Merged code blocks', -> { "dropdown": false, "handwritten": false, - "parseContext": 0, + "parseContext": "Expression", "type": "socketStart", "emptyString": "``" }, @@ -548,7 +548,7 @@ asyncTest 'Merged code blocks', -> { "dropdown": false, "handwritten": false, - "parseContext": -1, + "parseContext": "LastCallArg", "type": "socketStart", "emptyString": "``" }, @@ -674,7 +674,7 @@ asyncTest 'Custom Colors', -> { "dropdown": false, "handwritten": false, - "parseContext": "FunctionBody", + "parseContext": "Expression", "type": "socketStart", "emptyString": "``" }, @@ -692,7 +692,7 @@ asyncTest 'Custom Colors', -> { "dropdown": false, "handwritten": false, - "parseContext": 0, + "parseContext": "PropertyAccess", "type": "socketStart", "emptyString": "``" }, From f4004afae1b672a335dee3528c4375d5ca13185c Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 15:07:31 -0400 Subject: [PATCH 47/60] Fix typo --- src/languages/coffee.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index 4acf259c..5bcf469b 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -740,7 +740,7 @@ exports.CoffeeScriptParser = class CoffeeScriptParser extends parser.Parser if node.subject? then @csSocketAndMark node.subject, depth + 1, 'Expression', indentDepth for switchCase in node.cases - if switchCase[0].constructor is rrray + if switchCase[0].constructor is Array for condition in switchCase[0] @csSocketAndMark condition, depth + 1, 'Expression', indentDepth # (condition) else From 0e23a774606d84d0604685fed1c1bd2fec6fef6d Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 16:07:07 -0400 Subject: [PATCH 48/60] Fix some merge conflicts and a typo --- src/controller.coffee | 3 +- src/languages/c.coffee | 34 +- src/model.coffee | 10 + src/treewalk.coffee | 14 +- test/data/c-freeze-populator.js | 1185 +++++++++++++++---------------- test/src/ctest.coffee | 2 +- test/src/jstest.coffee | 4 +- 7 files changed, 623 insertions(+), 629 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index 0f480faa..28d7d2fc 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1185,7 +1185,7 @@ Editor::correctCursor = -> @session.cursor = @toCrossDocumentLocation cursor Editor::prepareNode = (node, context) -> - if node instanceof model.Container + if node.type is 'block' leading = node.getLeadingText() if node.start.next is node.end.prev trailing = null @@ -1355,6 +1355,7 @@ hook 'mousedown', 4, (point, event, state) -> for key, button of viewNode.buttonRects if button.contains mainPoint + console.log 'HIT BUTTON', key str = result.stringifyInPlace() line = @session.mode.handleButton str, key, result #.getReader() # TODO getReader() that allows tree walking if line?.length >= 0 and line isnt str diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 96ba553d..c9f84c8c 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -148,7 +148,7 @@ RULES = { ) and ( (not node.children[0].children[0]?.children?[0]?) or - node.children[0].children[0].children[0].type isnt 'Identifier' or not opts.knownFunctions? + node.children[0].children[0].children[0].type isnt 'Identifier' or not opts.knownFunctions? or node.children[0].children[0].children[0].data.text not of opts.knownFunctions or opts.knownFunctions[node.children[0].children[0].children[0].data.text].minArgs? ) @@ -476,8 +476,11 @@ removeLastSocketAnd = (str, block, prefixClip = null, suffixClip = null) -> return prefix + suffix config.handleButton = (str, type, block) -> + blockType = block.nodeContext?.type ? block.parseContext + if type is 'add-button' - if block.nodeContext.type is 'selectionStatement' + + if blockType is 'selectionStatement' indents = [] block.traverseOneLevel (child) -> if child.type is 'indent' @@ -509,23 +512,26 @@ config.handleButton = (str, type, block) -> return prefix + '\n}\nelse if (a == b)\n{\n \n' + suffix - else if block.nodeContext.type is 'postfixExpression' or block.nodeContext.type is 'specialMethodCall' + else if blockType is 'postfixExpression' or blockType is 'specialMethodCall' if str.match(/\(\s*\)\s*;?$/)? return str.replace(/(\s*\)\s*;?\s*)$/, "#{config.empty}$1") else return str.replace(/(\s*\)\s*;?\s*)$/, ", #{config.empty}$1") - else if block.nodeContext.type is 'parameterList' + else if blockType is 'parameterList' if str.match(/^\s*void\s*$/) return "type param" return str + ", type param" - else if block.nodeContext.type is 'declaration' + else if blockType is 'declaration' return str.replace(/(\s*;?\s*)$/, ", #{config.empty} = #{config.empty}$1") - else if block.nodeContext.type is 'initializer' + else if blockType is 'initializer' return str.replace(/(\s*}\s*)$/, ", #{config.empty}$1") - else if block.nodeContext.type is 'expression' + else if blockType is 'expression' return str.replace(/(\s*;\s*)?$/, ", #{config.empty}$1") - else - if block.nodeContext.type is 'selectionStatement' + + + else if type is 'subtract-button' + + if blockType is 'selectionStatement' indents = [] block.traverseOneLevel (child) -> if child.type is 'indent' @@ -549,9 +555,9 @@ config.handleButton = (str, type, block) -> return prefix + suffix - else if block.nodeContext.type is 'postfixExpression' or block.nodeContext.type is 'specialMethodCall' + else if blockType is 'postfixExpression' or blockType is 'specialMethodCall' return removeLastSocketAnd str, block, /\s*,\s*$/ - else if block.nodeContext.type is 'declaration' + else if blockType is 'declaration' reparsed = config.__antlrParse 'declaration', str lines = str.split '\n' @@ -561,16 +567,16 @@ config.handleButton = (str, type, block) -> prefix = prefix.replace /\s*,\s*$/, '' return prefix + suffix - else if block.nodeContext.type is 'initializer' + else if blockType is 'initializer' return removeLastSocketAnd str, block, /\s*,\s*$/ - else if block.nodeContext.type is 'parameterList' + else if blockType is 'parameterList' count = 0 block.traverseOneLevel (x) -> if x.type is 'socket' then count++ if count is 1 return 'void' else return removeLastSocketAnd str, block, /\s*,\s*$/ - else if block.nodeContext.type is 'expression' + else if blockType is 'expression' return removeLastSocketAnd str, block, /\s*,\s*$/ return str diff --git a/src/model.coffee b/src/model.coffee index 223bebc1..14018373 100644 --- a/src/model.coffee +++ b/src/model.coffee @@ -998,6 +998,16 @@ exports.ButtonContainer = class ButtonContainer extends Container super + _serialize_header: -> { + type: 'buttonContainerStart' + parseContext: @parseContext + buttons: @buttons + } + + _serialize_footer: -> { + type: 'buttonContainerEnd' + } + _cloneEmpty: -> new ButtonContainer @parseContext, @buttons, @data exports.ButtonContainerStartToken = class ButtonContainerStartToken extends StartToken diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 428ac825..e938b17e 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -129,13 +129,10 @@ exports.createTreewalkParser = (parse, config, root) -> parseContext: rules[0] @flagToRemove node.bounds, depth + 1 ->>>>>>> graph-based-droppability else if node.children.length > 0 switch @detNode node when 'block' - paddedRules = padRules wrapRules, rules - if wrap? bounds = wrap.bounds else @@ -153,12 +150,11 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth + 1 color: @getColor node shape: @getShape node + buttons: @getButtons node nodeContext: @getNodeContext node, wrap parseContext: rules[rules.length - 1] when 'buttonContainer' - paddedRules = padRules wrapRules, rules - if wrap? bounds = wrap.bounds else @@ -168,7 +164,6 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth + 1 parseContext: rules[0] - classes: paddedRules buttons: @getButtons(node) color: @getColor node shape: @getShape node @@ -189,8 +184,6 @@ exports.createTreewalkParser = (parse, config, root) -> return else - paddedRules = padRules wrapRules, rules - node.blockified = true if wrap? @@ -208,13 +201,12 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: bounds depth: depth + 1 color: @getColor node + buttons: @getButtons node shape: @getShape node nodeContext: @getNodeContext node, wrap parseContext: rules[rules.length - 1] when 'indent' - paddedRules = padRules wrapRules, rules - # A lone indent needs to be wrapped in a block. if @det(context) isnt 'block' @addBlock @@ -222,6 +214,7 @@ exports.createTreewalkParser = (parse, config, root) -> depth: depth color: @getColor node shape: @getShape node + buttons: @getButtons node nodeContext: @getNodeContext node, warp parseContext: rules[rules.length - 1] @@ -263,7 +256,6 @@ exports.createTreewalkParser = (parse, config, root) -> @mark child, prefix, depth + 2, false else if context? and @detNode(context) in ['block', 'buttonContainer'] if @det(node) is 'socket' and ((not config.SHOULD_SOCKET?) or config.SHOULD_SOCKET(@opts, node)) - paddedRules = padRules wrapRules, rules @addSocket empty: config.EMPTY_STRINGS?[node.type] ? config.empty bounds: node.bounds diff --git a/test/data/c-freeze-populator.js b/test/data/c-freeze-populator.js index 9b478ecb..4c420415 100644 --- a/test/data/c-freeze-populator.js +++ b/test/data/c-freeze-populator.js @@ -19,10 +19,10 @@ window.FREEZE_DATA.freezeTest = [ "#include <", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, "stdio.h", { @@ -50,10 +50,10 @@ window.FREEZE_DATA.freezeTest = [ "#include <", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, "stdlib.h", { @@ -81,10 +81,10 @@ window.FREEZE_DATA.freezeTest = [ "#define ", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, "MAXLEN", { @@ -93,10 +93,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, "100", { @@ -141,10 +141,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Linked list", { @@ -171,10 +171,10 @@ window.FREEZE_DATA.freezeTest = [ "struct ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -204,10 +204,10 @@ window.FREEZE_DATA.freezeTest = [ "long ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -223,10 +223,10 @@ window.FREEZE_DATA.freezeTest = [ "long ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -260,10 +260,10 @@ window.FREEZE_DATA.freezeTest = [ "struct ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -272,10 +272,10 @@ window.FREEZE_DATA.freezeTest = [ " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -303,10 +303,10 @@ window.FREEZE_DATA.freezeTest = [ "struct ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -315,10 +315,10 @@ window.FREEZE_DATA.freezeTest = [ " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "prev", { @@ -357,10 +357,10 @@ window.FREEZE_DATA.freezeTest = [ "typedef struct ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -369,10 +369,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -418,10 +418,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Memoryless swap", { @@ -448,22 +448,38 @@ window.FREEZE_DATA.freezeTest = [ "void ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "swap", { "type": "socketEnd" }, "(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -479,10 +495,10 @@ window.FREEZE_DATA.freezeTest = [ "long long *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -497,10 +513,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -516,10 +532,10 @@ window.FREEZE_DATA.freezeTest = [ "long long *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -531,6 +547,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ") {", { "indentContext": "blockItem", @@ -554,10 +573,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -573,10 +592,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -591,10 +610,10 @@ window.FREEZE_DATA.freezeTest = [ " ^= ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -610,10 +629,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -646,10 +665,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -665,10 +684,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -683,10 +702,10 @@ window.FREEZE_DATA.freezeTest = [ " ^= ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -702,10 +721,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -738,10 +757,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -757,10 +776,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -775,10 +794,10 @@ window.FREEZE_DATA.freezeTest = [ " ^= ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -794,10 +813,10 @@ window.FREEZE_DATA.freezeTest = [ "*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -860,10 +879,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Test if sorted", { @@ -890,22 +909,38 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "sorted", { "type": "socketEnd" }, "(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -920,10 +955,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -932,10 +967,10 @@ window.FREEZE_DATA.freezeTest = [ " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -950,10 +985,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -969,22 +1004,38 @@ window.FREEZE_DATA.freezeTest = [ "int (*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "fn", { "type": "socketEnd" }, ")(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "comment", @@ -1007,10 +1058,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "comment", @@ -1030,6 +1081,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ")", { "type": "blockEnd" @@ -1037,6 +1091,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ") {", { "indentContext": "blockItem", @@ -1061,10 +1118,10 @@ window.FREEZE_DATA.freezeTest = [ "for (", { "dropdown": false, + "emptyString": "__0_droplet__ __0_droplet__;", "handwritten": false, "parseContext": "declaration", - "type": "socketStart", - "emptyString": "__0_droplet__ __0_droplet__;" + "type": "socketStart" }, { "color": "control", @@ -1079,41 +1136,22 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { "type": "socketEnd" }, - " ", - { - "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "*", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - "*", + " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1122,21 +1160,15 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -1147,10 +1179,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -1165,10 +1197,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "logicalAndExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1177,10 +1209,10 @@ window.FREEZE_DATA.freezeTest = [ " && ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "inclusiveOrExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1195,10 +1227,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1207,10 +1239,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -1231,10 +1263,10 @@ window.FREEZE_DATA.freezeTest = [ "; ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1249,10 +1281,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1261,10 +1293,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1279,10 +1311,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1291,10 +1323,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -1336,10 +1368,10 @@ window.FREEZE_DATA.freezeTest = [ "if (", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -1355,10 +1387,10 @@ window.FREEZE_DATA.freezeTest = [ "!", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1373,10 +1405,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "fn", { @@ -1385,10 +1417,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1403,10 +1435,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1415,10 +1447,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -1433,10 +1465,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1451,10 +1483,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1469,10 +1501,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -1481,10 +1513,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -1499,10 +1531,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -1551,10 +1583,10 @@ window.FREEZE_DATA.freezeTest = [ "return ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "0", { @@ -1604,10 +1636,10 @@ window.FREEZE_DATA.freezeTest = [ "return ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "1", { @@ -1664,10 +1696,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Bubble sort", { @@ -1694,22 +1726,38 @@ window.FREEZE_DATA.freezeTest = [ "void ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "sort", { "type": "socketEnd" }, "(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1724,10 +1772,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -1736,10 +1784,10 @@ window.FREEZE_DATA.freezeTest = [ " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -1754,10 +1802,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1773,22 +1821,38 @@ window.FREEZE_DATA.freezeTest = [ "int (*", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "fn", { "type": "socketEnd" }, ")(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "comment", @@ -1811,10 +1875,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "comment", @@ -1834,6 +1898,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ")", { "type": "blockEnd" @@ -1841,6 +1908,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ") {", { "indentContext": "blockItem", @@ -1865,10 +1935,10 @@ window.FREEZE_DATA.freezeTest = [ "while (", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -1884,10 +1954,10 @@ window.FREEZE_DATA.freezeTest = [ "!", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -1902,10 +1972,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "sorted", { @@ -1914,10 +1984,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -1926,10 +1996,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "fn", { @@ -1972,10 +2042,10 @@ window.FREEZE_DATA.freezeTest = [ "for (", { "dropdown": false, + "emptyString": "__0_droplet__ __0_droplet__;", "handwritten": false, "parseContext": "declaration", - "type": "socketStart", - "emptyString": "__0_droplet__ __0_droplet__;" + "type": "socketStart" }, { "color": "control", @@ -1990,41 +2060,22 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { "type": "socketEnd" }, - " ", - { - "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "*", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - "*", + " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2033,21 +2084,15 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -2058,10 +2103,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -2076,10 +2121,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "logicalAndExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2088,10 +2133,10 @@ window.FREEZE_DATA.freezeTest = [ " && ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "inclusiveOrExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2106,10 +2151,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2118,10 +2163,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -2142,10 +2187,10 @@ window.FREEZE_DATA.freezeTest = [ "; ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2160,10 +2205,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2172,10 +2217,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2190,10 +2235,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2202,10 +2247,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -2247,10 +2292,10 @@ window.FREEZE_DATA.freezeTest = [ "if (", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -2266,10 +2311,10 @@ window.FREEZE_DATA.freezeTest = [ "!", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2284,10 +2329,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "fn", { @@ -2296,10 +2341,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2314,10 +2359,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2326,10 +2371,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -2344,10 +2389,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2362,10 +2407,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2380,10 +2425,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2392,10 +2437,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -2410,10 +2455,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -2446,10 +2491,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "statement", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2464,10 +2509,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "swap", { @@ -2476,10 +2521,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -2495,10 +2540,10 @@ window.FREEZE_DATA.freezeTest = [ "&", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2513,10 +2558,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2525,10 +2570,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -2549,10 +2594,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -2568,10 +2613,10 @@ window.FREEZE_DATA.freezeTest = [ "&", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2586,10 +2631,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2604,10 +2649,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -2616,10 +2661,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -2634,10 +2679,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -2734,10 +2779,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Comparator", { @@ -2764,22 +2809,38 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "comparator", { "type": "socketEnd" }, "(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2795,10 +2856,10 @@ window.FREEZE_DATA.freezeTest = [ "long long ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -2813,10 +2874,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -2832,10 +2893,10 @@ window.FREEZE_DATA.freezeTest = [ "long long ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -2847,6 +2908,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ") {", { "indentContext": "blockItem", @@ -2871,10 +2935,10 @@ window.FREEZE_DATA.freezeTest = [ "return ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -2890,10 +2954,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "a", { @@ -2902,10 +2966,10 @@ window.FREEZE_DATA.freezeTest = [ " > ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "b", { @@ -2969,10 +3033,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Main", { @@ -2999,22 +3063,38 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "main", { "type": "socketEnd" }, "(", + { + "buttons": [ + { + "border": false, + "glyph": "◀", + "key": "subtract-button" + }, + { + "border": false, + "glyph": "▶", + "key": "add-button" + } + ], + "parseContext": "parameterList", + "type": "buttonContainerStart" + }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -3030,10 +3110,10 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "n", { @@ -3048,10 +3128,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "parameterDeclaration", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -3067,10 +3147,10 @@ window.FREEZE_DATA.freezeTest = [ "char *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "args", { @@ -3083,6 +3163,9 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, + { + "type": "buttonContainerEnd" + }, ") {", { "indentContext": "blockItem", @@ -3107,10 +3190,10 @@ window.FREEZE_DATA.freezeTest = [ "//", { "dropdown": false, + "emptyString": "", "handwritten": true, "parseContext": "__comment__", - "type": "socketStart", - "emptyString": "" + "type": "socketStart" }, " Arbitrary array initializer just o test that syntax", { @@ -3137,28 +3220,10 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - { - "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "arbitraryArray", { @@ -3167,10 +3232,10 @@ window.FREEZE_DATA.freezeTest = [ "[] = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3186,10 +3251,10 @@ window.FREEZE_DATA.freezeTest = [ "{", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializerList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "1", { @@ -3198,10 +3263,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "2", { @@ -3210,10 +3275,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "3", { @@ -3222,10 +3287,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "4", { @@ -3234,10 +3299,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "5", { @@ -3250,12 +3315,6 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -3278,10 +3337,10 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "length", { @@ -3309,10 +3368,10 @@ window.FREEZE_DATA.freezeTest = [ "scanf(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"%d\"", { @@ -3321,10 +3380,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3340,10 +3399,10 @@ window.FREEZE_DATA.freezeTest = [ "&", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "length", { @@ -3377,10 +3436,10 @@ window.FREEZE_DATA.freezeTest = [ "if (", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3395,10 +3454,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "length", { @@ -3407,10 +3466,10 @@ window.FREEZE_DATA.freezeTest = [ " > ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "MAXLEN", { @@ -3446,10 +3505,10 @@ window.FREEZE_DATA.freezeTest = [ "puts(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"Error: list is too large\"", { @@ -3477,10 +3536,10 @@ window.FREEZE_DATA.freezeTest = [ "return ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "1", { @@ -3518,41 +3577,22 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { "type": "socketEnd" }, - " ", - { - "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "*", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - "*", + " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -3561,10 +3601,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3580,10 +3620,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "typeName", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3598,10 +3638,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -3617,10 +3657,10 @@ window.FREEZE_DATA.freezeTest = [ ")", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -3635,10 +3675,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "malloc", { @@ -3647,10 +3687,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3666,10 +3706,10 @@ window.FREEZE_DATA.freezeTest = [ "sizeof(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "typeName", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -3695,12 +3735,6 @@ window.FREEZE_DATA.freezeTest = [ { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -3723,10 +3757,10 @@ window.FREEZE_DATA.freezeTest = [ "scanf(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"%d\"", { @@ -3735,10 +3769,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -3754,10 +3788,10 @@ window.FREEZE_DATA.freezeTest = [ "&", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -3772,10 +3806,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -3784,10 +3818,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -3826,10 +3860,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -3844,10 +3878,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -3856,10 +3890,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "prev", { @@ -3874,10 +3908,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "NULL", { @@ -3904,41 +3938,22 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifiers", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { "type": "socketEnd" }, - " ", - { - "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "*", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - "*", + " *", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "directDeclarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -3947,21 +3962,15 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -3984,10 +3993,10 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarationSpecifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "temp", { @@ -4015,10 +4024,10 @@ window.FREEZE_DATA.freezeTest = [ "for (", { "dropdown": false, + "emptyString": "__0_droplet__ __0_droplet__;", "handwritten": false, "parseContext": "declaration", - "type": "socketStart", - "emptyString": "__0_droplet__ __0_droplet__;" + "type": "socketStart" }, { "color": "control", @@ -4034,28 +4043,10 @@ window.FREEZE_DATA.freezeTest = [ "int ", { "dropdown": false, - "handwritten": false, - "parseContext": "initDeclaratorList", - "type": "socketStart", - "emptyString": "__0_droplet__" - }, - { - "color": "command", - "nodeContext": { - "prefix": "", - "suffix": "", - "type": "initDeclarator" - }, - "parseContext": "initDeclarator", - "shape": 1, - "type": "blockStart" - }, - { - "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "declarator", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "i", { @@ -4064,21 +4055,15 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "initializer", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "0", { "type": "socketEnd" }, - { - "type": "blockEnd" - }, - { - "type": "socketEnd" - }, ";", { "type": "blockEnd" @@ -4089,10 +4074,10 @@ window.FREEZE_DATA.freezeTest = [ " ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4107,10 +4092,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "relationalExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "i", { @@ -4119,10 +4104,10 @@ window.FREEZE_DATA.freezeTest = [ " < ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "shiftExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4137,10 +4122,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "additiveExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "length", { @@ -4149,10 +4134,10 @@ window.FREEZE_DATA.freezeTest = [ " - ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "multiplicativeExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "1", { @@ -4173,10 +4158,10 @@ window.FREEZE_DATA.freezeTest = [ "; ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4191,10 +4176,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "i", { @@ -4230,10 +4215,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4248,10 +4233,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4260,10 +4245,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -4278,10 +4263,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4297,10 +4282,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "typeName", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4315,10 +4300,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "specifierQualifierList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -4334,10 +4319,10 @@ window.FREEZE_DATA.freezeTest = [ ")", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4352,10 +4337,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "malloc", { @@ -4364,10 +4349,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4383,10 +4368,10 @@ window.FREEZE_DATA.freezeTest = [ "sizeof(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "typeName", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "List", { @@ -4433,10 +4418,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4445,10 +4430,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4463,10 +4448,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4475,10 +4460,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -4512,10 +4497,10 @@ window.FREEZE_DATA.freezeTest = [ "scanf(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"%d\"", { @@ -4524,10 +4509,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4543,10 +4528,10 @@ window.FREEZE_DATA.freezeTest = [ "&", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "temp", { @@ -4579,10 +4564,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4597,10 +4582,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4609,10 +4594,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -4627,10 +4612,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "value", @@ -4646,10 +4631,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "typeName", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4672,10 +4657,10 @@ window.FREEZE_DATA.freezeTest = [ ")", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "castExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "temp", { @@ -4719,10 +4704,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "sort", { @@ -4731,10 +4716,10 @@ window.FREEZE_DATA.freezeTest = [ "(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -4743,10 +4728,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "comparator", { @@ -4774,10 +4759,10 @@ window.FREEZE_DATA.freezeTest = [ "for (", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4792,10 +4777,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4804,10 +4789,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "head", { @@ -4822,10 +4807,10 @@ window.FREEZE_DATA.freezeTest = [ "; ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4834,10 +4819,10 @@ window.FREEZE_DATA.freezeTest = [ "; ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4852,10 +4837,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "unaryExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4864,10 +4849,10 @@ window.FREEZE_DATA.freezeTest = [ " = ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4882,10 +4867,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4894,10 +4879,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "next", { @@ -4939,10 +4924,10 @@ window.FREEZE_DATA.freezeTest = [ "printf(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "argumentExpressionList", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"%d \"", { @@ -4951,10 +4936,10 @@ window.FREEZE_DATA.freezeTest = [ ", ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, { "color": "command", @@ -4969,10 +4954,10 @@ window.FREEZE_DATA.freezeTest = [ }, { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "postfixExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "cursor", { @@ -4981,10 +4966,10 @@ window.FREEZE_DATA.freezeTest = [ "->", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "Identifier", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "data", { @@ -5029,10 +5014,10 @@ window.FREEZE_DATA.freezeTest = [ "puts(", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "assignmentExpression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "\"\\n\"", { @@ -5060,10 +5045,10 @@ window.FREEZE_DATA.freezeTest = [ "return ", { "dropdown": false, + "emptyString": "__0_droplet__", "handwritten": false, "parseContext": "expression", - "type": "socketStart", - "emptyString": "__0_droplet__" + "type": "socketStart" }, "0", { diff --git a/test/src/ctest.coffee b/test/src/ctest.coffee index 8ffad59a..df4915b3 100644 --- a/test/src/ctest.coffee +++ b/test/src/ctest.coffee @@ -341,7 +341,7 @@ asyncTest 'Controller: ANTLR paren wrap rules for C semicolons', -> asyncTest 'Controller: ANTLR reparse rules', -> document.getElementById('test-main').innerHTML = '' window.editor = editor = new droplet.Editor(document.getElementById('test-main'), { - mode: 'c', + mode: 'c_cpp', palette: [] }) diff --git a/test/src/jstest.coffee b/test/src/jstest.coffee index d821f294..5ff9bbc2 100644 --- a/test/src/jstest.coffee +++ b/test/src/jstest.coffee @@ -684,7 +684,7 @@ asyncTest 'JS omits unary +/- for literals', -> { "dropdown": false, "handwritten": false, - "parseContext": null, + "parseContext": "Expression" "type": "socketStart", "emptyString": "" }, @@ -1144,7 +1144,7 @@ asyncTest 'JS beginner mode loops', -> { "dropdown": false, "handwritten": false, - "parseContext": null, + "parseContext": "Expression", "type": "socketStart", "emptyString": "" }, From 883ec5e8096799043fddedd89ab0649c2f34cb96 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 16:40:41 -0400 Subject: [PATCH 49/60] Fix tests for phantomjs --- Gruntfile.coffee | 4 ++++ package.json | 1 + test/data/c-freeze-populator.js | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 34031b94..41fd8abc 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -2,6 +2,7 @@ browserify = require 'browserify' coffeeify = require 'coffeeify' watchify = require 'watchify' + livereload = require 'tiny-lr' path = require 'path' @@ -225,4 +226,7 @@ module.exports = (grunt) -> } } + + grunt.loadNpmTasks 'grunt-keepalive' grunt.registerTask 'testserver', ['connect:testserver', 'watchify'] + grunt.registerTask 'serve', ['connect:testserver', 'keepalive'] diff --git a/package.json b/package.json index 937c44c2..e082fe43 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "grunt-contrib-uglify": "latest", "grunt-contrib-watch": "latest", "grunt-docco": "latest", + "grunt-keepalive": "^1.0.0", "grunt-mocha-spawn": "latest", "grunt-mocha-test": "^0.12.7", "mocha": "^2.2.5", diff --git a/test/data/c-freeze-populator.js b/test/data/c-freeze-populator.js index 4c420415..bdc0467e 100644 --- a/test/data/c-freeze-populator.js +++ b/test/data/c-freeze-populator.js @@ -462,12 +462,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -923,12 +923,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -1018,12 +1018,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -1740,12 +1740,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -1835,12 +1835,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -2823,12 +2823,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], @@ -3077,12 +3077,12 @@ window.FREEZE_DATA.freezeTest = [ "buttons": [ { "border": false, - "glyph": "◀", + "glyph": "\u25C0", "key": "subtract-button" }, { "border": false, - "glyph": "▶", + "glyph": "\u25B6", "key": "add-button" } ], From 008f00dc6df2ba75942d9919c8925cb807a45b6b Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Tue, 19 Jul 2016 18:24:26 -0400 Subject: [PATCH 50/60] Fix for tests --- src/controller.coffee | 2 +- src/draw.coffee | 2 -- src/languages/c.coffee | 2 +- src/languages/coffee.coffee | 1 + src/view.coffee | 11 +++++++---- test/src/uitest.coffee | 6 +++--- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/controller.coffee b/src/controller.coffee index 28d7d2fc..204a2dcc 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -1080,7 +1080,7 @@ Editor::spliceOut = (node, container = null) -> if parent?.type is 'socket' and node.start.type is 'blockStart' for socket, i in @session.rememberedSockets if @fromCrossDocumentLocation(socket.socket) is parent - @session.rememberedSockets.splice i, 0 + @session.rememberedSockets.splice i, 1 @populateSocket parent, socket.text break diff --git a/src/draw.coffee b/src/draw.coffee index d7090123..0f42ed05 100644 --- a/src/draw.coffee +++ b/src/draw.coffee @@ -471,8 +471,6 @@ exports.Draw = class Draw getLightBevelPath: -> @_clearCache(); @_lightBevelPath getDarkBevelPath: -> @_clearCache() - unless @_darkBevelPath? - debugger return @_darkBevelPath # TODO unhackify diff --git a/src/languages/c.coffee b/src/languages/c.coffee index c9f84c8c..5d23c742 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -154,7 +154,7 @@ RULES = { ) if node.children.length is 3 return {type: 'block', buttons: ADD_BUTTON} - else if opts.knownFunctions? and node.children[0].children[0].children[0].data.text of opts.knownFunctions + else if opts.knownFunctions? and node.children[0].children[0].children[0].data?.text of opts.knownFunctions minimum = opts.knownFunctions[node.children[0].children[0].children[0].data.text].minArgs nargs = 0 param = node.children[2] diff --git a/src/languages/coffee.coffee b/src/languages/coffee.coffee index dafbe3aa..e45d8585 100644 --- a/src/languages/coffee.coffee +++ b/src/languages/coffee.coffee @@ -154,6 +154,7 @@ PRECEDENCES = { 'While': -4 'Expression' : 0 'Call': 0 + 'Callee': 100 'LastCallArg': -1 } diff --git a/src/view.coffee b/src/view.coffee index 766d28bb..d0fbcec2 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1385,7 +1385,7 @@ exports.View = class View # *Seventh pass variables* # computeDropAreas # each one is a @view.draw.Path (or null) - @dropArea = null + @dropPoint = null @highlightArea = new @view.draw.Path([], false, { fillColor: '#FF0' strokeColor: '#FF0' @@ -1976,7 +1976,7 @@ exports.View = class View # By default, we will not have a # drop area (not be droppable). computeOwnDropArea: -> - @dropArea = null + @dropPoint = null if @highlightArea? @elements = @elements.filter (x) -> x isnt @highlightArea @highlightArea.destroy() @@ -2015,7 +2015,10 @@ exports.View = class View return not (@model.shape in [helper.MOSTLY_VALUE, helper.VALUE_ONLY]) computeOwnDropArea: -> - return unless @model.parent?.type in ['indent', 'document'] + unless @model.parent?.type in ['indent', 'document'] + @dropPoint = null + return + # Our drop area is a puzzle-piece shaped path # of height opts.highlightAreaHeight and width # equal to our last line width, @@ -2204,7 +2207,7 @@ exports.View = class View # things. computeOwnDropArea: -> if @model.start.next.type is 'blockStart' - @dropArea = null + @dropPoint = null @highlightArea.deactivate() else @dropPoint = @bounds[0].upperLeftCorner() diff --git a/test/src/uitest.coffee b/test/src/uitest.coffee index 898ecf79..8446169f 100644 --- a/test/src/uitest.coffee +++ b/test/src/uitest.coffee @@ -1182,9 +1182,9 @@ asyncTest 'Controller: ANTLR random drag reparse test', -> cb = -> if count is 0 start() - else + else if count % 10 is 0 ok editor.session.mode.parse(editor.getValue()), 'Still in a parseable state' - setTimeout (-> tick count - 1), 0 + setTimeout (-> tick count - 1), 0 if rng() > 0.1 op = getRandomDragOp(editor, rng) @@ -1193,4 +1193,4 @@ asyncTest 'Controller: ANTLR random drag reparse test', -> op = getRandomTextOp(editor, rng) performTextOperation editor, op, cb - tick 50 + tick 100 From 7f6bed095835f0fc3322f58d7c308b543ec60cd3 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 20 Jul 2016 10:05:53 -0400 Subject: [PATCH 51/60] Add some additional tests exercising the new rules --- test/src/ctest.coffee | 78 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/test/src/ctest.coffee b/test/src/ctest.coffee index 8ffad59a..61a35356 100644 --- a/test/src/ctest.coffee +++ b/test/src/ctest.coffee @@ -236,6 +236,7 @@ asyncTest 'Controller: ANTLR paren wrap rules', -> int y = 1 * 2; int x = 1 + 2; int a = 1 + 2 * 3; + printf("Hello"); } ''' @@ -257,8 +258,13 @@ asyncTest 'Controller: ANTLR paren wrap rules', -> int y = 1 * (1 + 2); int x = __0_droplet__; int a = 1 + 2 * 3; + printf("Hello"); }\n ''', 'Paren-wrapped + block dropping into * block' + + equal editor.session.tree.getFromTextLocation({ + row: 1, col: 14, type: 'block' + }).parseContext, 'primaryExpression', 'Changed parse context when adding parens' ), (-> pickUpLocation editor, 0, { row: 1 @@ -277,8 +283,80 @@ asyncTest 'Controller: ANTLR paren wrap rules', -> int y = __0_droplet__; int x = __0_droplet__; int a = 1 * (1 + 2) + 2 * 3; + printf("Hello"); }\n ''', 'Did not paren-wrap * block dropping into + block' + ), (-> + pickUpLocation editor, 0, { + row: 3 + col: 14 + type: 'block' + } + dropLocation editor, 0, { + row: 2 + col: 10 + type: 'socket' + } + ), (-> + equal editor.getValue(), ''' + int main() { + int y = __0_droplet__; + int x = 1 + 2; + int a = 1 * 2 + 2 * 3; + printf("Hello"); + }\n + ''', 'Un-paren-wrapped when dropping into place where parens are unnecessary' + + equal editor.session.tree.getFromTextLocation({ + row: 2, col: 10, type: 'block' + }).parseContext, 'additiveExpression', 'Changed parse context when removing parens' + ), (-> + pickUpLocation editor, 0, { + row: 4 + col: 2 + type: 'block' + } + dropLocation editor, 0, { + row: 1 + col: 10 + type: 'socket' + } + ), (-> + equal editor.getValue(), ''' + int main() { + int y = printf("Hello"); + int x = 1 + 2; + int a = 1 * 2 + 2 * 3; + }\n + ''', 'Removed semicolon' + + equal editor.session.tree.getFromTextLocation({ + row: 1, col: 10, type: 'block' + }).parseContext, 'postfixExpression', 'Changed parse context when removing semicolon' + ), (-> + pickUpLocation editor, 0, { + row: 1 + col: 10 + type: 'block' + } + dropLocation editor, 0, { + row: 3 + col: 2 + type: 'block' + } + ), (-> + equal editor.getValue(), ''' + int main() { + int y = __0_droplet__; + int x = 1 + 2; + int a = 1 * 2 + 2 * 3; + printf("Hello"); + }\n + ''', 'Added semicolon back' + + equal editor.session.tree.getFromTextLocation({ + row: 4, col: 2, type: 'block' + }).parseContext, 'expressionStatement', 'Changed parse context when adding semicolon' start() ) From 6dee597f64695d8190b6678bec43da2a9ffdd7b3 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 20 Jul 2016 10:19:52 -0400 Subject: [PATCH 52/60] Fix visual bug with buttons disappearing sometimes --- src/view.coffee | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/view.coffee b/src/view.coffee index d0fbcec2..ec466021 100644 --- a/src/view.coffee +++ b/src/view.coffee @@ -1394,6 +1394,7 @@ exports.View = class View @highlightArea.deactivate() @buttonGroups = {} + @buttonTexts = {} @buttonPaths = {} @buttonRects = {} @@ -1418,21 +1419,20 @@ exports.View = class View @buttonGroups[key].style = {} - textElement = new @view.draw.Text(new @view.draw.Point( + @buttonTexts[key] = new @view.draw.Text(new @view.draw.Point( (@view.opts.buttonWidth - @view.draw.measureCtx.measureText(glyph).width)/ 2, (@view.opts.buttonHeight - @view.opts.textHeight) / 2 ), glyph) @buttonPaths[key].setParent @buttonGroups[key] - textElement.setParent @buttonGroups[key] + @buttonTexts[key].setParent @buttonGroups[key] @buttonGroups[key].setParent @group @elements.push @buttonGroups[key] @activeElements.push @buttonPaths[key] - @activeElements.push textElement + @activeElements.push @buttonTexts[key] @activeElements.push @buttonGroups[key] - @elements.push @group @elements.push @path @elements.push @highlightArea @@ -1961,6 +1961,10 @@ exports.View = class View @buttonPaths[key].update() @buttonGroups[key].update() + for element in [@buttonPaths[key], @buttonGroups[key], @buttonTexts[key]] + unless element in @activeElements # TODO unlikely but might be performance chokehold? + @activeElements.push element # Possibly replace activeElements with a more set-like structure. + # Unset all the things we changed @path.style.fillColor = oldFill @path.style.strokeColor = oldStroke From 6d26d5988fc6d4b22bd28625554cbc78c7fad9ca Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Wed, 20 Jul 2016 11:12:25 -0400 Subject: [PATCH 53/60] Don't put an add button on struct declarations --- src/languages/c.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/languages/c.coffee b/src/languages/c.coffee index 5d23c742..731f4884 100644 --- a/src/languages/c.coffee +++ b/src/languages/c.coffee @@ -69,6 +69,7 @@ RULES = { 'structDeclaration': 'parens', # Skips + 'structDeclaratorList': 'skip', 'blockItemList': 'skip', 'macroParamList': 'skip', 'compilationUnit': 'skip', @@ -96,7 +97,7 @@ RULES = { 'declaration': (node) -> if node.children.length is 3 and node.children[1].children.length is 3 return {type: 'block', buttons: BOTH_BUTTON} - else if node.children.length >= 2 + else if node.children.length is 3 return {type: 'block', buttons: ADD_BUTTON} else return 'block' From 4a84d0f7c7255ade679924d73d23ac435ef915fc Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 20 Jul 2016 19:37:51 -0400 Subject: [PATCH 54/60] python mode basic tests; demo page minor bug fixed --- Gruntfile.coffee | 1 + example/example-python.html | 16 +++---- test/pytest.html | 27 +++++++++++ test/src/pytest.coffee | 92 +++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 test/pytest.html create mode 100644 test/src/pytest.coffee diff --git a/Gruntfile.coffee b/Gruntfile.coffee index d51a29e8..88f91ce5 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -99,6 +99,7 @@ module.exports = (grunt) -> 'test/js/jstest.js': ['test/src/jstest.coffee'] 'test/js/cstest.js': ['test/src/cstest.coffee'] 'test/js/htmltest.js': ['test/src/htmltest.coffee'] + 'test/js/pytest.js': ['test/src/pytest.coffee'] options: transform: ['coffeeify'] browserifyOptions: diff --git a/example/example-python.html b/example/example-python.html index 33babd80..ddec1ea0 100644 --- a/example/example-python.html +++ b/example/example-python.html @@ -6,7 +6,7 @@ + +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + diff --git a/test/src/pytest.coffee b/test/src/pytest.coffee new file mode 100644 index 00000000..b3340430 --- /dev/null +++ b/test/src/pytest.coffee @@ -0,0 +1,92 @@ +helper = require '../../src/helper.coffee' +Python = require '../../src/languages/python.coffee' + +asyncTest 'Python basic parsing', -> + customPy = new Python({ + functions: { + 'print': { + value: true + } + } + }) + + customSerialization = customPy.parse( + ''' + print 'hello' + ''' + ).serialize() + + expectedSerialization = ''' + print 'hello'''' + + strictEqual( + helper.xmlPrettyPrint(customSerialization), + helper.xmlPrettyPrint(expectedSerialization), + 'Dotted known functions work' + ) + + start() + +asyncTest 'Py indent', -> + customPy = new Python({ + functions: {} + }) + code = 'for i in range(0, 10):\n continue' + customSerialization = customPy.parse('for i in range(0, 10):\n continue') + stringifiedPy = customSerialization.stringify() + strictEqual(code, stringifiedPy) + start() + +asyncTest 'Py for loop', -> + customPy = new Python({ + functions: {} + }) + + customSerialization = customPy.parse('for i in range(0, 10):\n continue').serialize() + + expectedSerialization = '''for i in range(0, 10): +continue''' + + strictEqual( + helper.xmlPrettyPrint(customSerialization), + helper.xmlPrettyPrint(expectedSerialization) + ) + start() + + From 7a1425652ab2af678513280aed8361a81b6c41a2 Mon Sep 17 00:00:00 2001 From: David Anthony Bau Date: Thu, 21 Jul 2016 10:26:06 -0400 Subject: [PATCH 55/60] Allow type changing during block reparsing --- src/controller.coffee | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/controller.coffee b/src/controller.coffee index 204a2dcc..1eec2368 100644 --- a/src/controller.coffee +++ b/src/controller.coffee @@ -2590,10 +2590,16 @@ Editor::populateSocket = (socket, string) -> @spliceIn new model.List(first, last), socket.start Editor::populateBlock = (block, string) -> + if block.type is 'block' + context = block.parent.indentContext ? block.parent.parseContext ? block.parseContext + else + context = block.parseContext + newBlock = @session.mode.parse(string, { - context: block.parseContext + context: context wrapAtRoot: false }).start.next.container + if newBlock # Find the first token before the block # that will still be around after the From 012eeeeb51914994cbc66ace44400775bbc5ed0e Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Mon, 25 Jul 2016 14:37:59 -0400 Subject: [PATCH 56/60] typo fixed --- src/languages/python.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index f7cb7e2c..b861b512 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -83,7 +83,7 @@ insertButton = (opts, node) -> else return null -handelButton = (text, button, oldBlocks) -> +handleButton = (text, button, oldBlocks) -> checkElif = (node) -> res = 'init' if node.type is 'if_stmt' @@ -165,7 +165,7 @@ config = { DROPDOWN_CALLBACK: getDropdown COLOR_CALLBACK: getColor BUTTON_CALLBACK: insertButton - HANDLE_BUTTON_CALLBACK: handelButton + HANDLE_BUTTON_CALLBACK: handleButton COLOR_RULES: [ ['term', 'value'], From 8db958a4f2af4792c450830997c244d23e4e8a37 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Mon, 25 Jul 2016 15:01:22 -0400 Subject: [PATCH 57/60] tweaks to the treewalker (fixes the C mode unit tests) --- src/treewalk.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 5b891f32..35dca3fe 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -118,7 +118,7 @@ exports.createTreewalkParser = (parse, config, root) -> color: @getColor node, rules classes: padRules(wrapRules ? rules).concat(@getShape(node, rules)) parseContext: rules[0] #(if wrap? then wrap.type else rules[0]) - buttons: config.BUTTON_CALLBACK(@opts, node) ? null + buttons: if config.BUTTON_CALLBACK then config.BUTTON_CALLBACK(@opts, node) ? null else null when 'parens' # Parens are assumed to wrap the only child that has children @@ -183,8 +183,8 @@ exports.createTreewalkParser = (parse, config, root) -> else unless i is 0 end = child.bounds.start - # @lines[end.line] was breaking in python mode (index out of range) - if @lines[end.line-1][...end.column].trim().length is 0 + # For C mode, etc., end.line may be +1 longer than Python mode, etc., including the ending bracket + if end.line < @lines.length and @lines[end.line][...end.column].trim().length is 0 end.line -= 1 end.column = @lines[end.line].length From f3941bd29857030ced45be4ad4738cab8154c954 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Sun, 7 Aug 2016 22:36:37 -0400 Subject: [PATCH 58/60] adapting python mode to the container-buttons branch --- src/languages/python.coffee | 108 +++++++++++++++++++++--------------- src/treewalk.coffee | 3 +- 2 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index b861b512..7b8063f2 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -17,6 +17,14 @@ PYTHON_BUILTIN = ['type', 'object', 'hashCount', 'none', 'NotImplemented', 'pyCh PYTHON_KEYWORDS = PYTHON_KEYWORDS.concat(PYTHON_BUILTIN) PYTHON_KEYWORDS = PYTHON_KEYWORDS.filter((v, i) -> return PYTHON_KEYWORDS.indexOf(v) == i) # remove possible duplicates +ADD_BUTTON_VERT = [ + { + key: 'add-button' + glyph: '\u25BC' + border: false + } +] + # PARSER SECTION parse = (context, text) -> result = transform skulpt.parser.parse('file.py', text, context), text.split('\n') @@ -50,7 +58,7 @@ getFunctionName = (node) -> siblingNode = node.children[0].children?[0] if siblingNode?.type in ['T_KEYWORD', 'T_NAME'] - return siblingNode.meta.value + return siblingNode.data.text if node.parent? then getFunctionName(node.parent) @@ -83,28 +91,6 @@ insertButton = (opts, node) -> else return null -handleButton = (text, button, oldBlocks) -> - checkElif = (node) -> - res = 'init' - if node.type is 'if_stmt' - node.children?.forEach((c) -> if c.type is 'T_KEYWORD' then res = c.meta.value) - else - node.children?.forEach((c) -> res = checkElif(c)) - return res - - if button is 'add-button' and 'if_stmt' in oldBlocks.classes - node = parse({}, text).children[0] - elif = checkElif(node) - - if elif is 'if' or elif is 'elif' - text += '''\nelse:\n print \'hi\'''' - else if elif is 'else' - text = text.replace('else:', 'elif a == b:') - text += '''\nelse:\n print \'hi\'''' - - return text - - transform = (node, lines, parent = null) -> type = skulpt.tables.ParseTables.number2symbol[node.type] ? skulpt.Tokenizer.tokenNames[node.type] ? node.type @@ -116,8 +102,8 @@ transform = (node, lines, parent = null) -> type: type bounds: getBounds(node, lines) parent: parent - meta: { - value: node.value ? null + data: { + text: node.value ? null } # language-specific meta-data } @@ -156,7 +142,12 @@ config = { # Sockets 'T_NAME': 'socket', 'T_NUMBER': 'socket', - 'T_STRING': 'socket' + 'T_STRING': 'socket', + + 'if_stmt': (node) -> + if node.children[0].data.text is 'if' + return {type: 'block', buttons: ADD_BUTTON_VERT} + return 'block' } PAREN_RULES: {} @@ -165,30 +156,55 @@ config = { DROPDOWN_CALLBACK: getDropdown COLOR_CALLBACK: getColor BUTTON_CALLBACK: insertButton - HANDLE_BUTTON_CALLBACK: handleButton - - COLOR_RULES: [ - ['term', 'value'], - ['funcdef', 'control'], - ['for_stmt', 'control'], - ['while_stmt', 'control'], - ['with_stmt', 'control'], - ['if_stmt', 'control'], - ['try_stmt', 'control'], - ['import_stmt', 'command'], - ['print_stmt', 'command'], - ['expr_stmt', 'command'], - ['return_stmt', 'return'], - ['testlist', 'value'], - ['comparison', 'value'], - ['test', 'value'], - ['expr', 'value'] - ] + + COLOR_RULES: { + 'term': 'value', + 'funcdef': 'control', + 'for_stmt': 'control', + 'while_stmt': 'control', + 'with_stmt': 'control', + 'if_stmt': 'control', + 'try_stmt': 'control', + 'import_stmt': 'command', + 'print_stmt': 'command', + 'expr_stmt': 'command', + 'return_stmt': 'return', + 'testlist': 'value', + 'comparison': 'value', + 'test': 'value', + 'expr': 'value' + } + SHAPE_RULES: [] } config.SHOULD_SOCKET = (opts, node) -> - return node.meta.value not in Object.keys(opts.functions) or getArgNum(node) isnt null + return node.data.text not in Object.keys(opts.functions) or getArgNum(node) isnt null + +checkElif = (node) -> + res = 'init' + if node.type is 'if_stmt' + node.children?.forEach((c) -> if c.type is 'T_KEYWORD' then res = c.data.text) + else + node.children?.forEach((c) -> res = checkElif(c)) + return res + +config.handleButton = (str, type, block) -> + blockType = block.nodeContext?.type ? block.parseContext + + if type is 'add-button' + if blockType is 'if_stmt' + node = parse({}, str).children[0] + elif = checkElif(node) + + if elif is 'if' or elif is 'elif' + str += '''\nelse:\n print \'hi\'''' + else if elif is 'else' + str = str.replace('else:', 'elif a == b:') + str += '''\nelse:\n print \'hi\'''' + return str + else + return str result = treewalk.createTreewalkParser parse, config result.canParse = (node) -> diff --git a/src/treewalk.coffee b/src/treewalk.coffee index 396c1c70..ce1696ca 100644 --- a/src/treewalk.coffee +++ b/src/treewalk.coffee @@ -70,6 +70,7 @@ exports.createTreewalkParser = (parse, config, root) -> getColor: (node) -> color = config.COLOR_CALLBACK?(@opts, node) + if color? return color @@ -263,7 +264,7 @@ exports.createTreewalkParser = (parse, config, root) -> bounds: node.bounds depth: depth parseContext: rules[0] - dropdown: config.DROPDOWN_CALLBACK?(@opts, node) ? null + dropdown: config.DROPDOWN_CALLBACK?(@opts, node) ? null if config.EMPTY_STRINGS? and not @opts.preserveEmpty and helper.clipLines(@lines, node.bounds.start, node.bounds.end) is config.empty @flagToRemove node.bounds, depth + 1 From e0d08ffb12170d5085b94f936842d1a392389493 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 17 Aug 2016 19:23:51 -0400 Subject: [PATCH 59/60] python mode: tests fixed, subtract button, pass stmt not working yet --- src/languages/python.coffee | 49 +++++++++++++++---- test/src/pytest.coffee | 97 +++++++++++++++---------------------- 2 files changed, 77 insertions(+), 69 deletions(-) diff --git a/src/languages/python.coffee b/src/languages/python.coffee index 7b8063f2..5ac93cfa 100644 --- a/src/languages/python.coffee +++ b/src/languages/python.coffee @@ -25,6 +25,19 @@ ADD_BUTTON_VERT = [ } ] +BOTH_BUTTON_VERT = [ + { + key: 'subtract-button' + glyph: '\u25B2' + border: false + } + { + key: 'add-button' + glyph: '\u25BC' + border: false + } +] + # PARSER SECTION parse = (context, text) -> result = transform skulpt.parser.parse('file.py', text, context), text.split('\n') @@ -146,7 +159,7 @@ config = { 'if_stmt': (node) -> if node.children[0].data.text is 'if' - return {type: 'block', buttons: ADD_BUTTON_VERT} + return {type: 'block', buttons: BOTH_BUTTON_VERT} return 'block' } @@ -168,6 +181,7 @@ config = { 'import_stmt': 'command', 'print_stmt': 'command', 'expr_stmt': 'command', + 'pass_stmt': 'command', 'return_stmt': 'return', 'testlist': 'value', 'comparison': 'value', @@ -175,7 +189,13 @@ config = { 'expr': 'value' } - SHAPE_RULES: [] + SHAPE_RULES: [], + +# empty: '__0_droplet__', +# EMPTY_STRINGS: ['pass_stmt'] # put "pass" equivalent token here + EMPTY_STRINGS: { + 'stmt': 'pass' + } } config.SHOULD_SOCKET = (opts, node) -> @@ -191,20 +211,29 @@ checkElif = (node) -> config.handleButton = (str, type, block) -> blockType = block.nodeContext?.type ? block.parseContext + if blockType is 'if_stmt' + node = parse({}, str).children[0] + elif = checkElif(node) - if type is 'add-button' - if blockType is 'if_stmt' - node = parse({}, str).children[0] - elif = checkElif(node) + console.log node + if type is 'add-button' if elif is 'if' or elif is 'elif' - str += '''\nelse:\n print \'hi\'''' + str += '''\nelse:\n pass''' else if elif is 'else' str = str.replace('else:', 'elif a == b:') - str += '''\nelse:\n print \'hi\'''' + str += '''\nelse:\n pass''' return str - else - return str + else if type is 'subtract-button' + if elif is 'if' or elif is 'elif' + str = str.substr(0, str.lastIndexOf('\nelif ')) + else if elif is 'else' + str = str.substr(0, str.indexOf('\nelse:')) + return str + else + return str + + return str result = treewalk.createTreewalkParser parse, config result.canParse = (node) -> diff --git a/test/src/pytest.coffee b/test/src/pytest.coffee index b3340430..0be139bb 100644 --- a/test/src/pytest.coffee +++ b/test/src/pytest.coffee @@ -2,7 +2,7 @@ helper = require '../../src/helper.coffee' Python = require '../../src/languages/python.coffee' asyncTest 'Python basic parsing', -> - customPy = new Python({ + py = new Python({ functions: { 'print': { value: true @@ -10,83 +10,62 @@ asyncTest 'Python basic parsing', -> } }) - customSerialization = customPy.parse( + serialRes = py.parse( ''' print 'hello' ''' ).serialize() - expectedSerialization = ''' - print 'hello'''' - - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization), - 'Dotted known functions work' - ) + # why is "indentContext":undefined required here? + serialComp = [{"type":"documentStart","indentContext":undefined, + }, + {"type":"blockStart","color":"command","shape":0,"parseContext":"print_stmt","nodeContext":{"type":"print_stmt","prefix":"print ","suffix":""}}, + "print ", + {"type":"socketStart","emptyString":"__0_droplet__","parseContext":"test","handwritten":false,"dropdown":false},"'hello'",{"type":"socketEnd"}, + {"type":"blockEnd"}, + {"type":"documentEnd"}] + deepEqual serialRes, serialComp, 'Basic parsing should work' start() asyncTest 'Py indent', -> - customPy = new Python({ + py = new Python({ functions: {} }) code = 'for i in range(0, 10):\n continue' - customSerialization = customPy.parse('for i in range(0, 10):\n continue') - stringifiedPy = customSerialization.stringify() - strictEqual(code, stringifiedPy) + result = py.parse(code) + stringifiedRes = result.stringify() + strictEqual(code, stringifiedRes) start() asyncTest 'Py for loop', -> - customPy = new Python({ + py = new Python({ functions: {} }) - customSerialization = customPy.parse('for i in range(0, 10):\n continue').serialize() - - expectedSerialization = '''for i in range(0, 10): -continue''' + serialRes = py.parse('for i in range(0, 10):\n continue').serialize() + serialComp = [{"type":"documentStart","indentContext":undefined}, + {"type":"blockStart","color":"control","shape":0,"parseContext":"for_stmt","nodeContext":{"type":"for_stmt","prefix":"for ","suffix":""}}, + "for ", + {"type":"socketStart","emptyString":"__0_droplet__","parseContext":"exprlist","handwritten":false,"dropdown":false},"i",{"type":"socketEnd"}, + " in ", + {"type":"socketStart","emptyString":"__0_droplet__","parseContext":"testlist","handwritten":false,"dropdown":false}, + {"type":"blockStart","color":"comment","shape":0,"parseContext":"power","nodeContext":{"type":"power","prefix":"range(","suffix":")"}}, + "range(", + {"type":"socketStart","emptyString":"__0_droplet__","parseContext":"argument","handwritten":false,"dropdown":false},"0",{"type":"socketEnd"}, + ", ", + {"type":"socketStart","emptyString":"__0_droplet__","parseContext":"argument","handwritten":false,"dropdown":false},"10",{"type":"socketEnd"} + ,")", + {"type":"blockEnd"}, + {"type":"socketEnd"},":", + {"type":"indentStart","prefix":" ","indentContext":"small_stmt"},{"type":"newline","specialIndent":undefined, # ??? + }, + {"type":"blockStart","color":0,"shape":1,"parseContext":0,"nodeContext":{"type":"__comment__","prefix":"","suffix":""}}, + {"type":"socketStart","emptyString":"","parseContext":null,"handwritten":true,"dropdown":false},"continue",{"type":"socketEnd"},{"type":"blockEnd"},{"type":"indentEnd"}, + {"type":"blockEnd"}, + {"type":"documentEnd"}] - strictEqual( - helper.xmlPrettyPrint(customSerialization), - helper.xmlPrettyPrint(expectedSerialization) - ) + deepEqual serialRes, serialComp, 'For loop block and indent should work' start() From ce34e2d05580b729c0420153013681f7ba504f68 Mon Sep 17 00:00:00 2001 From: Takahiko Tsuchiya Date: Wed, 17 Aug 2016 19:29:30 -0400 Subject: [PATCH 60/60] dropdown menu arrow icon color fixed --- css/droplet.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/css/droplet.css b/css/droplet.css index 3433f0a4..211c97e2 100644 --- a/css/droplet.css +++ b/css/droplet.css @@ -372,11 +372,15 @@ text { cursor: -moz-grab; cursor: grab; } -.droplet-dropdown-arrow, .droplet-button-path { +.droplet-button-path { fill: #FFF; opacity: 0; cursor: pointer; } +.droplet-dropdown-arrow { + /*fill: #FFF;*/ + cursor: pointer; +} .droplet-button-path:hover { fill: #FFF; opacity: 0.5;