I want to create an api which is responsible to get the data from the Database.
My Requirment:
GET /products?query=EQUAL(product_id,"56789")
GET /products?query=AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236"))
GET /products?query=OR(EQUAL(product_id,"56789"),EQUAL(product_id,"369"))
my api query parameters contains operators like EQUAL,OR,AND etc. I dont know how to parse these custom operators.
Can any one suggest a solution to parse these operators?
Frankly, I would use normal SQL query instead of own operators.
But for own operators I would use parser SLY or PLY
Both created by David Beazley . PLY
is older, SLY
is never and use classes
It is hard to describe all code.
Lexer
recognizes tokens in string EQUAL
, AND
, OR
, (
, )
, ,
, variables
, strings
(values).
Parser
checks grammary - it checks if tokens are in correct order. It also converts to SQL query.
from sly import Lexer, Parser
class CalcLexer(Lexer):
tokens = {EQUAL, AND, OR, VARIABLE, STRING} #, NUMBER}
EQUAL = r'EQUAL' # has to be before VARIABLE
AND = r'AND' # has to be before VARIABLE
OR = r'OR' # has to be before VARIABLE
VARIABLE = r'[a-zA-Z][a-zA-Z0-9_]*'
STRING = r'"[^"]*"'
#NUMBER = r'\d+'
#VARIABLE['EQUAL'] = EQUAL # if there is no EQUAL before VARIABLE
#VARIABLE['AND'] = AND # if there is no AND before VARIABLE
#VARIABLE['OR'] = OR # if there is no OR before VARIABLE
literals = { '(', ')', ',' }
ignore = ' \t'
def error(self, t):
print(f"Illegal character '{t.STRING[0]}'")
#self.index += 1
class CalcParser(Parser):
tokens = CalcLexer.tokens
#def __init__(self):
#self.variables = {}
@_('EQUAL "(" VARIABLE "," STRING ")"')
def statement(self, p):
print('[PARSER]', p.VARIABLE, '=', p.STRING)
#self.variables[p.VARIABLE] = p.STRING
return f'{p.VARIABLE} = {p.STRING}'
#@_('EQUAL "(" VARIABLE "," NUMBER ")"')
#def statement(self, p):
# print('[PARSER]', p.VARIABLE, '=', p.NUMBER)
# #self.variables[p.VARIABLE] = p.NUMBER
# return f'{p.VARIABLE} = {p.NUMBER}'
#@_('EQUAL "(" VARIABLE "," VARIABLE ")"')
#def statement(self, p):
# print('[PARSER]', p.VARIABLE0, '=', p.VARIABLE1)
# #self.variables[p.VARIABLE0] = p.VARIABLE1
# return f'{p.VARIABLE0} = {p.VARIABLE1}'
@_('AND "(" statement "," statement ")"')
def statement(self, p):
print('[PARSER]', p.statement0, 'AND', p.statement1)
return f'({p.statement0}) AND ({p.statement1})'
@_('OR "(" statement "," statement ")"')
def statement(self, p):
print('[PARSER]', p.statement0, 'OR', p.statement1)
return f'({p.statement0}) OR ({p.statement1})'
#--------------------------------------------------------------------
examples = [
'EQUAL(product_id,"56789")',
'AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236"))',
'OR(EQUAL(product_id,"56789"),EQUAL(product_id,"369"))',
# nested
'OR(EQUAL(product_id,"2236"),AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236")))',
'OR(AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236")),EQUAL(product_id,"2236"))',
'OR(AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236")),AND(EQUAL(product_id,"56789"),EQUAL(product_id,"2236")))',
# with spaces
'EQUAL ( product_id , "56789" ) ',
#'EQUAL(product_id,"56789")', # VARIABLE,STRING
#'EQUAL(product_id,56789)', # VARIABLE,NUMBER
#'EQUAL(product_id,other_id)', # VARIABLE,VARIABLE
]
if __name__ == '__main__':
lexer = CalcLexer()
parser = CalcParser()
for text in examples:
print('---')
print('text:', text)
for tok in lexer.tokenize(text):
print(f'[LEXER] type={tok.type!r}, value={tok.value!r}')
print('result:', parser.parse(lexer.tokenize(text)))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.