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: introductory

Starter code:

def get_textliterals(pv_code):
	

Solutions:
import re

SKIPERS = re.compile(r'|'.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(r"'.+?'", 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(r"(?:--[^\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(r"(?:--[^\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
        else:
            if 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(r'/\*.*\*/', lambda mo : comment_replace(mo.group()), pv_code)
    pv_code = re.sub(r'(--.*)', lambda mo : one_line_comment_replace(mo.group()), pv_code)
    pv_code = re.sub(r"\'\'", '  ', 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 = [r"/\*(?:\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