<s> import re <EOL> INDENT_MODE = '<STR_LIT>' <EOL> PAREN_MODE = '<STR_LIT>' <EOL> BACKSLASH = '<STR_LIT:\\>' <EOL> BLANK_SPACE = '<STR_LIT:U+0020>' <EOL> DOUBLE_SPACE = '<STR_LIT:U+0020>' <EOL> DOUBLE_QUOTE = '<STR_LIT:">' <EOL> NEWLINE = '<STR_LIT:\n>' <EOL> SEMICOLON = '<STR_LIT:;>' <EOL> TAB = '<STR_LIT:\t>' <EOL> LINE_ENDING_REGEX = re . compile ( r"<STR_LIT>" ) <EOL> CLOSE_PARENS = frozenset ( [ '<STR_LIT:}>' , '<STR_LIT:)>' , '<STR_LIT:]>' ] ) <EOL> PARENS = { <EOL> '<STR_LIT:{>' : '<STR_LIT:}>' , <EOL> '<STR_LIT:}>' : '<STR_LIT:{>' , <EOL> '<STR_LIT:[>' : '<STR_LIT:]>' , <EOL> '<STR_LIT:]>' : '<STR_LIT:[>' , <EOL> '<STR_LIT:(>' : '<STR_LIT:)>' , <EOL> '<STR_LIT:)>' : '<STR_LIT:(>' , <EOL> } <EOL> def initialResult ( text , options , mode ) : <EOL> """<STR_LIT>""" <EOL> result = { <EOL> '<STR_LIT>' : mode , <EOL> '<STR_LIT>' : text , <EOL> '<STR_LIT>' : text . split ( NEWLINE ) , <EOL> '<STR_LIT>' : [ ] , <EOL> '<STR_LIT>' : - <NUM_LIT:1> , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:x>' : <NUM_LIT:0> , <EOL> '<STR_LIT>' : [ ] , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : [ ] , <EOL> } , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT>' : False , <EOL> '<STR_LIT:success>' : False , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT>' : <NUM_LIT:0> , <EOL> '<STR_LIT:error>' : { <EOL> '<STR_LIT:name>' : None , <EOL> '<STR_LIT:message>' : None , <EOL> '<STR_LIT>' : None , <EOL> '<STR_LIT:x>' : None , <EOL> } , <EOL> '<STR_LIT>' : { } , <EOL> } <EOL> if isinstance ( options , dict ) : <EOL> if '<STR_LIT>' in options : <EOL> result [ '<STR_LIT>' ] = options [ '<STR_LIT>' ] <EOL> if '<STR_LIT>' in options : <EOL> result [ '<STR_LIT>' ] = options [ '<STR_LIT>' ] <EOL> if '<STR_LIT>' in options : <EOL> result [ '<STR_LIT>' ] = options [ '<STR_LIT>' ] <EOL> return result <EOL> ERROR_QUOTE_DANGER = "<STR_LIT>" <EOL> ERROR_EOL_BACKSLASH = "<STR_LIT>" <EOL> ERROR_UNCLOSED_QUOTE = "<STR_LIT>" <EOL> ERROR_UNCLOSED_PAREN = "<STR_LIT>" <EOL> ERROR_UNHANDLED = "<STR_LIT>" <EOL> errorMessages = { } <EOL> errorMessages [ ERROR_QUOTE_DANGER ] = "<STR_LIT>" <EOL> errorMessages [ ERROR_EOL_BACKSLASH ] = "<STR_LIT>" <EOL> errorMessages [ ERROR_UNCLOSED_QUOTE ] = "<STR_LIT>" <EOL> errorMessages [ ERROR_UNCLOSED_PAREN ] = "<STR_LIT>" <EOL> def cacheErrorPos ( result , name , lineNo , x ) : <EOL> result [ '<STR_LIT>' ] [ name ] = { '<STR_LIT>' : lineNo , '<STR_LIT:x>' : x } <EOL> class ParinferError ( Exception ) : <EOL> pass <EOL> def error ( result , name , lineNo , x ) : <EOL> if lineNo is None : <EOL> lineNo = result [ '<STR_LIT>' ] [ name ] [ '<STR_LIT>' ] <EOL> if x is None : <EOL> x = result [ '<STR_LIT>' ] [ name ] [ '<STR_LIT:x>' ] <EOL> return { <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT:name>' : name , <EOL> '<STR_LIT:message>' : errorMessages [ name ] , <EOL> '<STR_LIT>' : lineNo , <EOL> '<STR_LIT:x>' : x , <EOL> } <EOL> def insertWithinString ( orig , idx , insert ) : <EOL> return orig [ : idx ] + insert + orig [ idx : ] <EOL> def replaceWithinString ( orig , start , end , replace ) : <EOL> return orig [ : start ] + replace + orig [ end : ] <EOL> def removeWithinString ( orig , start , end ) : <EOL> return orig [ : start ] + orig [ end : ] <EOL> def repeatString ( text , n ) : <EOL> result = "<STR_LIT>" <EOL> for i in range ( n ) : <EOL> result = result + text <EOL> return result <EOL> def getLineEnding ( text ) : <EOL> i = text . find ( "<STR_LIT:\r>" ) <EOL> if i != - <NUM_LIT:1> : <EOL> return "<STR_LIT:\r\n>" <EOL> return "<STR_LIT:\n>" <EOL> def insertWithinLine ( result , lineNo , idx , insert ) : <EOL> line = result [ '<STR_LIT>' ] [ lineNo ] <EOL> result [ '<STR_LIT>' ] [ lineNo ] = insertWithinString ( line , idx , insert ) <EOL> def replaceWithinLine ( result , lineNo , start , end , replace ) : <EOL> line = result [ '<STR_LIT>' ] [ lineNo ] <EOL> result [ '<STR_LIT>' ] [ lineNo ] = replaceWithinString ( line , start , end , replace ) <EOL> def removeWithinLine ( result , lineNo , start , end ) : <EOL> line = result [ '<STR_LIT>' ] [ lineNo ] <EOL> result [ '<STR_LIT>' ] [ lineNo ] = removeWithinString ( line , start , end ) <EOL> def initLine ( result , line ) : <EOL> result [ '<STR_LIT:x>' ] = <NUM_LIT:0> <EOL> result [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] + <NUM_LIT:1> <EOL> result [ '<STR_LIT>' ] . append ( line ) <EOL> result [ '<STR_LIT>' ] = None <EOL> result [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> def commitChar ( result , origCh ) : <EOL> ch = result [ '<STR_LIT>' ] <EOL> if origCh != ch : <EOL> replaceWithinLine ( result , result [ '<STR_LIT>' ] , result [ '<STR_LIT:x>' ] , result [ '<STR_LIT:x>' ] + len ( origCh ) , ch ) <EOL> result [ '<STR_LIT:x>' ] = result [ '<STR_LIT:x>' ] + len ( ch ) <EOL> def clamp ( valN , minN , maxN ) : <EOL> if minN is not None : <EOL> valN = max ( minN , valN ) <EOL> if maxN is not None : <EOL> valN = min ( maxN , valN ) <EOL> return valN <EOL> def peek ( arr ) : <EOL> arrLen = len ( arr ) <EOL> if arrLen == <NUM_LIT:0> : <EOL> return None <EOL> return arr [ arrLen - <NUM_LIT:1> ] <EOL> def isValidCloseParen ( parenStack , ch ) : <EOL> if len ( parenStack ) == <NUM_LIT:0> : <EOL> return False <EOL> return peek ( parenStack ) [ '<STR_LIT>' ] == PARENS [ ch ] <EOL> def onOpenParen ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] . append ( { <EOL> '<STR_LIT>' : result [ '<STR_LIT>' ] , <EOL> '<STR_LIT:x>' : result [ '<STR_LIT:x>' ] , <EOL> '<STR_LIT>' : result [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : result [ '<STR_LIT>' ] , <EOL> } ) <EOL> def onMatchedCloseParen ( result ) : <EOL> opener = peek ( result [ '<STR_LIT>' ] ) <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT:x>' ] + <NUM_LIT:1> <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] . append ( opener ) <EOL> result [ '<STR_LIT>' ] = opener [ '<STR_LIT:x>' ] <EOL> result [ '<STR_LIT>' ] . pop ( ) <EOL> def onUnmatchedCloseParen ( result ) : <EOL> result [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> def onCloseParen ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> if isValidCloseParen ( result [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] ) : <EOL> onMatchedCloseParen ( result ) <EOL> else : <EOL> onUnmatchedCloseParen ( result ) <EOL> def onTab ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] = DOUBLE_SPACE <EOL> def onSemicolon ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] = True <EOL> result [ '<STR_LIT>' ] = result [ '<STR_LIT:x>' ] <EOL> def onNewLine ( result ) : <EOL> result [ '<STR_LIT>' ] = False <EOL> result [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> def onQuote ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] = False <EOL> elif result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] = not result [ '<STR_LIT>' ] <EOL> if result [ '<STR_LIT>' ] : <EOL> cacheErrorPos ( result , ERROR_QUOTE_DANGER , result [ '<STR_LIT>' ] , result [ '<STR_LIT:x>' ] ) <EOL> else : <EOL> result [ '<STR_LIT>' ] = True <EOL> cacheErrorPos ( result , ERROR_UNCLOSED_QUOTE , result [ '<STR_LIT>' ] , result [ '<STR_LIT:x>' ] ) <EOL> def onBackslash ( result ) : <EOL> result [ '<STR_LIT>' ] = True <EOL> def afterBackslash ( result ) : <EOL> result [ '<STR_LIT>' ] = False <EOL> if result [ '<STR_LIT>' ] == NEWLINE : <EOL> if result [ '<STR_LIT>' ] : <EOL> err = error ( result , ERROR_EOL_BACKSLASH , result [ '<STR_LIT>' ] , result [ '<STR_LIT:x>' ] - <NUM_LIT:1> ) <EOL> raise ParinferError ( err ) <EOL> onNewLine ( result ) <EOL> CHAR_DISPATCH = { <EOL> '<STR_LIT:(>' : onOpenParen , <EOL> '<STR_LIT:{>' : onOpenParen , <EOL> '<STR_LIT:[>' : onOpenParen , <EOL> '<STR_LIT:)>' : onCloseParen , <EOL> '<STR_LIT:}>' : onCloseParen , <EOL> '<STR_LIT:]>' : onCloseParen , <EOL> DOUBLE_QUOTE : onQuote , <EOL> SEMICOLON : onSemicolon , <EOL> BACKSLASH : onBackslash , <EOL> TAB : onTab , <EOL> NEWLINE : onNewLine , <EOL> } <EOL> def onChar ( result ) : <EOL> ch = result [ '<STR_LIT>' ] <EOL> if result [ '<STR_LIT>' ] : <EOL> afterBackslash ( result ) <EOL> else : <EOL> charFn = CHAR_DISPATCH . get ( ch , None ) <EOL> if charFn is not None : <EOL> charFn ( result ) <EOL> result [ '<STR_LIT>' ] = ( not result [ '<STR_LIT>' ] and not result [ '<STR_LIT>' ] ) <EOL> def isCursorOnLeft ( result ) : <EOL> return ( result [ '<STR_LIT>' ] == result [ '<STR_LIT>' ] and <EOL> result [ '<STR_LIT>' ] is not None and <EOL> result [ '<STR_LIT>' ] <= result [ '<STR_LIT:x>' ] ) <EOL> def isCursorOnRight ( result , x ) : <EOL> return ( result [ '<STR_LIT>' ] == result [ '<STR_LIT>' ] and <EOL> result [ '<STR_LIT>' ] is not None and <EOL> x is not None and <EOL> result [ '<STR_LIT>' ] > x ) <EOL> def isCursorInComment ( result ) : <EOL> return isCursorOnRight ( result , result [ '<STR_LIT>' ] ) <EOL> def handleCursorDelta ( result ) : <EOL> hasCursorDelta = ( result [ '<STR_LIT>' ] is not None and <EOL> result [ '<STR_LIT>' ] == result [ '<STR_LIT>' ] and <EOL> result [ '<STR_LIT>' ] == result [ '<STR_LIT:x>' ] ) <EOL> if hasCursorDelta : <EOL> result [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] + result [ '<STR_LIT>' ] <EOL> def updateParenTrailBounds ( result ) : <EOL> line = result [ '<STR_LIT>' ] [ result [ '<STR_LIT>' ] ] <EOL> prevCh = None <EOL> if result [ '<STR_LIT:x>' ] > <NUM_LIT:0> : <EOL> prevCh = line [ result [ '<STR_LIT:x>' ] - <NUM_LIT:1> ] <EOL> ch = result [ '<STR_LIT>' ] <EOL> shouldReset = ( result [ '<STR_LIT>' ] and <EOL> ch != "<STR_LIT>" and <EOL> ch not in CLOSE_PARENS and <EOL> ( ch != BLANK_SPACE or prevCh == BACKSLASH ) and <EOL> ch != DOUBLE_SPACE ) <EOL> if shouldReset : <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT:x>' ] + <NUM_LIT:1> <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT:x>' ] + <NUM_LIT:1> <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = [ ] <EOL> result [ '<STR_LIT>' ] = None <EOL> def clampParenTrailToCursor ( result ) : <EOL> startX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> endX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> isCursorClamping = ( isCursorOnRight ( result , startX ) and <EOL> not isCursorInComment ( result ) ) <EOL> if isCursorClamping : <EOL> newStartX = max ( startX , result [ '<STR_LIT>' ] ) <EOL> newEndX = max ( endX , result [ '<STR_LIT>' ] ) <EOL> line = result [ '<STR_LIT>' ] [ result [ '<STR_LIT>' ] ] <EOL> removeCount = <NUM_LIT:0> <EOL> for i in range ( startX , newStartX ) : <EOL> if line [ i ] in CLOSE_PARENS : <EOL> removeCount = removeCount + <NUM_LIT:1> <EOL> for i in range ( removeCount ) : <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] . pop ( <NUM_LIT:0> ) <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = newStartX <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = newEndX <EOL> def removeParenTrail ( result ) : <EOL> startX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> endX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> if startX == endX : <EOL> return <EOL> openers = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> while len ( openers ) != <NUM_LIT:0> : <EOL> result [ '<STR_LIT>' ] . append ( openers . pop ( ) ) <EOL> removeWithinLine ( result , result [ '<STR_LIT>' ] , startX , endX ) <EOL> def correctParenTrail ( result , indentX ) : <EOL> parens = "<STR_LIT>" <EOL> while len ( result [ '<STR_LIT>' ] ) > <NUM_LIT:0> : <EOL> opener = peek ( result [ '<STR_LIT>' ] ) <EOL> if opener [ '<STR_LIT:x>' ] >= indentX : <EOL> result [ '<STR_LIT>' ] . pop ( ) <EOL> parens = parens + PARENS [ opener [ '<STR_LIT>' ] ] <EOL> else : <EOL> break <EOL> insertWithinLine ( result , result [ '<STR_LIT>' ] [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] [ '<STR_LIT>' ] , parens ) <EOL> def cleanParenTrail ( result ) : <EOL> startX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> endX = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> if ( startX == endX or result [ '<STR_LIT>' ] != result [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) : <EOL> return <EOL> line = result [ '<STR_LIT>' ] [ result [ '<STR_LIT>' ] ] <EOL> newTrail = "<STR_LIT>" <EOL> spaceCount = <NUM_LIT:0> <EOL> for i in range ( startX , endX ) : <EOL> if line [ i ] in CLOSE_PARENS : <EOL> newTrail = newTrail + line [ i ] <EOL> else : <EOL> spaceCount = spaceCount + <NUM_LIT:1> <EOL> if spaceCount > <NUM_LIT:0> : <EOL> replaceWithinLine ( result , result [ '<STR_LIT>' ] , startX , endX , newTrail ) <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] - spaceCount <EOL> def appendParenTrail ( result ) : <EOL> opener = result [ '<STR_LIT>' ] . pop ( ) <EOL> closeCh = PARENS [ opener [ '<STR_LIT>' ] ] <EOL> result [ '<STR_LIT>' ] = opener [ '<STR_LIT:x>' ] <EOL> insertWithinLine ( result , result [ '<STR_LIT>' ] [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] [ '<STR_LIT>' ] , closeCh ) <EOL> result [ '<STR_LIT>' ] [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] [ '<STR_LIT>' ] + <NUM_LIT:1> <EOL> def finishNewParenTrail ( result ) : <EOL> if result [ '<STR_LIT>' ] == INDENT_MODE : <EOL> clampParenTrailToCursor ( result ) <EOL> removeParenTrail ( result ) <EOL> elif result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> if result [ '<STR_LIT>' ] != result [ '<STR_LIT>' ] : <EOL> cleanParenTrail ( result ) <EOL> def correctIndent ( result ) : <EOL> origIndent = result [ '<STR_LIT:x>' ] <EOL> newIndent = origIndent <EOL> minIndent = <NUM_LIT:0> <EOL> maxIndent = result [ '<STR_LIT>' ] <EOL> opener = peek ( result [ '<STR_LIT>' ] ) <EOL> if opener is not None : <EOL> minIndent = opener [ '<STR_LIT:x>' ] + <NUM_LIT:1> <EOL> newIndent = newIndent + opener [ '<STR_LIT>' ] <EOL> newIndent = clamp ( newIndent , minIndent , maxIndent ) <EOL> if newIndent != origIndent : <EOL> indentStr = repeatString ( BLANK_SPACE , newIndent ) <EOL> replaceWithinLine ( result , result [ '<STR_LIT>' ] , <NUM_LIT:0> , origIndent , indentStr ) <EOL> result [ '<STR_LIT:x>' ] = newIndent <EOL> result [ '<STR_LIT>' ] = result [ '<STR_LIT>' ] + newIndent - origIndent <EOL> def onProperIndent ( result ) : <EOL> result [ '<STR_LIT>' ] = False <EOL> if result [ '<STR_LIT>' ] : <EOL> err = error ( result , ERROR_QUOTE_DANGER , None , None ) <EOL> raise ParinferError ( err ) <EOL> if result [ '<STR_LIT>' ] == INDENT_MODE : <EOL> correctParenTrail ( result , result [ '<STR_LIT:x>' ] ) <EOL> elif result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> correctIndent ( result ) <EOL> def onLeadingCloseParen ( result ) : <EOL> result [ '<STR_LIT>' ] = True <EOL> result [ '<STR_LIT>' ] = True <EOL> if result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> if isValidCloseParen ( result [ '<STR_LIT>' ] , result [ '<STR_LIT>' ] ) : <EOL> if isCursorOnLeft ( result ) : <EOL> result [ '<STR_LIT>' ] = False <EOL> onProperIndent ( result ) <EOL> else : <EOL> appendParenTrail ( result ) <EOL> def onIndent ( result ) : <EOL> if result [ '<STR_LIT>' ] in CLOSE_PARENS : <EOL> onLeadingCloseParen ( result ) <EOL> elif result [ '<STR_LIT>' ] == SEMICOLON : <EOL> result [ '<STR_LIT>' ] = False <EOL> elif result [ '<STR_LIT>' ] != NEWLINE : <EOL> onProperIndent ( result ) <EOL> def processChar ( result , ch ) : <EOL> origCh = ch <EOL> result [ '<STR_LIT>' ] = ch <EOL> result [ '<STR_LIT>' ] = False <EOL> if result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> handleCursorDelta ( result ) <EOL> if result [ '<STR_LIT>' ] and ch != BLANK_SPACE and ch != TAB : <EOL> onIndent ( result ) <EOL> if result [ '<STR_LIT>' ] : <EOL> result [ '<STR_LIT>' ] = "<STR_LIT>" <EOL> else : <EOL> onChar ( result ) <EOL> updateParenTrailBounds ( result ) <EOL> commitChar ( result , origCh ) <EOL> def processLine ( result , line ) : <EOL> initLine ( result , line ) <EOL> if result [ '<STR_LIT>' ] == INDENT_MODE : <EOL> result [ '<STR_LIT>' ] = ( len ( result [ '<STR_LIT>' ] ) != <NUM_LIT:0> and <EOL> not result [ '<STR_LIT>' ] ) <EOL> elif result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> result [ '<STR_LIT>' ] = not result [ '<STR_LIT>' ] <EOL> chars = line + NEWLINE <EOL> for c in chars : <EOL> processChar ( result , c ) <EOL> if result [ '<STR_LIT>' ] == result [ '<STR_LIT>' ] [ '<STR_LIT>' ] : <EOL> finishNewParenTrail ( result ) <EOL> def finalizeResult ( result ) : <EOL> if result [ '<STR_LIT>' ] : <EOL> err = error ( result , ERROR_QUOTE_DANGER , None , None ) <EOL> raise ParinferError ( err ) <EOL> if result [ '<STR_LIT>' ] : <EOL> err = error ( result , ERROR_UNCLOSED_QUOTE , None , None ) <EOL> raise ParinferError ( err ) <EOL> if len ( result [ '<STR_LIT>' ] ) != <NUM_LIT:0> : <EOL> if result [ '<STR_LIT>' ] == PAREN_MODE : <EOL> opener = peek ( result [ '<STR_LIT>' ] ) <EOL> err = error ( result , ERROR_UNCLOSED_PAREN , opener [ '<STR_LIT>' ] , opener [ '<STR_LIT:x>' ] ) <EOL> raise ParinferError ( err ) <EOL> elif result [ '<STR_LIT>' ] == INDENT_MODE : <EOL> correctParenTrail ( result , <NUM_LIT:0> ) <EOL> result [ '<STR_LIT:success>' ] = True <EOL> def processError ( result , e ) : <EOL> result [ '<STR_LIT:success>' ] = False <EOL> if e [ '<STR_LIT>' ] : <EOL> del e [ '<STR_LIT>' ] <EOL> result [ '<STR_LIT:error>' ] = e <EOL> else : <EOL> result [ '<STR_LIT:error>' ] [ '<STR_LIT:name>' ] = ERROR_UNHANDLED <EOL> result [ '<STR_LIT:error>' ] [ '<STR_LIT:message>' ] = e [ '<STR_LIT>' ] <EOL> def processText ( text , options , mode ) : <EOL> result = initialResult ( text , options , mode ) <EOL> try : <EOL> for line in result [ '<STR_LIT>' ] : <EOL> processLine ( result , line ) <EOL> finalizeResult ( result ) <EOL> except ParinferError as e : <EOL> errorDetails = e . args [ <NUM_LIT:0> ] <EOL> processError ( result , errorDetails ) <EOL> return result <EOL> def getChangedLines ( result ) : <EOL> changedLines = [ ] <EOL> for i in range ( len ( result [ '<STR_LIT>' ] ) ) : <EOL> if result [ '<STR_LIT>' ] [ i ] != result [ '<STR_LIT>' ] [ i ] : <EOL> changedLines . append ( { <EOL> '<STR_LIT>' : i , <EOL> '<STR_LIT>' : result [ '<STR_LIT>' ] [ i ] , <EOL> } ) <EOL> return changedLines <EOL> def publicResult ( result ) : <EOL> if not result [ '<STR_LIT:success>' ] : <EOL> return { <EOL> '<STR_LIT:text>' : result [ '<STR_LIT>' ] , <EOL> '<STR_LIT:success>' : False , <EOL> '<STR_LIT:error>' : result [ '<STR_LIT:error>' ] , <EOL> } <EOL> lineEnding = getLineEnding ( result [ '<STR_LIT>' ] ) <EOL> return { <EOL> '<STR_LIT:text>' : lineEnding . join ( result [ '<STR_LIT>' ] ) , <EOL> '<STR_LIT:success>' : True , <EOL> '<STR_LIT>' : getChangedLines ( result ) , <EOL> } <EOL> def indent_mode ( text , options ) : <EOL> result = processText ( text , options , INDENT_MODE ) <EOL> return publicResult ( result ) <EOL> def paren_mode ( text , options ) : <EOL> result = processText ( text , options , PAREN_MODE ) <EOL> return publicResult ( result ) </s>
