mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-28 22:22:59 -06:00
135 lines
5.3 KiB
Python
135 lines
5.3 KiB
Python
|
#----------------------------------------------------------------------
|
||
|
# Name: parse.py
|
||
|
# Author: David N. Mashburn <david.n.mashburn@gmail.com>
|
||
|
# Created: 12/20/2009
|
||
|
# Tags: phoenix-port
|
||
|
#----------------------------------------------------------------------
|
||
|
"""parse.py is a utility that allows simple checking for line continuations
|
||
|
to give the shell information about where text is commented and where it is
|
||
|
not and also how to appropriately break up a sequence of commands into
|
||
|
separate multi-line commands...
|
||
|
"""
|
||
|
|
||
|
__author__ = "David N. Mashburn <david.n.mashburn@gmail.com>"
|
||
|
# created 12/20/2009
|
||
|
|
||
|
import re
|
||
|
|
||
|
# change this to testForContinuations
|
||
|
|
||
|
def testForContinuations(codeBlock,ignoreErrors=False):
|
||
|
""" Test 4 different types of continuations:""" + \
|
||
|
""" String Continuations (ie with ''')""" + \
|
||
|
""" Indentation Block Continuations (ie "if 1:" )""" + \
|
||
|
""" Line Continuations (ie with \\ character )""" + \
|
||
|
""" Parenthetical continuations (, [, or {"""
|
||
|
|
||
|
stringMark = None
|
||
|
paraList = []
|
||
|
indentNumber=[0]
|
||
|
|
||
|
stringMarks = ['"""',"'''",'"',"'"]
|
||
|
openMarks = ['(','[','{']
|
||
|
closeMarks = [')',']','}']
|
||
|
paraMarkDict = { '(':')', '[':']', '{':'}' }
|
||
|
|
||
|
stringContinuationList=[]
|
||
|
lineContinuationList=[] # For \ continuations ... False because cannot start as line Continuation...
|
||
|
indentationBlockList=[]
|
||
|
parentheticalContinuationList=[]
|
||
|
newIndent=False
|
||
|
lspContinuation=False
|
||
|
for i,l in enumerate(codeBlock.split('\n')):
|
||
|
currentIndentation = len(l)-len(l.lstrip())
|
||
|
|
||
|
if i>0:
|
||
|
lspContinuation = lineContinuationList[-1] or \
|
||
|
stringContinuationList[-1] or \
|
||
|
parentheticalContinuationList[-1]
|
||
|
# first, check for non-executing lines (whitespace and/or comments only)
|
||
|
if l.lstrip()=='':
|
||
|
emptyLine=True
|
||
|
elif l.strip()[0]=='#':
|
||
|
emptyLine=True
|
||
|
else: # otherwise, check the indentation...
|
||
|
emptyLine=False
|
||
|
if newIndent and currentIndentation>indentNumber[-1]:
|
||
|
newIndent=False
|
||
|
indentNumber.append(currentIndentation)
|
||
|
elif lspContinuation:
|
||
|
pass
|
||
|
elif not newIndent and currentIndentation in indentNumber:
|
||
|
while currentIndentation<indentNumber[-1]:
|
||
|
indentNumber.pop() # This is the end of an indentation block
|
||
|
elif not ignoreErrors:
|
||
|
#print('Invalid Indentation!!')
|
||
|
return ['Invalid Indentation Error',i]
|
||
|
|
||
|
firstWord = re.match(' *\w*',l).group().lstrip()
|
||
|
if firstWord in ['if','else','elif','for','while',
|
||
|
'def','class','try','except','finally']:
|
||
|
hasContinuationWord = True
|
||
|
else:
|
||
|
hasContinuationWord = False
|
||
|
|
||
|
|
||
|
commented=False
|
||
|
nonCommentLength=len(l)
|
||
|
|
||
|
result = re.finditer('"""'+'|'+"'''" + r'''|"|'|\"|\'|\(|\)|\[|\]|\{|\}|#''',l)
|
||
|
for r in result:
|
||
|
j = r.group()
|
||
|
|
||
|
if stringMark == None:
|
||
|
if j=='#': # If it is a legitimate comment, ignore everything after
|
||
|
commented=True
|
||
|
# get length up to last non-comment character
|
||
|
nonCommentLength = r.start()
|
||
|
break
|
||
|
elif j in stringMarks:
|
||
|
stringMark=j
|
||
|
else:
|
||
|
if paraList != [] and j in closeMarks:
|
||
|
if paraMarkDict[paraList[-1]]==j:
|
||
|
paraList.pop()
|
||
|
elif not ignoreErrors:
|
||
|
#print('Invalid Syntax!!')
|
||
|
return ['Invalid Syntax Error',i]
|
||
|
if j in openMarks:
|
||
|
paraList.append(j)
|
||
|
elif stringMark==j:
|
||
|
stringMark=None
|
||
|
|
||
|
stringContinuationList.append(stringMark!=None)
|
||
|
|
||
|
indentationBlockList.append(False)
|
||
|
nonCommentString = l[:nonCommentLength].rstrip()
|
||
|
if nonCommentString!='' and stringContinuationList[-1]==False:
|
||
|
if nonCommentString[-1]==':':
|
||
|
indentationBlockList[-1]=True
|
||
|
newIndent=True
|
||
|
|
||
|
lineContinuationList.append(False)
|
||
|
if len(l)>0 and not commented:
|
||
|
if l[-1]=='\\':
|
||
|
lineContinuationList[-1]=True
|
||
|
|
||
|
parentheticalContinuationList.append( paraList != [] )
|
||
|
|
||
|
# Now stringContinuationList (et al) is line by line key for magic
|
||
|
# telling it whether or not each next line is part of a string continuation
|
||
|
|
||
|
if (stringContinuationList[-1] or indentationBlockList[-1] or \
|
||
|
lineContinuationList[-1] or parentheticalContinuationList[-1]) \
|
||
|
and not ignoreErrors:
|
||
|
#print('Incomplete Syntax!!')
|
||
|
return ['Incomplete Syntax Error',i]
|
||
|
|
||
|
if newIndent and not ignoreErrors:
|
||
|
#print('Incomplete Indentation!')
|
||
|
return ['Incomplete Indentation Error',i]
|
||
|
|
||
|
# Note that if one of these errors above gets thrown, the best solution is to pass the resulting block
|
||
|
# to the interpreter as exec instead of interp
|
||
|
return stringContinuationList,indentationBlockList,lineContinuationList,parentheticalContinuationList
|