失礼なタイトルで申し訳ありません。これ以上いいものは思いつきませんでした
次の要件を持つ pyparsing を使用して DSL を実装しようとしています。
- 変数: すべて v_ で始まります
- 単項演算子: +、-
- 二項演算子: +、-、*、/、%
- 定数
- 変数が 1 つしかない場合の通常の関数と同様の関数
- 関数は次のように機能する必要があります:
foo(v_1+v_2) = foo(v_1) + foo(v_2)
,foo(bar(10*v_6))=foo(bar(10))*foo(bar(v_6))
. これは、バイナリ操作の場合に当てはまります。
私は1-5を働かせることができます
これは私がこれまでに持っているコードです
from pyparsing import *
exprstack = []
#~ @traceParseAction
def pushFirst(tokens):
exprstack.insert(0,tokens[0])
# define grammar
point = Literal( '.' )
plusorminus = Literal( '+' ) | Literal( '-' )
number = Word( nums )
integer = Combine( Optional( plusorminus ) + number )
floatnumber = Combine( integer +
Optional( point + Optional( number ) ) +
Optional( integer )
)
ident = Combine("v_" + Word(nums))
plus = Literal( "+" )
minus = Literal( "-" )
mult = Literal( "*" )
div = Literal( "/" )
cent = Literal( "%" )
lpar = Literal( "(" ).suppress()
rpar = Literal( ")" ).suppress()
addop = plus | minus
multop = mult | div | cent
expop = Literal( "^" )
band = Literal( "@" )
# define expr as Forward, since we will reference it in atom
expr = Forward()
fn = Word( alphas )
atom = ( ( floatnumber | integer | ident | ( fn + lpar + expr + rpar ) ).setParseAction(pushFirst) |
( lpar + expr.suppress() + rpar ))
factor = Forward()
factor << atom + ( ( band + factor ).setParseAction( pushFirst ) | ZeroOrMore( ( expop + factor ).setParseAction( pushFirst ) ) )
term = factor + ZeroOrMore( ( multop + factor ).setParseAction( pushFirst ) )
expr << term + ZeroOrMore( ( addop + term ).setParseAction( pushFirst ) )
print(expr)
bnf = expr
pattern = bnf + StringEnd()
def test(s):
del exprstack[:]
bnf.parseString(s,parseAll=True)
print exprstack
test("avg(+10)")
test("v_1+8")
test("avg(v_1+10)+10")
これが私が欲しいものです。
私の関数はこのタイプです:
foo(v_1+v_2) = foo(v_1) + foo(v_2)
他の二項演算でも同じ動作が期待されます。パーサーにこれを自動的に行わせる方法がわかりません。