Phân tích cú pháp trong JavaScript: tất cả các công cụ và thư viện bạn có thể sử dụng – cách phân tích cú pháp trong javascript

Chúng tôi trình bày và so sánh tất cả các lựa chọn thay thế khả thi mà bạn có thể sử dụng để phân tích cú pháp các ngôn ngữ trong JavaScript. Từ thư viện đến trình tạo trình phân tích cú pháp, chúng tôi cung cấp tất cả các tùy chọn

Bạn đang xem: cách phân tích cú pháp trong javascript

Đây là một bài viết tương tự như bài trước chúng tôi đã viết: < span> Phân tích cú pháp trong Java , vì vậy phần giới thiệu giống nhau. Chuyển đến chương 3 nếu bạn đã đọc nó.

Nếu bạn cần phân tích cú pháp một ngôn ngữ hoặc tài liệu, từ JavaScript, về cơ bản, có ba cách để giải quyết vấn đề:

  • sử dụng thư viện hiện có hỗ trợ ngôn ngữ cụ thể đó: ví dụ: thư viện để phân tích cú pháp XML
  • tự tay xây dựng trình phân tích cú pháp tùy chỉnh của riêng bạn
  • một công cụ hoặc thư viện để tạo trình phân tích cú pháp: ví dụ ANTLR, bạn có thể sử dụng để tạo trình phân tích cú pháp cho bất kỳ ngôn ngữ nào

Phân tích cú pháp: Công cụ và Thư viện


Nhận hướng dẫn vào hộp thư đến của bạn để đọc trên tất cả các thiết bị của bạn khi bạn có thời gian. Tìm hiểu về phân tích cú pháp trong Java, Python, C # và JavaScript

Thành công! Bây giờ hãy kiểm tra email của bạn để xác nhận đăng ký của bạn.

Sử dụng Thư viện Hiện có

Tùy chọn đầu tiên là tùy chọn tốt nhất cho các ngôn ngữ được hỗ trợ và nổi tiếng, như XML hoặc HTML. Một thư viện tốt thường bao gồm cả API để xây dựng và sửa đổi theo chương trình các tài liệu bằng ngôn ngữ đó. Đây thường là những gì bạn nhận được từ một trình phân tích cú pháp cơ bản. Vấn đề là những thư viện như vậy không quá phổ biến và chúng chỉ hỗ trợ những ngôn ngữ phổ biến nhất. Trong những trường hợp khác, bạn không gặp may.

Tự tay xây dựng trình phân tích cú pháp tùy chỉnh của riêng bạn

Bạn có thể cần chọn tùy chọn thứ hai nếu bạn có nhu cầu cụ thể. Cả hai đều có nghĩa là ngôn ngữ bạn cần phân tích cú pháp không thể được phân tích cú pháp bằng các trình tạo trình phân tích cú pháp truyền thống hoặc bạn có các yêu cầu cụ thể mà bạn không thể đáp ứng khi sử dụng trình tạo trình phân tích cú pháp điển hình. Ví dụ: vì bạn cần hiệu suất tốt nhất có thể hoặc tích hợp sâu giữa các thành phần khác nhau.

Một công cụ hoặc thư viện để tạo trình phân tích cú pháp

Trong tất cả các trường hợp khác, tùy chọn thứ ba phải là tùy chọn mặc định, vì là tùy chọn linh hoạt nhất và có thời gian phát triển ngắn hơn. Đó là lý do tại sao trong bài viết này, chúng tôi tập trung vào các công cụ và thư viện tương ứng với tùy chọn này.

Lưu ý: văn bản trong blockquote mô tả một chương trình đến từ tài liệu tương ứng

Chúng ta sẽ thấy:

  • các công cụ có thể tạo trình phân tích cú pháp có thể sử dụng được từ JavaScript (và có thể từ các ngôn ngữ khác)
  • Thư viện JavaScript để tạo trình phân tích cú pháp

Các công cụ có thể được sử dụng để tạo mã cho trình phân tích cú pháp được gọi là trình tạo trình phân tích cú pháp hoặc trình biên dịch trình biên dịch . Các thư viện tạo trình phân tích cú pháp được gọi là trình tổ hợp phân tích cú pháp .

Trình tạo phân tích cú pháp (hoặc tổ hợp phân tích cú pháp) không hề nhỏ: bạn cần một thời gian để học cách sử dụng chúng và không phải tất cả các loại trình tạo phân tích cú pháp đều phù hợp với mọi loại ngôn ngữ. Đó là lý do tại sao chúng tôi đã chuẩn bị một danh sách những cái được biết đến nhiều nhất trong số chúng, kèm theo một đoạn giới thiệu ngắn cho mỗi cái. Chúng tôi cũng đang tập trung vào một ngôn ngữ đích: JavaScript. Điều này cũng có nghĩa là (thông thường) bản thân trình phân tích cú pháp sẽ được viết bằng JavaScript.

Liệt kê tất cả các công cụ và thư viện có thể phân tích cú pháp cho tất cả các ngôn ngữ sẽ khá thú vị, nhưng không hữu ích. Đó là bởi vì sẽ có quá nhiều lựa chọn đơn giản và tất cả chúng ta sẽ bị lạc trong chúng. Bằng cách tập trung vào một ngôn ngữ lập trình, chúng tôi có thể cung cấp một so sánh giữa các quả táo và giúp bạn chọn một tùy chọn cho dự án của mình.

Những điều hữu ích cần biết về trình phân tích cú pháp

Để đảm bảo rằng tất cả các lập trình viên đều có thể truy cập danh sách này, chúng tôi đã chuẩn bị một giải thích ngắn gọn cho các thuật ngữ và khái niệm mà bạn có thể gặp khi tìm kiếm trình phân tích cú pháp. Chúng tôi không cố gắng cung cấp cho bạn những lời giải thích chính thức mà là những lời giải thích thực tế.

Cấu trúc của Trình phân tích cú pháp

Một trình phân tích cú pháp thường bao gồm hai phần: lexer, còn được gọi là máy quét hoặc trình phân tích cú pháp và trình phân tích cú pháp thích hợp. Không phải tất cả trình phân tích cú pháp đều áp dụng lược đồ hai bước này: một số trình phân tích cú pháp không phụ thuộc vào trình phân tích cú pháp. Chúng được gọi là trình phân tích cú pháp không cần máy quét.

Bộ lexer và bộ phân tích cú pháp hoạt động theo trình tự: bộ lexer quét đầu vào và tạo ra các mã thông báo phù hợp, bộ phân tích cú pháp sẽ quét các mã và tạo ra kết quả phân tích cú pháp.

Hãy xem ví dụ sau và tưởng tượng rằng chúng ta đang cố gắng phân tích cú pháp toán học.

 437 + 734 

Luồng đầu vào được trình phân tích cú pháp chuyển đổi thành Mã thông báo và sau đó trong AST

Lexer quét văn bản và tìm ‘4’, ‘3’, ‘7’ và sau đó là dấu cách ‘‘. Công việc của lexer là nhận ra rằng các ký tự đầu tiên tạo thành một mã thông báo loại NUM. Sau đó, lexer tìm thấy một ký hiệu ‘+’, tương ứng với mã thông báo thứ hai thuộc loại PLUS và cuối cùng nó tìm thấy một mã thông báo khác thuộc loại NUM.

Trình phân tích cú pháp thường sẽ kết hợp các mã thông báo do lexer tạo ra và nhóm chúng lại.

Các định nghĩa được sử dụng bởi lexers hoặc trình phân tích cú pháp được gọi là quy tắc hoặc sản xuất. Quy tắc lexer sẽ chỉ định rằng một chuỗi các chữ số tương ứng với mã thông báo loại NUM, trong khi quy tắc phân tích cú pháp sẽ chỉ định rằng một chuỗi mã thông báo loại NUM, CỘNG, NUM tương ứng với một biểu thức.

Trình phân tích cú pháp không máy quét khác vì chúng xử lý trực tiếp văn bản gốc, thay vì xử lý danh sách mã thông báo do lexer tạo ra.

Hiện nay, việc tìm các bộ có thể tạo cả lexer và parser là một điều điển hình. Trước đây, thay vào đó, việc kết hợp hai công cụ khác nhau trở nên phổ biến hơn: một để sản xuất lexer và một để sản xuất trình phân tích cú pháp. Đây là ví dụ như trường hợp của lex & amp; cặp đôi yacc: lex tạo ra lexer, trong khi yacc tạo ra trình phân tích cú pháp.

Cây phân tích cú pháp và cây cú pháp tóm tắt

Có hai thuật ngữ có liên quan và đôi khi chúng được sử dụng thay thế cho nhau: cây phân tích cú pháp và cây cú pháp tóm tắt (AST).

Về mặt khái niệm, chúng rất giống nhau:

  • chúng đều là cây : có một gốc đại diện cho toàn bộ đoạn mã được phân tích cú pháp. Sau đó, có các cây con nhỏ hơn đại diện cho các phần mã trở nên nhỏ hơn cho đến khi các mã thông báo đơn lẻ xuất hiện trong cây
  • sự khác biệt là mức độ trừu tượng: cây phân tích cú pháp chứa tất cả các mã thông báo xuất hiện trong chương trình và có thể là một tập hợp của các quy tắc trung gian. Thay vào đó, AST là một phiên bản đánh bóng của cây phân tích cú pháp, nơi thông tin có thể được lấy ra hoặc không quan trọng để hiểu đoạn mã sẽ bị loại bỏ

Trong AST, một số thông tin bị mất, chẳng hạn như các chú thích và biểu tượng nhóm (dấu ngoặc đơn) không được thể hiện. Những thứ như nhận xét là không cần thiết đối với một chương trình và các ký hiệu nhóm được xác định ngầm theo cấu trúc của cây.

Cây phân tích cú pháp là một đại diện của mã gần với cú pháp cụ thể hơn. Nó cho thấy nhiều chi tiết về việc triển khai trình phân tích cú pháp. Ví dụ, thường một quy tắc tương ứng với loại nút. Cây phân tích cú pháp thường được người dùng chuyển đổi theo AST, có thể nhờ một số trợ giúp từ trình tạo phân tích cú pháp.

Biểu diễn đồ họa của AST trông như thế này.

Đôi khi bạn có thể muốn bắt đầu tạo một cây phân tích cú pháp và sau đó lấy từ nó một AST. Điều này có thể có ý nghĩa vì cây phân tích cú pháp dễ sản xuất hơn cho trình phân tích cú pháp (nó là đại diện trực tiếp của quá trình phân tích cú pháp) nhưng AST đơn giản hơn và dễ xử lý hơn bằng các bước sau. Theo các bước sau, chúng tôi muốn nói đến tất cả các thao tác mà bạn có thể muốn thực hiện trên cây: xác thực mã, diễn giải, biên dịch, v.v.

Ngữ pháp

Ngữ pháp là một mô tả chính thức của một ngôn ngữ có thể được sử dụng để nhận dạng cấu trúc của nó.

Nói một cách đơn giản là danh sách các quy tắc xác định cách mỗi cấu trúc có thể được tạo ra. Ví dụ: quy tắc cho câu lệnh if có thể chỉ định rằng nó phải bắt đầu bằng từ khóa “if”, theo sau là dấu ngoặc đơn bên trái, một biểu thức, dấu ngoặc đơn bên phải và một câu lệnh.

Một quy tắc có thể tham chiếu các quy tắc hoặc loại mã thông báo khác. Trong ví dụ về câu lệnh if, từ khóa “if”, dấu ngoặc đơn bên trái và bên phải là các loại mã thông báo, trong khi biểu thức và câu lệnh là các tham chiếu đến các quy tắc khác.

Định dạng được sử dụng nhiều nhất để mô tả ngữ pháp là Biểu mẫu Backus-Naur (BNF) , cũng có nhiều biến thể, bao gồm cả Biểu mẫu Backus-Naur mở rộng . Biến thể Mở rộng có lợi thế là bao gồm một cách đơn giản để biểu thị các lần lặp lại. Một quy tắc điển hình trong ngữ pháp Backus-Naur trông giống như sau:

 & lt; biểu tượng & gt; :: = __expression__ 

Ký hiệu & lt; & gt; thường không có giá trị, có nghĩa là nó có thể được thay thế bằng nhóm phần tử ở bên phải, __expression__ . Phần tử __expression__ có thể chứa các ký hiệu hoặc ký hiệu đầu cuối danh nghĩa khác. Ký hiệu đầu cuối chỉ đơn giản là những ký hiệu không xuất hiện dưới dạng & lt; biểu tượng & gt; ở bất kỳ đâu trong ngữ pháp. Ví dụ điển hình về ký hiệu đầu cuối là một chuỗi ký tự, chẳng hạn như “lớp”.

Quy tắc đệ quy trái

Trong ngữ cảnh phân tích cú pháp, một tính năng quan trọng là hỗ trợ các quy tắc đệ quy trái. Điều này có nghĩa là một quy tắc có thể bắt đầu bằng một tham chiếu đến chính nó. Tham chiếu này cũng có thể là gián tiếp.

Hãy xem xét các phép toán số học ví dụ. Một phép bổ sung có thể được mô tả là hai (các) biểu thức được phân tách bằng ký hiệu dấu cộng (+), nhưng một biểu thức cũng có thể chứa các phép bổ sung khác.

 add :: = biểu thức '+' biểu thức
nhân :: = biểu thức '*' biểu thức
// một biểu thức có thể là một phép cộng hoặc một phép nhân hoặc một số
biểu thức :: = bổ sung | phép nhân | // một số 

Mô tả này cũng khớp với nhiều phép cộng như 5 + 4 + 3. Đó là vì nó có thể được hiểu là biểu thức (5) (‘+’) biểu thức (4 + 3) . Và bản thân 4 + 3 có thể được chia thành hai thành phần của nó.

Vấn đề là loại quy tắc này có thể không được sử dụng với một số trình tạo phân tích cú pháp. Giải pháp thay thế là một chuỗi dài các biểu thức cũng quan tâm đến mức độ ưu tiên của các toán tử.

Một số trình tạo phân tích cú pháp hỗ trợ quy tắc đệ quy trái trực tiếp, nhưng không hỗ trợ quy tắc gián tiếp.

Các loại ngôn ngữ và ngữ pháp

Chúng tôi chủ yếu quan tâm đến hai loại ngôn ngữ có thể được phân tích cú pháp bằng trình tạo trình phân tích cú pháp: ngôn ngữ thông thường và ngôn ngữ không có ngữ cảnh. Chúng tôi có thể cung cấp cho bạn định nghĩa chính thức theo Chomsky phân cấp ngôn ngữ , nhưng nó sẽ không hữu ích như vậy. Thay vào đó, hãy xem xét một số khía cạnh thực tế.

Xem Thêm  Chuỗi JavaScript chứa: Hướng dẫn từng bước - kiểm tra xem có chứa chuỗi javascript không

Một ngôn ngữ thông thường có thể được xác định bằng một loạt các cụm từ thông dụng, trong khi ngôn ngữ không có ngữ cảnh cần thêm một thứ gì đó. Một nguyên tắc chung đơn giản là nếu ngữ pháp của một ngôn ngữ có các phần tử đệ quy thì nó không phải là một ngôn ngữ thông thường. Ví dụ: như chúng tôi đã nói ở nơi khác, HTML không phải là ngôn ngữ thông thường . Trên thực tế, hầu hết các ngôn ngữ lập trình là ngôn ngữ không có ngữ cảnh.

Thông thường đối với một loại ngôn ngữ tương ứng với cùng một loại ngữ pháp. Điều đó có nghĩa là có ngữ pháp thông thường và ngữ pháp không có ngữ cảnh tương ứng với các ngôn ngữ thông thường và không có ngữ cảnh. Nhưng để làm phức tạp vấn đề, có một loại ngữ pháp tương đối mới (được tạo ra vào năm 2004), được gọi là Parsing Expression Grammar (PEG). Những ngữ pháp này mạnh ngang ngửa với ngữ pháp Không có ngữ cảnh, nhưng theo tác giả của chúng, chúng mô tả ngôn ngữ lập trình một cách tự nhiên hơn.

Sự khác biệt giữa PEG và CFG

Sự khác biệt chính giữa PEG và CFG là thứ tự các lựa chọn có ý nghĩa trong PEG, nhưng không có ý nghĩa trong CFG. Nếu có nhiều cách hợp lệ có thể có để phân tích cú pháp đầu vào, thì một CFG sẽ không rõ ràng và do đó sai. Thay vào đó với PEG, lựa chọn áp dụng đầu tiên sẽ được chọn và điều này sẽ tự động giải quyết một số điều không rõ ràng.

Một điểm khác biệt khác là PEG sử dụng trình phân tích cú pháp không cần máy quét: chúng không cần giai đoạn phân tích từ vựng hoặc từ vựng riêng biệt.

Theo truyền thống, cả PEG và một số CFG đều không thể xử lý các quy tắc đệ quy bên trái, nhưng một số công cụ đã tìm ra giải pháp thay thế cho điều này. Bằng cách sửa đổi thuật toán phân tích cú pháp cơ bản hoặc bằng cách để công cụ tự động viết lại quy tắc đệ quy trái theo cách không đệ quy. Một trong hai cách này đều có nhược điểm: hoặc bằng cách làm cho trình phân tích cú pháp được tạo ít dễ hiểu hơn hoặc làm xấu đi hiệu suất của nó. Tuy nhiên, trong điều kiện thực tế, ưu điểm của việc phát triển dễ dàng và nhanh hơn nhiều hơn nhược điểm.

Nếu bạn muốn biết thêm về lý thuyết phân tích cú pháp, bạn nên đọc Hướng dẫn phân tích cú pháp: Thuật toán và thuật ngữ .

Trình tạo phân tích cú pháp

Quy trình làm việc cơ bản của công cụ trình tạo trình phân tích cú pháp khá đơn giản: bạn viết ngữ pháp xác định ngôn ngữ hoặc tài liệu và bạn chạy công cụ để tạo trình phân tích cú pháp có thể sử dụng được từ mã JavaScript của bạn.

Trình phân tích cú pháp có thể tạo ra AST mà bạn có thể phải tự xem qua hoặc bạn có thể duyệt với các lớp bổ sung sẵn sàng sử dụng, chẳng hạn như Người nghe hoặc Khách truy cập . Thay vào đó, một số công cụ cung cấp cơ hội nhúng mã bên trong ngữ pháp được thực thi mỗi khi quy tắc cụ thể được khớp.

Thông thường, bạn cần một thư viện thời gian chạy và / hoặc chương trình để sử dụng trình phân tích cú pháp đã tạo.

Thông thường (Lexer)

Các công cụ phân tích ngôn ngữ thông thường thường được gọi là lexers.

Lexer

Lexer là lexer tuyên bố được mô phỏng theo flex. Mặc dù mô tả công bằng hơn sẽ là một từ ngắn dựa trên RegExp . Tài liệu có vẻ tối thiểu, chỉ với một vài ví dụ, nhưng toàn bộ là 147 dòng mã, vì vậy nó thực sự toàn diện.

Tuy nhiên, trong một vài dòng có thể hỗ trợ một số điều thú vị và nó có vẻ khá phổ biến và dễ sử dụng. Một điều là nó hỗ trợ RingoJS , một nền tảng JavaScript trên JVM. Một cái khác là tích hợp với Jison, bản sao Bison trong JavaScript. Nếu bạn kiềm chế được kỳ vọng của mình, đó có thể là một công cụ hữu ích.

Không có ngữ pháp, bạn chỉ sử dụng một hàm để xác định mẫu RegExp và hành động sẽ được thực thi khi mẫu được khớp. Vì vậy, nó là sự kết hợp giữa máy tạo lexer và máy tổ hợp lexer. Bạn không thể kết hợp các hàm lexer khác nhau, như trong bộ tổ hợp lexer, nhưng lexer mà nó chỉ được tạo động trong thời gian chạy, vì vậy nó cũng không phải là trình tạo lexer thích hợp.

 var lexer = new Lexer;

var chars = lines = 0;

lexer.addRule (/ n /, function () {
    dòng ++;
    ký tự ++;
});
    
lexer.addRule (/./, function () {
    ký tự ++;
});
    
lexer.setInput ("Xin chào Thế giới! n Xin chào các Ngôi sao! n!")
    
lexer.lex (); 

Không có ngữ cảnh

Hãy xem các công cụ tạo trình phân tích cú pháp Miễn phí theo ngữ cảnh.

ANTLR

ANTLR là trình tạo trình phân tích cú pháp tuyệt vời được viết bằng Java cũng có thể tạo trình phân tích cú pháp cho JavaScript và nhiều ngôn ngữ khác. Ngoài ra còn có một phiên bản beta cho TypeScript từ cùng một người tạo ra phiên bản C # được tối ưu hóa. ANTLR dựa trên thuật toán LL mới do tác giả phát triển và được mô tả trong bài báo này: Phân tích cú pháp LL thích ứng (*): Sức mạnh của phân tích động (PDF) .

Nó khá phổ biến vì có nhiều tính năng hữu ích: ví dụ: phiên bản 4 hỗ trợ các quy tắc đệ quy trái trực tiếp. Tuy nhiên, giá trị gia tăng thực sự của một cộng đồng rộng lớn đó là một lượng lớn ngữ pháp sẵn có .

Nó cung cấp hai cách để xem AST, thay vì nhúng các hành động vào ngữ pháp: khách truy cập và người nghe. Cách đầu tiên phù hợp khi bạn phải thao tác hoặc tương tác với các phần tử của cây, trong khi cách thứ hai hữu ích khi bạn chỉ cần làm điều gì đó khi một quy tắc được khớp.

Ngữ pháp điển hình được chia thành hai phần: quy tắc lexer và quy tắc phân tích cú pháp. Sự phân chia là ngầm định, vì tất cả các quy tắc bắt đầu bằng một ký tự hoa là các quy tắc dài hơn, trong khi các quy tắc bắt đầu bằng một ký tự thường là các quy tắc phân tích cú pháp. Ngoài ra, ngữ pháp từ vựng và phân tích cú pháp có thể được xác định trong các tệp riêng biệt.

 ngữ pháp đơn giản;

cơ bản: NAME ':' NAME;

TÊN: [a-zA-Z] *;

BÌNH LUẬN : '/*' .*? '* /' - & gt; bỏ qua; 

Nếu bạn muốn tìm hiểu cách sử dụng ANTLR, bạn có thể xem hướng dẫn ANTLR khổng lồ này mà chúng tôi đã viết. Nếu bạn đã sẵn sàng trở thành nhà phát triển ANTLR chuyên nghiệp, bạn có thể mua khóa học video của chúng tôi để Xây dựng trình phân tích cú pháp và ngôn ngữ chuyên nghiệp sử dụng ANTLR . Khóa học được giảng dạy bằng Python, nhưng mã nguồn cũng có sẵn bằng JavaScript.

APG

APG là trình phân tích cú pháp gốc đệ quy sử dụng một biến thể của BNF tăng cường mà họ gọi là Superset Augmented BNF. ABNF là một biến thể cụ thể của BNF được thiết kế để hỗ trợ tốt hơn giao thức truyền thông hai chiều. APG cũng hỗ trợ các toán tử bổ sung, như các vị từ cú pháp và các hàm đối sánh do người dùng xác định tùy chỉnh.

Nó có thể tạo trình phân tích cú pháp trong C / C ++, Java và JavaScript. Hỗ trợ cho ngôn ngữ cuối cùng có vẻ cao hơn và cập nhật hơn: nó có thêm một số tính năng và nó được cập nhật gần đây hơn. Trên thực tế, tài liệu cho biết nó được thiết kế để có giao diện của JavaScript RegExp.

Bởi vì nó dựa trên ABNF, nó đặc biệt phù hợp để phân tích ngôn ngữ của nhiều đặc điểm kỹ thuật Internet và trên thực tế, là trình phân tích được lựa chọn cho một số các công ty viễn thông lớn.

Ngữ pháp APG rất rõ ràng và dễ hiểu.

 // ví dụ từ hướng dẫn của tác giả của công cụ có sẵn tại đây
// https://www.sitepoint.com/alternative-to-regular-expressions/
phone-number = ["("] mã vùng sep office-code sep người đăng ký
mã vùng = 3digit; 3 chữ số
office-code = 3digit; 3 chữ số
người đăng ký = 4digit; 4 chữ số
sep = * 3 (% d32-47 /% d58-126 /% d9); 0-3 ASCII không phải chữ số
chữ số =% d48-57; 0-9 

Jison

Jison tạo các trình phân tích cú pháp từ dưới lên trong JavaScript. API của nó tương tự như Bison’s, do đó có tên.

Mặc dù tên Jison cũng có thể thay thế flex, vì vậy bạn không cần phải dùng lexer riêng. Mặc dù bạn có thể sử dụng một hoặc xây dựng lexer tùy chỉnh của riêng bạn. Tất cả những gì bạn cần là một đối tượng có các chức năng setInput lex . Nó có thể nhận dạng tốt nhất các ngôn ngữ được mô tả bởi ngữ pháp LALR (1), mặc dù nó cũng có các chế độ cho LR (0), SLR (1).

Trình phân tích cú pháp được tạo không yêu cầu thành phần thời gian chạy, bạn có thể sử dụng nó như một phần mềm độc lập.

Nó có một tài liệu đủ tốt với một vài ví dụ và thậm chí là một phần để thử ngữ pháp của bạn trực tuyến. Mặc dù đôi khi nó dựa vào sách hướng dẫn của Bison để đề cập đến việc thiếu tài liệu của riêng mình.

Có thể nhập ngữ pháp Jison bằng định dạng JSON tùy chỉnh hoặc theo kiểu Bison. Cả hai đều yêu cầu bạn sử dụng các hành động được nhúng nếu bạn muốn thực hiện điều gì đó khi một quy tắc được khớp. Ví dụ sau ở định dạng JSON tùy chỉnh.

 // ví dụ từ tài liệu
{
   "comment": "JSON Math Parser",
   // Các bình luận JavaScript cũng hoạt động

   "lex": {
      "quy tắc": [
         ["s +", "/ * bỏ qua khoảng trắng * /"],
         ["[0-9] + (?:. [0-9] +)? B", "return 'NUMBER'"],
         ["*",                     "trở về '*'"],
         ["/",                     "trở về '/'"],
         ["-",                       "trở về '-'"],
         ["+", "return '+'"],
         [..] // bỏ qua một số phần
      ]
   },

   "toán tử": [
      ["left", "+", "-"],
      ["bên trái", "*", "/"],
      ["left", "UMINUS"]
      [..] // bỏ qua một số phần
   ],

   "bnf": {
      "biểu thức": [["e EOF", "return $ 1"]],

      "e": [
         ["e + e", "$$ = $ 1 + $ 3"],
         ["e - e", "$$ = $ 1- $ 3"],
         ["- e", "$$ = - $ 2", {"Pre": "UMINUS"}],
         ["NUMBER", "$$ = Number (yytext)"],
         [..] // bỏ qua một số phần
      ]
   }
}

rất phổ biến và được nhiều dự án sử dụng, bao gồm CoffeeScript và Handlebars.js.

Nearley

nearley sử dụng thuật toán phân tích cú pháp Earley được bổ sung với các tính năng tối ưu hóa của Joop Leo để phân tích cú pháp các cấu trúc dữ liệu phức tạp một cách dễ dàng. nearley rất nhanh và thực sự mạnh mẽ. Nó có thể phân tích cú pháp theo nghĩa đen bất cứ thứ gì bạn ném vào nó.

Thuật toán Earley được thiết kế để dễ dàng xử lý tất cả các ngữ pháp, kể cả các ngữ pháp đệ quy trái và không rõ ràng. Về cơ bản, ưu điểm chính của nó là nó không bao giờ thất bại thảm hại. Mặt khác, nó có thể chậm hơn các thuật toán phân tích cú pháp khác. Gần như bản thân nó cũng có thể phát hiện một số ngữ pháp không rõ ràng. Nó cũng có thể báo cáo nhiều kết quả trong trường hợp đầu vào không rõ ràng.

Ngữ pháp Nearley là văn bản được viết trong tệp .ne có thể bao gồm mã tùy chỉnh. Một quy tắc có thể bao gồm một hành động được nhúng, mà tài liệu này gọi là một chức năng xử lý hậu kỳ. Bạn cũng có thể sử dụng lexer tùy chỉnh.

 # từ các ví dụ trong Gần
# csv.ne

@ {%
var appendItem = function (a, b) {return function (d) {return d [a] .concat ([d [b]]); }};
var appendItemChar = function (a, b) {return function (d) {return d [a] .concat (d [b]); }};
var void = function (d) {return []; };
var voidStr = function (d) {return ""; };
%}

tệp - & gt; header newline lines {% function (d) {return {header: d [0], rows: d [2]}; }%}
# id là một hàm tiền xử lý đặc biệt trả về mã thông báo đầu tiên trong trận đấu
tiêu đề - & gt; hàng {% id%}

hàng - & gt; hàng ngang
                   | hàng dòng mới hàng {% appendItem (0,2)%}

hàng - & gt; đồng ruộng
                   | row "," trường {% appendItem (0,2)%}

trường - & gt; unquoted_field {% id%}
                   | "" "quote_field" "" {% function (d) {return d [1]; }%}

quote_field - & gt; null {% blankStr%}
                   | quote_field quote_field_char {% appendItemChar (0,1)%}

quote_field_char - & gt; [^ "] {% id%}
                   | "" "" "" {% function (d) {return "" ";}%}

unquoted_field - & gt; null {% blankStr%}
                   | unquoted_field char {% appendItemChar (0,1)%}

char - & gt; [^ nr ",] {% id%}

dòng mới - & gt; "r" "n" {% trống%} ca
                   | "r" | "n" {% trống%}

Một tính năng thú vị khác là bạn có thể tạo mã thông báo tùy chỉnh. Bạn có thể xác định chúng bằng cách sử dụng thư viện mã hóa, nghĩa đen hoặc hàm kiểm tra. Hàm kiểm tra phải trả về true nếu văn bản tương ứng với mã thông báo cụ thể đó.

 @ {%
var print_tok = {Lite: "print"};
var number_tok = {test: function (x) {return x.constructor === Số; }}
%}

chính - & gt; % print_tok% number_tok 

Nearley bao gồm các công cụ để gỡ lỗi và hiểu trình phân tích cú pháp của bạn. Ví dụ: Unparser có thể tự động tạo các chuỗi ngẫu nhiên được trình phân tích cú pháp của bạn coi là đúng. Điều này rất hữu ích để kiểm tra trình phân tích cú pháp của bạn chống lại nhiễu ngẫu nhiên hoặc thậm chí để tạo dữ liệu từ một lược đồ (ví dụ: địa chỉ email ngẫu nhiên). Nó cũng bao gồm một công cụ để tạo SVG sơ đồ đường sắt : một cách đồ họa để trình bày ngữ pháp.

Xem Thêm  Camera Hành Trình Gopro Cũ - Mới, Chính Hãng, Giá Rẻ Toàn quốc - chotot vb

Sơ đồ đường sắt Sơ đồ đường sắt từ bản trình diễn tài liệu

Trình phân tích cú pháp Nearley yêu cầu thời gian chạy của Nearley.

Tài liệu Nearley là một tổng quan tốt về những gì có sẵn và cũng có một sân chơi của bên thứ ba để thử ngữ pháp trực tuyến. Nhưng bạn sẽ không tìm thấy lời giải thích đầy đủ về tất cả các tính năng.

PEG

Sau khi bộ phân tích cú pháp CFG là lúc để xem bộ phân tích cú pháp PEG có sẵn cho JavaScript.

Tán

Canopy là trình biên dịch phân tích cú pháp nhắm mục tiêu đến Java, JavaScript, Python và Ruby. Nó lấy một tệp mô tả ngữ pháp biểu thức phân tích cú pháp và biên dịch nó thành một mô-đun phân tích cú pháp trong ngôn ngữ đích. Các trình phân tích cú pháp được tạo không phụ thuộc thời gian chạy vào chính Canopy.

Nó cũng cung cấp khả năng truy cập dễ dàng vào các nút cây phân tích cú pháp.

Ngữ pháp Canopy có tính năng gọn gàng là sử dụng chú thích hành động để sử dụng mã tùy chỉnh trong trình phân tích cú pháp. Trong điều kiện thực tế. bạn chỉ cần viết tên của một hàm bên cạnh một quy tắc và sau đó bạn triển khai hàm trong mã nguồn của mình.

 // các hành động được thêm vào trước bởi%
bản đồ ngữ pháp
  bản đồ & lt; - "{" string ":" value "}"% make_map
  chuỗi & lt; - "'" [^'] * "'"% make_string
  giá trị & lt; - danh sách / số
  danh sách & lt; - "[" value ("," value) * "]"% make_list
  số & lt; - [0-9] +% make_number 

Tệp JavaScript chứa mã hành động.

 var maps = request ('./ maps');

var action = {
  make_map: function (input, start, end, các phần tử) {
    var map = {};
    map [Elements [1]] = Elements [3];
    trả lại bản đồ;
  },
  [..]
}; 

Ohm là trình tạo phân tích cú pháp bao gồm thư viện và ngôn ngữ dành riêng cho miền

Ngữ pháp Ohm được xác định ở định dạng tùy chỉnh có thể được đặt trong một tệp riêng biệt hoặc trong một chuỗi. Tuy nhiên, trình phân tích cú pháp được tạo động chứ không phải bằng một công cụ riêng biệt. Theo nghĩa đó, nó hoạt động giống như một thư viện phân tích cú pháp hơn là một trình tạo phân tích cú pháp truyền thống.

Một chức năng trợ giúp để tạo AST được bao gồm trong số các tính năng bổ sung.

Trong Ohm, ngữ pháp xác định một ngôn ngữ và các hành động ngữ nghĩa chỉ định những việc cần làm với các đầu vào hợp lệ trong ngôn ngữ đó

Ngữ pháp được tách biệt hoàn toàn khỏi các hành động ngữ nghĩa. Điều này đơn giản hóa tính di động và khả năng đọc và cho phép hỗ trợ các ngôn ngữ khác nhau với cùng một ngữ pháp. Hiện tại Ohm chỉ hỗ trợ JavaScript, nhưng nhiều ngôn ngữ hơn được lên kế hoạch cho tương lai. Ngữ pháp điển hình sau đó rõ ràng và dễ đọc.

 Số học {
  Hết hạn
    = AddExp

  AddExp
    = AddExp "+" PriExp - cộng
    | AddExp "-" PriExp - dấu trừ
    | PriExp

  PriExp
    = "(" Exp ")" - dấu ngoặc
    | con số

  con số
    = chữ số +
} 

Các hành động ngữ nghĩa có thể được triển khai bằng một API đơn giản. Về mặt thực tế, mô hình này hoạt động giống như mô hình khách truy cập với sự khác biệt là dễ dàng xác định các nhóm hành động ngữ nghĩa hơn.

 var semantics = g.createSemantics (). addOperation ('eval', {
  Exp: function (e) {
    trả về e.eval ();
  },
  AddExp: function (e) {
    trả về e.eval ();
  },
  AddExp_plus: function (left, op, right) {
    trả về left.eval () + right.eval ();
  },
  AddExp_minus: function (left, op, right) {
    trả về left.eval () - right.eval ();
  },
  PriExp: function (e) {
    trả về e.eval ();
  },
  PriExp_paren: function (open, exp, close) {
    trả về exp.eval ();
  },
  number: function (ký tự) {
    return parseInt (this.sourceString, 10);
  },
});
var match = g.match ('1 + (2 - 3) + 4');
console.log (ngữ nghĩa (khớp) .eval ()); 

Để hỗ trợ gỡ lỗi, Ohm có một dấu vết văn bản và trình hiển thị đồ họa (đang hoạt động). Bạn có thể xem trình hiển thị đồ họa tại nơi làm việc và kiểm tra ngữ pháp trong trình chỉnh sửa tương tác .

Tài liệu này không tệ lắm, mặc dù bạn phải vào thư mục doc để tìm. Không có hướng dẫn, nhưng có một vài ví dụ và tài liệu tham khảo. Đặc biệt, tài liệu đề xuất đọc một ví dụ Toán học được nhận xét tốt.

PEG.js

PEG.js là trình tạo trình phân tích cú pháp đơn giản cho JavaScript tạo ra trình phân tích cú pháp nhanh với báo cáo lỗi xuất sắc.

PEG.js có thể hoạt động như một trình tạo trình phân tích cú pháp truyền thống và tạo trình phân tích cú pháp bằng một công cụ hoặc có thể tạo một trình phân tích cú pháp bằng cách sử dụng ngữ pháp được xác định trong mã. Nó hỗ trợ các bộ tải mô-đun khác nhau (ví dụ: AMD, CommonJS, v.v.).

PEG.js có một trình soạn thảo trực tuyến gọn gàng cho phép viết ngữ pháp, kiểm tra trình phân tích cú pháp đã tạo và tải xuống.

Ngữ pháp PEG.js thường được viết trong tệp .pegjs và có thể bao gồm các hành động được nhúng, mã khởi tạo tùy chỉnh và các vị từ ngữ nghĩa. Điều đó có nghĩa là các chức năng xác định xem một kết hợp cụ thể có được kích hoạt hay không.

 // ví dụ từ tài liệu
{
  function makeInteger (o) {
    return parseInt (o.join (""), 10);
  }
}

bắt đầu
  = phụ gia

phụ gia
  = left: phép nhân "+" right: phép cộng {return left + right; }
  / nhân

nhân
  = left: primary "*" right: phép nhân {return left * right; }
  / sơ đẳng

sơ đẳng
  = số nguyên
  / "(" additive: additive ")" {return additive; }

số nguyên "số nguyên"
  = chữ số: [0-9] + {return makeInteger (chữ số); } 

Tài liệu này đủ tốt, có một vài ngữ pháp ví dụ, nhưng không có sẵn hướng dẫn. Sự phổ biến của dự án đã dẫn đến sự phát triển của công cụ của bên thứ ba, chẳng hạn như một công cụ để tạo sơ đồ đường ray và plugin , chẳng hạn như một công cụ để tạo trình phân tích cú pháp TypeScrypt.

Waxeye

Waxeye là trình tạo trình phân tích cú pháp dựa trên việc phân tích cú pháp ngữ pháp biểu thức (PEG). Nó hỗ trợ C, Java, Javascript, Python, Ruby và Scheme.

Waxeye có thể tạo điều kiện thuận lợi cho việc tạo AST bằng cách xác định các nút trong ngữ pháp sẽ không được đưa vào cây được tạo. Điều đó khá hữu ích, nhưng một nhược điểm của Waxeye là nó chỉ tạo ra một AST. Theo nghĩa là không có cách nào để tự động thực hiện một hành động khi bạn khớp với một nút. Bạn phải duyệt và thực hiện những gì bạn cần theo cách thủ công.

Một tác dụng phụ tích cực của hạn chế này là ngữ pháp dễ đọc và sạch sẽ. Chúng cũng độc lập với bất kỳ ngôn ngữ nào.

 // từ sách hướng dẫn

calc & lt; - ws tổng

sum & lt; - prod * ([+ -] ws prod)

prod & lt; - unary * ([* /] ws unary)

một ngôi & lt; = '-' là một ngôi
       | : '(' ws sum: ')' ws
       | num

num & lt; - + [0-9]? ('.' + [0-9]) ws

ws & lt ;: * [tnr] 

Một tính năng cụ thể của Waxeye là nó cung cấp một số trợ giúp để biên soạn các ngữ pháp khác nhau với nhau và sau đó nó tạo điều kiện thuận lợi cho mô đun. Ví dụ: bạn có thể tạo một ngữ pháp chung cho các số nhận dạng, ngữ pháp này thường giống nhau ở nhiều ngôn ngữ.

Waxeye có một tài liệu tuyệt vời dưới dạng sổ tay giải thích các khái niệm cơ bản và cách sử dụng công cụ cho tất cả các ngôn ngữ mà nó hỗ trợ. Có một số ngữ pháp mẫu.

Waxeye dường như vẫn được duy trì, nhưng nó không được phát triển tích cực.

Trình kết hợp phân tích cú pháp

Chúng cho phép bạn tạo trình phân tích cú pháp đơn giản bằng mã JavaScript, bằng cách kết hợp các hàm đối sánh mẫu khác nhau, tương đương với các quy tắc ngữ pháp. Chúng thường được coi là phù hợp nhất cho các nhu cầu phân tích cú pháp đơn giản hơn. Vì chúng chỉ là thư viện JavaScript, bạn có thể dễ dàng giới thiệu chúng vào dự án của mình: bạn không cần bất kỳ bước tạo cụ thể nào và bạn có thể viết tất cả mã của mình trong trình soạn thảo yêu thích của mình. Lợi thế chính của chúng là khả năng được tích hợp trong quy trình làm việc truyền thống và IDE của bạn.

Trong thực tế, điều này có nghĩa là chúng rất hữu ích cho tất cả các vấn đề nhỏ về phân tích cú pháp mà bạn tìm thấy. Nếu nhà phát triển điển hình gặp phải một vấn đề, quá phức tạp đối với một biểu thức chính quy đơn giản, thì những thư viện này thường là giải pháp. Tóm lại, nếu bạn cần tạo trình phân tích cú pháp nhưng thực sự không muốn, thì trình kết hợp phân tích cú pháp có thể là lựa chọn tốt nhất của bạn.

Bennu, Parjs và Parsimmon

Bennu là một thư viện tổ hợp trình phân tích cú pháp Javascript dựa trên Parsec. Thư viện Bennu bao gồm một bộ tổ hợp phân tích cú pháp cốt lõi triển khai giao diện Fantasy Land . Các chức năng nâng cao hơn như thông báo lỗi chi tiết, trạng thái phân tích cú pháp tùy chỉnh, ghi nhớ và chạy các trình phân tích cú pháp không sửa đổi tăng dần cũng được hỗ trợ.

Tất cả các thư viện đều được lấy cảm hứng từ Parsec. Bennu và Parsimmon là lâu đời nhất và Bennu là cao cấp hơn giữa hai người. Tất cả họ cũng có một tài liệu mở rộng, nhưng họ không có hướng dẫn. Bennu dường như vẫn được duy trì, nhưng nó không được phát triển tích cực.

Một ví dụ từ tài liệu.

 var parse = request ('bennu'). parse;
var text = request ('bennu'). text;

var aOrB = parse.either (
    text.character ('a'),
    text.character ('b'));

parse.run (aOrB, 'b'); // 'b' 

Parsimmon là một thư viện nhỏ để viết các trình phân tích cú pháp lớn được tạo thành từ nhiều trình phân tích cú pháp nhỏ. API được lấy cảm hứng từ phân tích cú pháp và Promises / A +.

Parsimmon là phổ biến nhất trong số ba, nó ổn định và cập nhật.

Sau đây là một phần của ví dụ JSON.

 let khoảng trắng = P.regexp (/ s * / m);

let JSONParser = P.createLanguage ({
  // Đây là điểm nhập chính của trình phân tích cú pháp: một giá trị JSON đầy đủ.
  giá trị: r = & gt;
    P.alt (
      r. đối tượng,
      r. chuỗi,
      [..]
    ) .thru (parser = & gt; whitespace.then (parser)),

  [..]

  // Các trình phân tích cú pháp dựa trên Regexp thường phải được đặt tên để báo cáo lỗi tốt hơn.
  chuỗi: () = & gt;
    mã thông báo (P.regexp (/ "((?:. |.) *?)" /, 1))
      .map (giải thích các kiểu)
      .desc ('string'),

  [..]

  đối tượng: r = & gt;
    r.lbrace
      .then (r.pair.sepBy (r.comma))
      .skip (r.rbrace)
      .map (cặp = & gt; {
        để đối tượng = {};
        cặp.forEach (cặp = & gt; {
          let [key, value] = cặp;
          object [key] = value;
        });
        đối tượng trả lại;
      }),
});

//////////////////////////////////////////////////////// ///////////////////////

let text = // Đối tượng JSON

let ast = JSONParser.value.tryParse (văn bản);

Parjs là một thư viện JavaScript gồm các trình tổ hợp phân tích cú pháp, tương tự về nguyên tắc và thiết kế với các ứng dụng tương tự của Parsec và đặc biệt là sự thích ứng F # của nó FParsec .

Nó cũng tương tự như thư viện parsimmon, nhưng có ý định vượt trội hơn nó.

Parjs chỉ mới được vài tháng, nhưng nó đã khá phát triển. Nó cũng có lợi thế là được viết bằng TypeScript.

Tất cả các thư viện đều có tài liệu tốt, nhưng Parjs thật tuyệt vời: nó giải thích cách sử dụng trình phân tích cú pháp và cũng như cách thiết kế trình phân tích cú pháp tốt với nó. Có một số ví dụ, bao gồm các ví dụ sau về định dạng chuỗi.

 / **
 * Tạo bởi lifeg ngày 04/04/2017.
 * /
nhập "../setup";
nhập {Parjs, LoudParser} từ "../src";
// + XÁC ĐỊNH BỘ PHẬN

// Phân tích cú pháp một số nhận dạng, một asciiLetter theo sau là một asciiLetter hoặc một chữ số, ví dụ: a12b nhưng không phải 1ab.
let Id = Parjs.letter.then (Parjs.letter.or (Parjs.digit) .many ()). str;

// Phân tích cú pháp mã thông báo định dạng, `danh tính` giữa` {`và`} `. Trả về kết quả dưới dạng đối tượng Token.
let formatToken = Id.between (Parjs.string ("{"), Parjs.string ("}")). map (x = & gt; ({token: x}));

// Phân tích cú pháp một ký tự thoát. Điều này phân tích cú pháp "{a}" dưới dạng văn bản "{a}" thay vì mã thông báo.
// Cũng thoát khỏi ký tự đã thoát, phân tích cú pháp "` `" thành "` ".
// Hoạt động với các ký tự tùy ý như `a được phân tích cú pháp thành a.
let Escape = Parjs.string ("` "). then (Parjs.anyChar) .str.map (x = & gt; ({text: x.substr (1)}));

// Phân tích cú pháp văn bản không phải là ký tự thoát hoặc {.
let text = Parjs.noCharOf ("` {"). many (1) .str.map (x = & gt; ({text: x}));

// Bản thân trình phân tích cú pháp. Phân tích cú pháp hoặc là formatToken, ví dụ: {abc} hoặc một tổ hợp thoát `x, hoặc văn bản không chứa` {.
// Phân tích cú pháp nhiều lần.
let formatParser = formatToken.or (Escape, text) .many ();

// Điều này in ra một chuỗi mã thông báo {text: "xin chào, tên tôi là"}, {mã thông báo: tên}, {văn bản: "và tôi là"}, {mã thông báo: "tuổi}, ...
console.log (formatParser.parse ("xin chào, tên tôi là {name} và tôi {age} tuổi. Đây là` {Escape}. Đây là thoát kép: `` {name}. ")); 

Thư viện JavaScript liên quan đến phân tích cú pháp

Ngoài ra còn có một số thư viện thú vị khác liên quan đến phân tích cú pháp không thuộc danh mục chung.

Thư viện JavaScript phân tích cú pháp JavaScript

Có một trường hợp đặc biệt có thể được quản lý theo cách cụ thể hơn: trường hợp bạn muốn phân tích cú pháp mã JavaScript trong JavaScript. Trái ngược với những gì chúng tôi đã tìm thấy cho Java và C #, không có sự lựa chọn chắc chắn: có nhiều lựa chọn tốt để phân tích cú pháp JavaScript.

Ba thư viện phổ biến nhất dường như là: Acorn , Esprima UglifyJS . Chúng tôi sẽ không nói cái nào là tốt nhất vì tất cả chúng đều có vẻ tuyệt vời, được cập nhật và hỗ trợ tốt.

Một điểm khác biệt quan trọng là UglifyJS cũng là một bộ công cụ quản lý / nén / làm đẹp, có nghĩa là nó cũng có nhiều công dụng khác. Mặt khác, nó là người duy nhất chỉ hỗ trợ đến phiên bản ECMAScript 5. Một điều khác cần xem xét là chỉ esprima mới có tài liệu xứng đáng cho các dự án tầm cỡ như vậy.

Thư viện phân tích cú pháp thú vị: Chevrotain

Chevrotain là một JavaScript LL (k) DSL phân tích cú pháp rất nhanh và giàu tính năng. Nó có thể được sử dụng để xây dựng trình phân tích cú pháp / trình biên dịch / thông dịch viên cho nhiều trường hợp sử dụng khác nhau, từ các tệp cấu hình đơn giản đến các ngôn ngữ lập trình chính thức đầy đủ.

Có một công cụ phân tích cú pháp thú vị khác không thực sự phù hợp với các danh mục công cụ phổ biến hơn, như trình tạo phân tích cú pháp hoặc bộ tổ hợp: Chevrotain, một DSL phân tích cú pháp. DSL phân tích cú pháp hoạt động như một sự kết hợp giữa bộ tổ hợp bộ phân tích cú pháp và bộ tạo bộ phân tích cú pháp. Bạn xác định trực tiếp ngữ pháp trong mã JavaScript, nhưng sử dụng API (Chevrotain) chứ không phải cú pháp chuẩn như EBNF hoặc PEG. Bạn có thể thấy một số lý do để thích DSL phân tích cú pháp hơn là trình tạo trình phân tích cú pháp trong tài liệu của họ.

Chevrotain hỗ trợ nhiều tính năng nâng cao điển hình của trình tạo trình phân tích cú pháp: như các vị từ ngữ nghĩa, từ vựng và phân tích cú pháp riêng biệt và định nghĩa ngữ pháp (tùy chọn) được tách biệt khỏi các hành động. Các hành động có thể được thực hiện bằng cách sử dụng khách truy cập và do đó bạn có thể sử dụng lại cùng một ngữ pháp cho nhiều dự án.

Sau đây là một phần ngữ pháp JSON mẫu từ tài liệu. Như bạn có thể thấy cú pháp rõ ràng hơn để hiểu đối với một nhà phát triển chưa có kinh nghiệm về phân tích cú pháp, nhưng hơi dài dòng hơn ngữ pháp chuẩn.

 const {CstParser, Lexer, createToken} = request ("chevrotain")

// ----------------- lexer -----------------
const True = createToken ({name: "True", pattern: / true /})
const False = createToken ({name: "False", mẫu: / false /})
const Null = createToken ({name: "Null", pattern: / null /})
const LCurly = createToken ({name: "LCurly", pattern: / {/})
const RCurly = createToken ({name: "RCurly", pattern: /} /})
const LSquare = createToken ({name: "LSquare", pattern: / \ [/})
const RSquare = createToken ({name: "RSquare", pattern: /] /})
const Comma = createToken ({name: "Comma", pattern: /, /})
const Colon = createToken ({name: "Colon", mẫu: /: /})
const StringLiteral = createToken ({
  tên: "StringLiteral",
  mẫu: / "(?: [^ \\"] | \\ (?: [bfnrtv "\\ /] | u [0-9a-fA-F] {4})) *" /
})
const NumberLiteral = createToken ({
  tên: "NumberLiteral",
  mẫu: /-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?/
})
const WhiteSpace = createToken ({
  tên: "Khoảng trắng",
  mẫu: / [\ t \ n \ r] + /,
  nhóm: Lexer.SKIPPED
})

const allTokens = [
  Khoảng trắng,
  NumberLiteral,
  Chuỗi chữ,
  Tất cả,
  RCurly,
  LSquare,
  Quảng trường R,
  Dấu phẩy,
  Đại tràng,
  ĐÚNG VẬY,
  Sai,
  Vô giá trị
]

const JsonLexer = new Lexer (allTokens)

// ----------------- phân tích cú pháp -----------------

lớp JsonParser mở rộng CstParser {
  // Rất tiếc, không hỗ trợ cho các trường lớp có bộ khởi tạo trong ES2015, chỉ trong esNext ...
  // vì vậy các quy tắc phân tích cú pháp được xác định bên trong hàm tạo, vì mỗi quy tắc phân tích cú pháp phải được khởi tạo bởi
  // gọi RULE (...)
  // xem: https://github.com/jeffmo/es-class-fields-and-static-properties
  người xây dựng() {
    siêu (allTokens)

    // không bắt buộc, sử dụng $ (hoặc bất kỳ dấu hiệu nào khác) để giảm độ dài dòng (cái này. cái này. cái này. cái này. .......)
    const $ = cái này

    // các phương thức phân tích cú pháp
    $ .RULE ("json", () = & gt; {
      $ .OR ([
        {ALT: () = & gt; $ .SUBRULE ($. Object)},
        {ALT: () = & gt; $ .SUBRULE ($. Mảng)}
      ])
    })

    $ .RULE ("đối tượng", () = & gt; {
      $ .CONSUME (Hàng tuần)
      $ .OPTION (() = & gt; {
        $ .SUBRULE ($. ObjectItem)
        $ .MANY (() = & gt; {
          $ .CONSUME (Dấu phẩy)
          $ .SUBRULE2 ($. ObjectItem)
        })
      })
      $ .CONSUME (RCurly)
    })

    $ .RULE ("objectItem", () = & gt; {
      $ .CONSUME (StringLiteral)
      $ .CONSUME (Dấu hai chấm)
      $ .SUBRULE (giá trị $.)
    })

    $ .RULE ("mảng", () = & gt; {
      $ .CONSUME (LSquare)
      $ .OPTION (() = & gt; {
        $ .SUBRULE (giá trị $.)
        $ .MANY (() = & gt; {
          $ .CONSUME (Dấu phẩy)
          $ .SUBRULE2 (giá trị $.)
        })
      })
      $ .CONSUME (RSquare)
    })

    $ .RULE ("giá trị", () = & gt; {
      $ .OR ([
        {ALT: () = & gt; $ .CONSUME (StringLiteral)},
        {ALT: () = & gt; $ .CONSUME (NumberLiteral)},
        {ALT: () = & gt; $ .SUBRULE ($. Object)},
        {ALT: () = & gt; $ .SUBRULE ($. Mảng)},
        {ALT: () = & gt; $ .CONSUME (Đúng)},
        {ALT: () = & gt; $ .CONSUME (Sai)},
        {ALT: () = & gt; $ .CONSUME (Null)}
      ])
    })

    // rất quan trọng để gọi điều này sau khi tất cả các quy tắc đã được xác định.
    // nếu không trình phân tích cú pháp có thể không hoạt động chính xác vì nó sẽ thiếu thông tin
    // có nguồn gốc trong giai đoạn tự phân tích.
    this.performSelfAnalysis ()
  }
}

// ----------------- gói tất cả lại với nhau -----------------

// sử dụng lại cùng một phiên bản phân tích cú pháp.
const parser = new JsonParser ()

module.exports = {
  jsonTokens: allTokens,

  JsonParser: JsonParser,

  phân tích cú pháp: hàm phân tích cú pháp (văn bản) {
    const lexResult = JsonLexer.tokenize (văn bản)
    // thiết lập một đầu vào mới sẽ ĐẶT LẠI trạng thái của phiên bản phân tích cú pháp.
    parser.input = lexResult.tokens
    // bất kỳ quy tắc cấp cao nhất nào cũng có thể được sử dụng làm điểm nhập
    const cst = parser.json ()

    trở về {
      cst: cst,
      lexErrors: lexResult.errors,
      parseErrors: phân tích cú pháp.errors
    }
  }
} 

Nó rất nhanh, nhanh hơn bất kỳ thư viện JavaScript nào khác và có thể cạnh tranh với trình phân tích cú pháp tùy chỉnh được viết bằng tay, tùy thuộc vào công cụ JavaScript mà nó chạy trên đó. Bạn có thể xem các con số và biết thêm chi tiết về tiêu chuẩn phân tích cú pháp thư viện do tác giả của thư viện phát triển.

Nó cũng hỗ trợ các tính năng hữu ích để gỡ lỗi như tạo sơ đồ đường sắt và báo cáo lỗi tùy chỉnh. Ngoài ra còn có một số tính năng hữu ích để xây dựng trình biên dịch, trình thông dịch hoặc công cụ cho người chỉnh sửa, chẳng hạn như khôi phục lỗi tự động hoặc hỗ trợ nội dung cú pháp . Điều cuối cùng có nghĩa là nó có thể đề xuất mã thông báo tiếp theo được cung cấp một đầu vào nhất định, vì vậy nó có thể được sử dụng làm khối xây dựng cho tính năng tự động hoàn thành.

Đây không phải là tất cả, Chevrotain thậm chí còn cung cấp động cơ của riêng mình để sử dụng bên ngoài . Điều này có nghĩa là bạn có thể xây dựng thư viện phân tích cú pháp của riêng mình trên Chevrotain. Ví dụ: bạn có thể tạo định dạng của riêng mình cho một ngữ pháp và sau đó sử dụng công cụ Chevrotain để hỗ trợ phân tích cú pháp. Nó thậm chí còn cung cấp cho bạn các tính năng kiểm tra lỗi miễn phí, chẳng hạn như phát hiện các lựa chọn thay thế không rõ ràng, đệ quy trái, v.v.

Chevrotain có một tài liệu tuyệt vời và được tổ chức tốt, với một hướng dẫn, ngữ pháp ví dụ và một tài liệu tham khảo. Nó cũng có trình chỉnh sửa / sân chơi trực tuyến gọn gàng .

Chevrotain được viết bằng TypeScript.

Tóm tắt

Như chúng tôi đã nói trong bài viết về phân tích cú pháp trong Java và C #, thế giới phân tích cú pháp hơi khác với thế giới thông thường của các lập trình viên. Trong trường hợp của JavaScript, ngôn ngữ này cũng sống trong một thế giới khác với bất kỳ ngôn ngữ lập trình nào khác. Có sự chênh lệch về năng lực giữa các nhà phát triển đến mức bạn có thể tìm thấy những người giỏi nhất làm việc với những người chỉ biết cách tập hợp một tập lệnh. Và cả hai đều muốn phân tích cú pháp.

Vì vậy, đối với JavaScript, có những công cụ tương tự như vậy. Chúng tôi có các công cụ nghiêm túc được phát triển bởi các học giả cho các khóa học của họ hoặc trong quá trình lấy bằng của họ cùng với các công cụ đơn giản hơn nhiều. Một số trong số đó làm mờ ranh giới giữa trình tạo phân tích cú pháp và trình tổ hợp phân tích cú pháp. Và tất cả chúng đều có vị trí của chúng. Một điều phức tạp nữa là trong khi các tổ hợp phân tích cú pháp thường được dành riêng để sử dụng dễ dàng hơn, thì với JavaScript không phải lúc nào cũng vậy. Bạn có thể tìm thấy các bộ tổ hợp phân tích cú pháp rất mạnh và phức tạp cũng như các bộ tạo phân tích cú pháp dễ dàng hơn nhiều.

Vì vậy, với JavaScript hơn bao giờ hết, chúng tôi chắc chắn không thể đề xuất một phần mềm này hơn phần mềm kia. Điều tốt nhất cho người dùng có thể không tốt nhất cho người khác. Và tất cả chúng ta đều biết rằng giải pháp đúng kỹ thuật nhất có thể không lý tưởng trong cuộc sống thực với tất cả các ràng buộc của nó. Vì vậy, chúng tôi muốn chia sẻ những gì chúng tôi đã học được về các tùy chọn tốt nhất để phân tích cú pháp trong JavaScript.

Chúng tôi muốn cảm ơn Shahar Soel vì đã thông báo cho chúng tôi về Chevrotain và đề xuất một số chỉnh sửa cần thiết.


Xem thêm những thông tin liên quan đến chủ đề cách phân tích cú pháp trong javascript

Arrow function trong Javascript ES6

alt

  • Tác giả: F8 Official
  • Ngày đăng: 2020-09-08
  • Đánh giá: 4 ⭐ ( 7632 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: 1. Giới thiệu (https://youtu.be/MFDXxCNqjKQ)
    2. Let & Const (https://youtu.be/tCPTBPua1Xo)
    3. Template literals (https://youtu.be/7Ls-fa8iVXA)
    4. Arrow function (https://youtu.be/9QeNLypIiZs)
    5. Classes (https://youtu.be/jSvViDjWXaE)
    6. Default parameter values (https://youtu.be/451KRGBBRJY)
    7. Enhanced object literals (https://youtu.be/WB6FQdp41hs)
    8. Spread (https://youtu.be/MJZICS7nQk8)
    9. Destructuring & Rest (https://youtu.be/J1m4vLDUhEI)
    10. Tagged template literals (https://youtu.be/XV0d0A37sd8)
    11. Modules (https://youtu.be/08lWi4T2Bfg)
    12. Optional chaining (https://youtu.be/kxX7kKjXXKs)

    🔥 Hãy chia sẻ các khóa học để mọi người được học MIỄN PHÍ ❤️
    🔥 Truy cập http://fullstack.edu.vn (miễn phí) để làm bài tập và quản lý được tiến độ học của bạn. Trong tương lai còn giúp bạn có hồ sơ đẹp trong mắt Nhà Tuyển Dụng.
    🔥 Tham gia nhóm Học lập trình tại F8 trên Facebook: https://www.facebook.com/groups/f8official/

    hoclaptrinh mienphi frontend backend devops
    ---------------------------------------
    HỌC LẬP TRÌNH MIỄN PHÍ
    1. Khóa Javascript cơ bản: https://fullstack.edu.vn/courses/javascript-co-ban
    2. Khóa HTML, CSS: https://fullstack.edu.vn/courses/html-css
    3. Khóa Responsive web design: https://fullstack.edu.vn/courses/responsive-web-design
    4. Khóa Xây dựng web với NodeJS & ExpressJS: https://fullstack.edu.vn/courses/nodejs
    ---------------------------------------
    LIÊN KẾT HỮU ÍCH
    1. Học lập trình: http://fullstack.edu.vn
    2. Viết CV xin việc: http://mycv.vn
    3. Danh sách phát Youtube: https://www.youtube.com/channel/UCNSCWwgW-rwmoE3Yc4WmJhw/playlists
    -----------------------------------------------------------
    LIÊN HỆ
    1. Facebook: https://fb.com/sondnmc
    2. Email: sondnf8@gmail.com

    Yêu các bạn ❤️

Mọi thứ bạn cần biết về chèn dấu chấm phẩy trong JavaScript

  • Tác giả: itzone.com.vn
  • Đánh giá: 3 ⭐ ( 1809 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: The ITZone platform Vietnam is the community for anyone interested in news, training seminars, presentations etc in the IT industry

Cú pháp JavaScript cơ bản

  • Tác giả: hanoiict.edu.vn
  • Đánh giá: 4 ⭐ ( 1387 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Trong bài viết hướng dẫn tự học Javascript này, bạn sẽ học cách viết code JavaScript, sử dụng cú pháp Javascript cơ bản.   Hiểu cú pháp Javascript   Cú pháp của JavaScript là tập hợp các quy tắc xác định chương trình JavaScript có cấu trúc chính xác. Một JavaScript bao gồm các câu lệnh JavaScript được đặt trong các thẻ

Phương thức phân tích cú pháp JavaScript JSON ()

  • Tác giả: pluginthanhtoan.com
  • Đánh giá: 3 ⭐ ( 1050 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: botvietbai.com cung cấp các hướng dẫn, tài liệu tham khảo và bài tập trực tuyến miễn phí bằng tất cả các ngôn ngữ chính của web. Bao gồm các chủ đề phổ biến như HTML, CSS, JavaScript, Python, SQL, Java, và nhiều hơn nữa.

Cú pháp trong JavaScript

  • Tác giả: freehost.page
  • Đánh giá: 5 ⭐ ( 3737 lượt đánh giá )
  • Khớp với kết quả tìm kiếm:

Cú pháp trong JavaScript

  • Tác giả: hocjavascript.net
  • Đánh giá: 5 ⭐ ( 5054 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Cú pháp JavaScript bao gồm những quy tắc để viết mã JavaScript. Chúng ta phải tuân thủ cú pháp khi xây dựng một chương trình.Một chương trình

Trình phân tích cú pháp JavaScript để tạo cây cú pháp trừu tượng (AST): Acorn

  • Tác giả: helpex.vn
  • Đánh giá: 3 ⭐ ( 3917 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: 0. Lời nói đầu Trình phân tích cú pháp JavaScript - Acorn và AST là những thứ hữu ích. Chúng giúp chúng tôi chỉnh sửa mã nguồn một cách tự động và hiệu quả. Bài đăng này hướng dẫn bạn cách…

Xem thêm các bài viết khác thuộc chuyên mục: Kiến thức lập trình