如何使用Pyparsing解析嵌套的函数调用? [英] How to parse nested function calls using Pyparsing?

查看:109
本文介绍了如何使用Pyparsing解析嵌套的函数调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个CSS解析器,但无法弄清楚如何解析嵌套函数调用,例如 alpha(rgb(1、2、3),0.5).

I'm developing a css parser but cannot figure out how to parse nested function calls like alpha(rgb(1, 2, 3), 0.5).

这是我的代码:

# -*- coding: utf-8 -*-


from pyparsing import * #, Word, alphas, OneOrMore, countedArray, And, srange, hexnums,  Combine, cStyleComment

from string import punctuation
from app.utils.file_manager import loadCSSFile, writeFile
from pyparsing import OneOrMore, Optional, Word, quotedString, delimitedList,  Suppress
from __builtin__ import len

# divide tudo por espaços, tabulações e novas linhas
words = ZeroOrMore(cStyleComment | Word(printables))

digit = '0123456789'; underscore = '_'; hyphen =  '-'
hexDigit = 'abcdefABCDEF' + digit
letter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
az_AZ_underscore = underscore + letter;  
az_AZ_09_underscore = az_AZ_underscore + digit; 
az_AZ_hyphen = hyphen + letter;
az_AZ_09_hiphen = az_AZ_hyphen + digit;
LPAR = Suppress('('); RPAR = Suppress(')')

# identifiers
identifier = Combine(Word(az_AZ_underscore) + Optional(Word(az_AZ_09_underscore)))
# identifiers
identifier_reserved = Combine(Word(az_AZ_hyphen) + Optional(Word(az_AZ_09_hiphen)))

# numbers
hexadecimal = Word(hexnums, min=1)
integer = Word(digit, min=1)
decimal = Combine('.' + integer | integer + Optional('.' + integer))


# value values
color_hex = Combine('#' +  hexadecimal ) 
at_identifier =  Combine('@' + identifier)
arg = at_identifier | color_hex | decimal | quotedString 




function_call = identifier + LPAR + Optional(delimitedList(arg)) + RPAR

value =  Group(color_hex | at_identifier | function_call)

print(value.parseString('a(b())'))

我想做类似 arg = at_identifier |的事情. color_hex |十进制| quotedString | function_call ,但这是不可能的,因为尚未声明变量function_call.

I whould like to do something like arg = at_identifier | color_hex | decimal | quotedString | function_call but it's not possible because the variable is function_call is not declared yet.

如何使用Pyparsing解析嵌套的函数调用?

How could I parse nested function calls using Pyparsing?

推荐答案

您真的非常亲密.要定义这样的递归语法,您需要向前声明嵌套表达式.

You are really very close. To define a recursive grammar like this, you need to forward-declare the nested expression.

如您所见,这是

arg = at_identifier | color_hex | decimal | quotedString
function_call = identifier + LPAR + Optional(delimitedList(arg)) + RPAR

仅使用不属于函数调用的arg解析函数调用.

only parses function calls with args that are not themselves function calls.

要递归地定义它,首先使用Forward()定义一个空的占位符表达式:

To define this recursively, first define an empty placeholder expression, using Forward():

function_call = Forward()

我们尚不知道该表达式将包含什么内容,但是我们知道它将是有效的参数类型.既然已经声明了它,我们就可以使用它:

We don't know yet what will go into this expression, but we do know that it will be a valid argument type. Since it has been declared now we can use it:

arg = at_identifier | color_hex | decimal | quotedString | function_call

现在我们已经定义了arg,我们可以定义将在function_call中使用的内容.代替使用普通的Python赋值(=),我们必须使用运算符来修改function_call而不是重新定义它. Pyparsing允许您使用<< =或<<运算符(首选第一个):

Now that we have arg defined, we can define what will go into a function_call. Instead of using ordinary Python assignment using '=', we have to use an operator that will modify the function_call instead of redefining it. Pyparsing allows you to use <<= or << operators (the first is preferred):

function_call <<= identifier + LPAR + Optional(delimitedList(arg)) + RPAR

这现在足以解析给定的示例字符串,但是您对实际的嵌套结构失去了可见性.如果您将函数调用分组如下:

This is now sufficient to parse your given sample string, but you've lost visibility to the actual nesting structure. If you group your function call like this:

function_call <<= Group(identifier + LPAR + Group(Optional(delimitedList(arg))) + RPAR)

您将始终从函数调用(命名的和解析的args)中获得可预测的结构,并且函数调用本身将被分组.

you will always get a predictable structure from a function call (a named and the parsed args), and the function call itself will be grouped.

这篇关于如何使用Pyparsing解析嵌套的函数调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆