2010-04-15 36 views
6

Tôi đang viết một trình phân tích cú pháp con xúc xắc tùy chỉnh (snicker nếu bạn phải) trong python. Về cơ bản, tôi muốn sử dụng đánh giá toán học tiêu chuẩn nhưng thêm 'd' điều hành:Cách đánh giá một biểu thức toán học tùy chỉnh trong Python

#xdy 
sum = 0 
for each in range(x): 
    sum += randInt(1, y) 
return sum 

Vì vậy, ví dụ, 1d6 2d6 + + 2d6-72 + 4d100 = (5) + (1 + 1) + (6 + 2) -72+ (5 + 39 + 38 + 59) = 84

Tôi đã sử dụng regex để thay thế tất cả 'd bằng tổng và sau đó sử dụng eval, nhưng regex của tôi bị phân tách khi xử lý dấu ngoặc đơn hai bên. Có cách nào nhanh hơn để thực hiện việc này hơn là triển khai phân tích cú pháp đệ quy của riêng tôi không? Có lẽ thêm một toán tử vào eval?

Chỉnh sửa: Tôi dường như đã đưa ra một ví dụ không tốt, vì ví dụ trên hoạt động với phiên bản hiện tại của tôi. Những gì tôi đang tìm kiếm là một số cách để đánh giá, nói, (5+ (6d6)) d (7-2 * (1d4)).
Bằng cách "tách rời", tôi chỉ có nghĩa là biểu thức chính quy hiện tại của tôi không thành công. Tôi đã quá mơ hồ về sự thất bại của tôi, xin lỗi vì sự nhầm lẫn. Đây là mã hiện tại của tôi:

def evalDice(roll_matchgroup): 
    roll_split = roll_matchgroup.group('roll').split('d') 
    print roll_split 
    roll_list = [] 

    for die in range(int(roll_split[0])): 
     roll = random.randint(1,int(roll_split[1])) 
     roll_list.append(roll) 

def EvalRoll(roll): 
    if not roll: return 0 
    rollPattern = re.compile('(?P<roll>\d*d\d+)') 
    roll_string = rollPattern.sub(evalDice, roll.lower()) 

cho điều này, "1d6 + 4d100" làm việc tốt, nhưng "(1d6 +4) D100" hoặc thậm chí "1d6 + 4d (100)" thất bại.

+0

Bạn có thể cho chúng tôi thấy những gì bạn đã thử và cách nó không thành công? –

+0

Kết thúc chỉ cần tạo một hàm trợ giúp đệ quy. Cảm ơn vì sự giúp đỡ! – taynaron

Trả lời

5

Python không cho phép bạn viết các toán tử mới, và bạn không thể làm dấu ngoặc đơn với ngôn ngữ thông thường. Bạn sẽ phải viết một trình phân tích cú pháp gốc đệ quy. Điều này khá đơn giản cho ngôn ngữ xúc xắc của bạn.

Hoặc, bạn có thể coopt một toán tử Python hiện có và sử dụng các công cụ phân tích cú pháp Pythons để chuyển văn bản thành một AST.

+0

Tôi nghĩ rằng các parens chỉ là một kết quả trung gian minh họa, không phải là một phần của chính DSL. Viết '1d6 + 2d6 + 2d6-72 + 4d100 = 84' sẽ không được giải thích. 1 cho đề xuất gốc rec, mặc dù. –

+0

Sau đó, tôi bối rối. Tại sao "regex [fall] của OP lại tách biệt khi giao dịch với dấu ngoặc đơn"? –

+1

Tôi khá mơ hồ hơn tôi nghĩ, xin lỗi. Ví dụ trên hoạt động tốt. Ý tôi là nếu bạn đặt dấu ngoặc đơn ở hai bên của d (như (4 + 2) d6) thì người phiên dịch không thể xử lý việc đánh giá điều đó. – taynaron

6

Bạn có thể sử dụng callback function với re.sub. Khi bạn làm theo các liên kết, tìm xuống đoạn bắt đầu với "Nếu repl là một chức năng ..."

import re 
import random 

def xdy(matchobj): 
    x,y=map(int,matchobj.groups()) 
    s = 0 
    for each in range(x): 
     s += random.randint(1, y) 
    return str(s) 
s='1d6+2d6+2d6-72+4d100' 
t=re.sub('(\d+)d(\d+)',xdy,s) 
print(t) 
# 5+10+8-72+197 
print(eval(t)) 
# 148 
0

này sử dụng eval, mà là khá khủng khiếp thực sự, nhưng ở đây bạn đi

>>> x = '1d6+2d6+2d6-72+4d100' 
>>> eval(re.sub(r'(\d+)d(\d+)',r'sum((random.randint(1,x) for x in \1 * [\2]))', x)) 

Một số lưu ý nhanh chóng:

này thay thế, chẳng hạn, 4d6 với sum((random.randint(1,x) for x in 4 * [6])).

4 * [6] cho danh sách [6,6,6,6].

((random.randint(1,x) for x in [6,6,6,6])) là máy phát tương đương với danh sách hiểu; cái cụ thể này sẽ trả lại bốn số ngẫu nhiên từ 1 đến 6.

2

Hãy xem thư viện PyParsing. Đặc biệt, trang examplessample khá gần với những gì bạn muốn:

dice2.py

Một phân tích cú pháp roll dice và đánh giá để đánh giá chuỗi như "4d20 + 5,5 + 4d6.takeHighest (3)" .

0

Trong Supybot dice plugin tôi phân tích sự biểu hiện với

r'(?P<sign>[+-])((?P<dice>\d*)d(?P<sides>\d+)|(?P<mod>\d+))' 

sau đó nhận được tổng số của mỗi con xúc xắc và một modifier tổng, cuộn chúng và nhận được kết quả tổng (Tôi muốn hiển thị tổng số của mỗi con xúc xắc) .

Các vấn đề liên quan