UNPKG

babel-bridge

Version:

a 'runtime' parsing expression grammar parser

127 lines (99 loc) 4.28 kB
{array, defineModule, log, merge, escapeJavascriptString, find} = require 'art-standard-lib' {Node} = require '../Nodes' defineModule module, -> class IndentBlocks blockStartRegExp = /\n(?: *\n)*( +)(?=$|[^ \n])/y toEolContent = /(\ *)((?:\ *[^ \n]+)+)\ */y blockLinesRegExp = (indent) -> /// ( (?:\s*\n) (?:#{indent}\ *[^\n\ ][^\n]*) )+ ///y ### TODO: for matchBlock and matchToEolAndBlock We also need a source-offset mapper from the new source back to the old-source. I think the map should just be part of the returned object ### @matchBlock: matchBlock = (source, sourceOffset, returnRawMatch = false) -> blockStartRegExp.lastIndex = sourceOffset if match = blockStartRegExp.exec source [__, indent] = match length = indent.length linesRegExp = blockLinesRegExp indent linesRegExp.lastIndex = sourceOffset [rawSubsource] = linesRegExp.exec source replaceRegExp = ///(?:^\n#{indent})|(\n)(?:#{indent})///g replaceWith = "$1" # generated on demand, but then cached for future sourceMap calls. subsourceToParentSourceMap = null subsource = if returnRawMatch then rawSubsource else rawSubsource.replace replaceRegExp, "$1" matchLength: rawSubsource.length subsource: subsource sourceMap: if returnRawMatch (suboffset) -> suboffset + sourceOffset else (suboffset) -> subsourceToParentSourceMap ||= computeSubsourceToParentSourceMap sourceOffset, replaceRegExp, indent, rawSubsource bestMapEntry = find subsourceToParentSourceMap, (entry) -> entry if suboffset < entry.subsourceEndOffset suboffset + bestMapEntry.toSourceDelta computeSubsourceToParentSourceMap = (sourceBaseOffset, replaceRegExp, indent, rawSubsource)-> indentLength = indent.length indentWithNewLineLength = indentLength + 1 indexes = [] sourceOffset = toSourceDelta = sourceBaseOffset subsourceOffset = subsourceEndOffset = 0 while match = replaceRegExp.exec rawSubsource matchLength = match[0].length keptLength = match[1]?.length || 0 removedLength = matchLength - keptLength sourceEndOffset = match.index + sourceBaseOffset + matchLength subsourceEndOffset += sourceEndOffset - sourceOffset - removedLength indexes.push { keptLength removedLength sourceOffset subsourceOffset toSourceDelta sourceEndOffset subsourceEndOffset } toSourceDelta += removedLength sourceOffset = sourceEndOffset subsourceOffset = subsourceEndOffset sourceEndOffset = sourceBaseOffset + rawSubsource.length subsourceEndOffset = sourceEndOffset - sourceOffset + sourceOffset indexes.push { sourceOffset subsourceOffset toSourceDelta sourceEndOffset subsourceEndOffset } indexes # I think this is actually matchToEolOrBlock - one or the other @matchToEolAndBlock: matchToEolAndBlock = (source, offset) -> toEolContent.lastIndex = offset if eolMatch = toEolContent.exec source [sourceMatched, spaces] = eolMatch matchLength = sourceMatched.length if blockMatch = matchBlock source, offset + matchLength, true matchLength += blockMatch.matchLength subsource: source.slice offset + spaces.length, offset + matchLength sourceMap: (suboffset) -> offset + spaces.length + suboffset matchLength: matchLength else matchBlock source, offset @getParseFunction: (matcher, subparseOptions) -> parse: (parentNode) -> {nextOffset:offset, source} = parentNode if block = matcher source, offset {subsource, matchLength, sourceMap} = block parentNode.subparse subsource, merge subparseOptions, originalOffset: offset originalMatchLength: matchLength sourceMap: sourceMap @getPropsToSubparseBlock: (subparseOptions = {}) => @getParseFunction @matchBlock, subparseOptions @getPropsToSubparseToEolAndBlock: (subparseOptions = {}) => @getParseFunction @matchToEolAndBlock, subparseOptions