2009-12-01 34 views
16

Tôi đang tạo trình phân tích cú pháp cho ngôn ngữ lập trình ảo gọi là C-- (không phải ngôn ngữ C-- thực tế). Tôi đã lên sân khấu nơi tôi cần dịch ngữ pháp của ngôn ngữ sang một thứ gì đó mà Pyparsing có thể chấp nhận. Thật không may khi tôi đến để phân tích chuỗi đầu vào của tôi (đó là chính xác và không nên gây ra Pyparsing để lỗi) nó không phân tích cú pháp chính xác. Tôi lo sợ điều này là do lỗi trong ngữ pháp của tôi, nhưng khi tôi bắt đầu Pyparsing lần đầu tiên, tôi dường như không thể nhìn thấy nơi tôi đang đi sai.Gỡ lỗi Pyparsing Grammar

Tôi đã tải lên ngữ pháp mà tôi đang dịch từ here để mọi người đọc qua.

EDIT: Cập nhật với lời khuyên của Paul.

Đây là ngữ pháp Tôi hiện đã có (hai dòng đầu Cú pháp định nghĩa là khủng khiếp xấu của tôi, tôi biết):

# Lexical structure definition 
ifS = Keyword('if') 
elseS = Keyword('else') 
whileS = Keyword('while') 
returnS = Keyword('return') 
intVar = Keyword('int') 
voidKeyword = Keyword('void') 
sumdiff = Literal('+') | Literal('-') 
prodquot = Literal('*') | Literal('/') 
relation = Literal('<=') | Literal('<') | Literal('==') | \ 
      Literal('!=') | Literal('>') | Literal('=>') 
lbrace = Literal('{') 
rbrace = Literal('}') 
lparn = Literal('(') 
rparn = Literal(')') 
semi = Literal(';') 
comma = Literal(',') 
number = Word(nums) 
identifier = Word(alphas, alphanums) 

# Syntax definition 
term = '' 
statement = '' 
variable = intVar + identifier + semi 
locals  = ZeroOrMore(variable) 
expr  = term | OneOrMore(Group(sumdiff + term)) 
args  = ZeroOrMore(OneOrMore(Group(expr + comma)) | expr) 
funccall = Group(identifier + lparn + args + rparn) 
factor  = Group(lparn + expr + rparn) | identifier | funccall | number 
term  = factor | OneOrMore(prodquot + factor) 
cond  = Group(lparn + expr + relation + expr + rparn) 
returnState = Group(returnS + semi) | Combine(returnS + expr + semi) 
assignment = Group(identifier + '=' + expr + semi) 
proccall = Group(identifier + lparn + args + rparn + semi) 
block  = Group(lbrace + locals + statement + rbrace) 
iteration = Group(whileS + cond + block) 
selection = Group(ifS + cond + block) | Group(ifS + cond + block + elseS + block) 
statement = OneOrMore(proccall | assignment | selection | iteration | returnState) 
param  = Group(intVar + identifier) 
paramlist = OneOrMore(Combine(param + comma)) | param 
params  = paramlist | voidKeyword 
procedure = Group(voidKeyword + identifier + lparn + params + rparn + block) 
function = Group(intVar + identifier + lparn + params + rparn + block) 
declaration = variable | function | procedure 
program  = OneOrMore(declaration) 

Tôi muốn biết nếu có bất kỳ sai lầm tôi đã thực hiện việc dịch ngữ pháp và những cải tiến mà tôi có thể làm để làm cho nó đơn giản hóa trong khi tôn trọng ngữ pháp mà tôi đã đưa ra.

CHỈNH SỬA 2: Đã cập nhật để bao gồm lỗi mới.

Đây là chuỗi đầu vào tôi đang phân tích cú pháp:

int larger (int first , int second) { 
if (first > second) { 
return first ; 
} else { 
return second ; 
} 
} 

void main (void) { 
int count ; 
int sum ; 
int max ; 
int x ; 

x = input () ; 
max = x ; 
sum = 0 ; 
count = 0 ; 

while (x != 0) { 
count = count + 1 ; 
sum = sum + x ; 
max = larger (max , x) ; 
x = input () ; 
} 

output (count) ; 
output (sum) ; 
output (max) ; 
} 

Và đây là thông báo lỗi tôi nhận được khi chạy chương trình của tôi từ Terminal:

/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1156: SyntaxWarning: null string passed to Literal; use Empty() instead 
other = Literal(other) 
/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1258: SyntaxWarning: null string passed to Literal; use Empty() instead 
other = Literal(other) 
Expected ")" (at char 30), (line:6, col:26) 
None 
+0

Bạn có bất kỳ manh mối nào cho chúng tôi, chẳng hạn như thông báo lỗi nào bạn nhận được (nếu có)? Bạn nói "nó không phân tích cú pháp chính xác" nhưng làm thế nào để bạn biết điều đó? Có lỗi không? Nó tạo ra một AST không chính xác? Cần thêm thông tin. –

+0

Xin lỗi về điều đó. Tôi đã cập nhật câu hỏi của mình với chuỗi đầu vào mà tôi đang cố phân tích cú pháp và các thông báo lỗi tôi nhận được trong Terminal. – greenie

Trả lời

31

1) Thay đổi Literal("if")-Keyword("if") (và cứ như vậy, xuống đến Literal("void")), để tránh khớp với "if" hàng đầu của một biến có tên là "ifactor".

2) nums, alphas, và alphanums không biểu hiện, họ là chuỗi, có thể được sử dụng với các lớp Word để xác định một số bộ tiêu biểu của nhân vật khi định nghĩa "chữ" như "một số là một từ tạo thành nums "hoặc" số nhận dạng là từ bắt đầu bằng alpha, tiếp theo là số không hoặc nhiều chữ số. " Vì vậy, thay vì:

number = nums 
identifier = alphas + OneOrMore(alphanums) 

bạn muốn

number = Word(nums) 
identifier = Word(alphas, alphanums) 

3) Thay vì Combine, tôi nghĩ rằng bạn muốn Group. Sử dụng Combine khi bạn muốn mã thông báo phù hợp tiếp giáp với không có khoảng trắng xen kẽ, và sẽ nối các mã thông báo và trả về chúng dưới dạng một chuỗi. Combine thường được sử dụng trong những trường hợp như thế này:

realnum = Combine(Word(nums) + "." + Word(nums)) 

Without Combine, phân tích "3.14" sẽ quay trở lại danh sách các chuỗi ['3', '.', '14'], vì vậy chúng tôi thêm Combine để các kết quả phân tích cho realnum là '3.14' (mà sau đó bạn có thể vượt qua một hành động phân tích cú pháp để chuyển đổi thành giá trị thực thực tế 3.14). Combine s thực thi không có khoảng trắng xen kẽ cũng khiến chúng tôi vô tình phân tích cú pháp 'The answer is 3. 10 is too much.' và suy nghĩ "3. 10" đại diện cho một số thực.

4) Điều này không nên gây ra lỗi của bạn, nhưng chuỗi đầu vào của bạn có không gian bổ sung. Nếu bạn nhận được ngữ pháp của bạn làm việc, bạn sẽ có thể phân tích cú pháp "int x;" cũng như "int x ;".

Hy vọng một số gợi ý này giúp bạn tiếp tục. Bạn đã đọc bất kỳ bài viết hoặc hướng dẫn về pyparsing trực tuyến nào chưa? Và hãy xem qua các ví dụ trực tuyến. Bạn sẽ cần hiểu rõ cách Word, Literal, Combine, v.v. thực hiện các tác vụ phân tích cú pháp riêng lẻ của chúng.

5) Bạn đã triển khai sai định nghĩa đệ quy cho thuật ngữ và tuyên bố. Thay vì gán '' với họ, hãy viết:

term = Forward() 
statement = Forward() 

Sau đó, khi bạn đi để thực sự xác định chúng với các định nghĩa đệ quy của họ, sử dụng toán tử << (và chắc chắn kèm theo RHS trong () 's).

term << (... term definition ...) 
statement << (... statement definition ...) 

Bạn có thể tìm thấy một ví dụ về phân tích cú pháp đệ quy here, và một bài thuyết trình về cách sử dụng cơ bản pyparsing here - xem phần có tiêu đề "Phân tích Lists" để biết thêm bước-by-step về cách đệ quy được xử lý.

+0

Cảm ơn Paul. Tôi đã thay thế tất cả các trường hợp kết hợp với nhóm và bây giờ tôi nhận được một số lỗi khác nhau mà tôi nghĩ là có liên quan đến cách các quy tắc của tôi được viết chứ không phải là cú pháp tôi đã sử dụng. Tôi đã cập nhật bài đăng gốc của mình để phản ánh những thay đổi bạn đã đề xuất và lỗi mới mà tôi có. – greenie

+0

Tuyệt vời Paul, cảm ơn rất nhiều. Tôi ước tôi có thể +1 bạn nhiều hơn :) – greenie