2012-08-09 41 views
5

Tôi đang cố gắng nghĩ ra một cách tốt để phân tích chuỗi bằng cách sử dụng JavaCC mà không nhầm lẫn khớp với một mã thông báo khác. Những chuỗi này có thể có dấu cách, chữ cái và số.Phân tích chuỗi với JavaCC

định danh của tôi và số thẻ như sau:

<IDENTIFIER: (["a"-"z", "A"-"Z"])+> 
<NUMBER: (["0"-"9"])+> 

chuỗi dấu hiệu hiện tại của tôi là:

<STRING: "\"" (<IDENTIFIER> | <NUMBERS> | " ")+ "\""> 

Lý tưởng nhất, tôi muốn chỉ lưu những thứ đó là bên trong dấu ngoặc kép. Tôi có một tập tin riêng biệt, trong đó tôi thực sự tiết kiệm các biến và giá trị. Tôi có nên xóa các trích dẫn trong đó không?

tôi ban đầu đã có một phương pháp trong các tập tin phân tích cú pháp như thế này:

variable=<INDENTIFIER> <ASSIGN> <QUOTE> message=<IDENTIFIER> <QUOTE> 
{File.saveVariable(variable.image, message.image);} 

Nhưng, như bạn có thể đoán, điều này đã không cho phép cho các không gian-hoặc số cho rằng vấn đề. Đối với các số nhận dạng như tên biến, tôi chỉ muốn cho phép các chữ cái.

Vì vậy, tôi chỉ muốn nhận được một số lời khuyên về cách tôi có thể đi về chụp chuỗi ký tự. Cụ thể, tôi muốn tạo các chuỗi như:

" hello", "hello ", " hello " and "\nhello", "hello\n", "\nhello\n" 

hợp lệ trong cú pháp của tôi.

+0

Bạn nên chấp nhận câu trả lời của DerMike - nó có vẻ khá hoàn hảo. –

Trả lời

10

Khi vượt qua " trình phân tích cú pháp đầu tiên của bạn muốn chuyển sang trạng thái STRING STATE và để nó tiếp theo (Bonus: unquoted) ".

Giống như:

TOKEN: 
{ 
    <QUOTE:"\""> : STRING_STATE 
} 

<STRING_STATE> MORE: 
{ 
    "\\" : ESC_STATE 
} 

<STRING_STATE> TOKEN: 
{ 
    <ENDQUOTE:<QUOTE>> : DEFAULT 
| <CHAR:~["\"","\\"]> 
} 

<ESC_STATE> TOKEN: 
{ 
    <CNTRL_ESC:["\"","\\","/","b","f","n","r","t"]> : STRING_STATE 
} 

Bạn có thể sử dụng như thế này:

/** 
* Match a quoted string. 
*/ 
String string() : 
{ 
    StringBuilder builder = new StringBuilder(); 
} 
{ 
    <QUOTE> (getChar(builder))* <ENDQUOTE> 
    { 
    return builder.toString(); 
    } 
} 

/** 
* Match char inside quoted string. 
*/ 
void getChar(StringBuilder builder): 
{ 
    Token t; 
} 
{ 
    (t = <CHAR> | t = <CNTRL_ESC>) 
    { 
    if (t.image.length() < 2) 
    { 
     // CHAR 
     builder.append(t.image.charAt(0)); 
    } 
    else if (t.image.length() < 6) 
    { 
     // ESC 
     char c = t.image.charAt(1); 
     switch (c) 
     { 
     case 'b': builder.append((char) 8); break; 
     case 'f': builder.append((char) 12); break; 
     case 'n': builder.append((char) 10); break; 
     case 'r': builder.append((char) 13); break; 
     case 't': builder.append((char) 9); break; 
     default: builder.append(c); 
     } 
    } 
    } 
} 

HTH.