We like parsed SQL or PL/SQL blocks...

You need to write function that return list of literals indices from source block, excluding "in" comments, OR return empty list if no literals found.

input:
some fragment of sql or pl/sql code

output:
list of literals indices [(start, end), ...] OR empty list

Sample:
```
get_textliterals("'this' is sample") -> [(0,6)]
get_textliterals("'this' is sample 'too'") -> [(0, 6), (15, 20)]
```

Text literal: any text between single quotes
Sample:
```
  s := 'i am literal'
```
Single-line comment: any text started with "--" 
Sample:
```
  a := 1;
  -- this is single-line comment
```
Multy-line comment: any text between /* */
```
  a := 1;
  /*
  this is long multy-line comment
  */
```

Note: 
1) handle single quote inside literal
```
  s := 'we can use quote '' in literal'
```  
2) multy-line literal
```
 s := '
 this is literal too
 ';
```
3) skip literal inside comment
```
s := 'test'; --when comment started - this is not 'literal'
```
4) any unclosed literal should be closed with last symbol of the source fragment
```
s := 'test
```
There is one literal in this code: "'test"

Difficulty: EASY

Starter code:
def get_textliterals(pv_code):
	

Solutions:
import re
SKIPERS = re.compile('|'.join(['\\\\*.*?\\*/', '--.*?(\n|$)', "''"]))

def get_textliterals(code):
	code = SKIPERS.sub(lambda m: 'x' * len(m.group()), code.rstrip())
	if code.count("'") % 2:
		code += "'"
	return [(m.start(), m.end()) for m in re.finditer("'.+?'", code, flags=re.DOTALL)]


def get_textliterals(pv_code):
	start_index = None
	all_index_store = []
	a_comment = False
	b_comment = False
	for (index, char) in enumerate(pv_code):
		if char == '*' and pv_code[index - 1] == '/':
			a_comment = True
		elif a_comment == True and char == '/' and (pv_code[index - 1] == '*'):
			a_comment = False
		elif char == '-' and pv_code[index - 1] == '-':
			b_comment = True
		elif b_comment == True and char == '\n':
			b_comment = False
		elif (char == "'" or len(pv_code) - 1 == index) and a_comment == False and (b_comment == False):
			if start_index != None:
				if index > 0 and pv_code[index - 1] == "'" or (len(pv_code) > index + 1 and pv_code[index + 1] == "'"):
					continue
				all_index_store.append((start_index, index + 1))
				start_index = None
			else:
				start_index = index
	return all_index_store


import re

def get_textliterals(pv_code):
	return [(match.start(1), match.end(1)) for match in re.finditer("(?:--[^\\n]*\\n?|/\\*.*?\\*/|((?:'[^']*')+|'[^']*$)|.)", pv_code, re.DOTALL) if match.group(1)]


import re

def get_textliterals(pv_code):
	print(pv_code)
	result = [(match.start(1), match.end(1)) for match in re.finditer("(?:--[^\\n]*\\n?|/\\*.*?\\*/|((?:'[^']*')+|'[^']*$)|.)", pv_code, re.MULTILINE) if match.group(1)]
	return result


def comm_check(l, p_l, comm_started):
	if l == '/' and p_l == '*' and (comm_started == 2):
		return 0
	if comm_started == 1 and l == '\n':
		return 0
	if l == '-' and p_l == '-':
		return 1
	elif l == '*' and p_l == '/':
		return 2
	else:
		return comm_started

def get_textliterals(pv_code):
	indices = []
	open_i = -1
	comm_start = 0
	for i in range(0, len(pv_code)):
		comm_start = comm_check(pv_code[i], pv_code[i - 1], comm_start)
		if pv_code[i] == "'" and comm_start == 0:
			if open_i == -1:
				open_i = i
			else:
				if i + 1 < len(pv_code) and i - 1 >= 0:
					if pv_code[i + 1] == "'" or pv_code[i - 1] == "'":
						continue
				indices.append((open_i, i + 1))
				open_i = -1
	if open_i != -1:
		indices.append((open_i, len(pv_code)))
	return indices


def get_textliterals(pv_code):
	l_list = []
	l_switch = 'empty'
	for i in range(len(pv_code)):
		if pv_code[i] == "'" and pv_code[i:i + 2] != "''" and (pv_code[i - 1:i + 1] != "''"):
			if l_switch == 'empty':
				l_begin = i
				l_switch = 'begin'
			elif l_switch == 'begin':
				l_list.append((l_begin, i + 1))
				l_switch = 'empty'
		elif pv_code[i:i + 2] == '--':
			if l_switch != 'begin' and l_switch != 'rem2':
				l_switch = 'rem1'
		elif pv_code[i:i + 2] == '/*':
			if l_switch != 'begin' and l_switch != 'rem1':
				l_switch = 'rem2'
		elif pv_code[i:i + 2] == '*/':
			if l_switch == 'rem2':
				l_switch = 'empty'
		elif pv_code[i] == '\n':
			if l_switch == 'rem1':
				l_switch = 'empty'
	if l_switch == 'begin':
		l_list.append((l_begin, i + 1))
	return l_list


def get_textliterals(pv_code):
	r = []
	i = 0
	in_quote = False
	while i < len(pv_code):
		if in_quote:
			if pv_code[i] == "'":
				if pv_code[i:].startswith("''"):
					i += 1
				else:
					r.append((s, i + 1))
					in_quote = False
		elif pv_code[i] == "'":
			s = i
			in_quote = True
		elif pv_code[i:].startswith('--'):
			i = pv_code.index('\n', i)
		elif pv_code[i:].startswith('/*'):
			i = pv_code.index('*/', i + 2)
			i += 1
		i += 1
	if in_quote:
		r.append((s, len(pv_code)))
	return r


import re

def comment_replace(comment):
	return ' ' * len(comment)

def one_line_comment_replace(comment):
	return ' ' * len(comment)

def get_textliterals(pv_code):
	pv_code = re.sub('/\\*.*\\*/', lambda mo: comment_replace(mo.group()), pv_code)
	pv_code = re.sub('(--.*)', lambda mo: one_line_comment_replace(mo.group()), pv_code)
	pv_code = re.sub("\\'\\'", '  ', pv_code)
	results = list()
	while "'" in pv_code:
		start_index = pv_code.index("'")
		pv_code = pv_code[:pv_code.index("'")] + 'X' + pv_code[pv_code.index("'") + 1:]
		if "'" in pv_code:
			end_index = pv_code.index("'") + 1
			pv_code = pv_code[:pv_code.index("'")] + 'X' + pv_code[pv_code.index("'") + 1:]
		if start_index < end_index:
			indxs = (start_index, end_index)
		else:
			indxs = (start_index, len(pv_code))
		results.append(indxs)
	return results


def get_textliterals(pv_code):
	literal_start = -1
	result = []
	comment = False
	inline_comment = False
	quote = False
	for (idx, c) in enumerate(pv_code):
		if idx + 1 == len(pv_code) and literal_start != -1:
			literal_end = idx + 1
			result.append((literal_start, literal_end))
			break
		elif c == '*' and pv_code[idx - 1] == '/':
			comment = True
		elif c == '/' and pv_code[idx - 1] == '*' and comment:
			comment = False
		elif c == "'" and literal_start != -1 and (not comment) and (not inline_comment):
			if idx + 1 < len(pv_code) and pv_code[idx + 1] == "'":
				quote = True
			elif pv_code[idx - 1] == "'":
				continue
			else:
				literal_end = idx + 1
				result.append((literal_start, literal_end))
				literal_start = -1
				quote = False
		elif c == "'" and quote == False and (not comment) and (not inline_comment):
			literal_start = idx
		elif c == '-' and pv_code[idx - 1] == '-':
			inline_comment = True
		elif c == '\n':
			inline_comment = False
	return result


from re import finditer

def get_textliterals(pv_code):
	l = len(pv_code)
	pv_code = pv_code.replace("''", '""')
	addedQuote = False
	if not pv_code.endswith("'"):
		addedQuote = True
		pv_code += "'"
	patterns = ['/\\*(?:\\n|.)*?\\*/', '--.+', "'(?:\n|.)*?'"]
	comments = [m.span() for m in finditer(patterns[0], pv_code)] + [m.span() for m in finditer(patterns[1], pv_code)]
	answer = []
	candidates = [m.span() for m in finditer(patterns[2], pv_code)]
	for (startA, endA) in candidates:
		ok = True
		for (startB, endB) in comments:
			if startB < startA < endA < endB:
				ok = False
				break
		if ok:
			if addedQuote and endA - 1 == l:
				endA -= 1
			answer.append((startA, endA))
	return answer