Mã thông báo lexer python

Trình phân tích cú pháp là công cụ mạnh mẽ và sử dụng ANTLR, bạn có thể viết tất cả các loại trình phân tích cú pháp, có thể sử dụng được từ nhiều ngôn ngữ khác nhau

Trong hướng dẫn đầy đủ này, chúng ta sẽ

  • giải thích những điều cơ bản. trình phân tích cú pháp là gì, nó có thể được sử dụng để làm gì
  • see how to setup ANTLR to be used from JavaScript, Python, Java and C#
  • discuss how to test your parser
  • present the most advanced and useful features present in ANTLR. you will learn all you need to parse all possible languages
  • show tons of examples

Maybe you have read some tutorial that was too complicated or so incomplete that seemed to assume that you already knew how to use a parser. This is not that kind of tutorial. We just expect you to know how to code and how to use a text editor or an IDE. That’s it

At the end of this tutorial

  • you will be able to write a parser to recognize different formats and languages
  • you will be able to create all the rules you need to build a lexer and a parser
  • you will know how to deal with the common problems you will encounter
  • you will understand errors and you will know how to avoid them by testing your grammar

In other words, we will start from the very beginning and when we reach the end you will have learned all you could possibly need to learn about ANTLR to be productive

ANTLR Mega Tutorial Giant List of Content

What is ANTLR?

ANTLR is a parser generator, a tool that helps you to create parsers. A parser takes a piece of text and transforms it in an organized structure, a parse tree, also known as a Abstract Syntax Tree [AST]. You can think of the AST as a story describing the content of the code, or also as its logical representation, created by putting together the various pieces

Graphical representation of an AST for the Euclidean algorithm

What you need to do to get a parse tree

  1. define a lexer and parser grammar
  2. invoke ANTLR. it will generate a lexer and a parser in your target language [e. g. , Java, Python, C#, JavaScript]
  3. sử dụng từ vựng và trình phân tích cú pháp được tạo. bạn yêu cầu họ chuyển mã để nhận dạng và họ trả lại cho bạn một cây phân tích cú pháp

Vì vậy, bạn cần bắt đầu bằng cách xác định ngữ pháp từ vựng và trình phân tích cú pháp cho nội dung mà bạn đang phân tích. Thông thường “thứ” là ngôn ngữ, nhưng nó cũng có thể là định dạng dữ liệu, sơ đồ hoặc bất kỳ loại cấu trúc nào được biểu thị bằng văn bản

Lưu ý rằng về mặt kỹ thuật, những gì bạn nhận được từ ANTLR là một cây phân tích chứ không phải AST. Sự khác biệt là cây phân tích cú pháp chính xác là những gì xuất phát từ trình phân tích cú pháp, trong khi AST là phiên bản tinh tế hơn của cây phân tích cú pháp. Bạn tạo AST bằng cách thao tác với cây phân tích cú pháp, để có được thứ gì đó dễ sử dụng hơn cho các phần tiếp theo của chương trình của bạn. Những thay đổi này đôi khi cần thiết vì cây phân tích cú pháp có thể được tổ chức theo cách giúp việc phân tích cú pháp dễ dàng hơn hoặc hoạt động tốt hơn. Tuy nhiên, bạn có thể thích thứ gì đó thân thiện với người dùng hơn trong phần còn lại của chương trình

Sự khác biệt trong tranh luận trong các ví dụ của chúng tôi được hiển thị ở đây, vì chúng khá đơn giản, vì vậy chúng tôi sử dụng các thuật ngữ thay thế cho nhau ở đây. Tuy nhiên, đó là điều cần lưu ý khi đọc các tài liệu khác

Biểu thức chính quy không đủ?

Nếu bạn là một lập trình viên điển hình, bạn có thể tự hỏi tại sao tôi không thể sử dụng biểu thức chính quy?

Rõ ràng nhất là thiếu đệ quy. bạn không thể tìm thấy một biểu thức [thông thường] bên trong một biểu thức khác, trừ khi bạn viết mã bằng tay cho từng cấp độ. Thứ gì đó nhanh chóng trở nên không thể duy trì . Nhưng vấn đề lớn hơn là nó không thực sự có khả năng mở rộng. nếu bạn định tập hợp lại dù chỉ một vài biểu thức thông thường, bạn sẽ tạo ra một mớ hỗn độn khó bảo trì.

Không dễ để sử dụng các biểu thức chính quy

Bạn đã bao giờ thử phân tích cú pháp HTML bằng một biểu thức chính quy chưa? . Bạn không tin tôi? .

antlr4 -Dlanguage=JavaScript Chat.g4
6. Rực rỡ. Bạn làm được rồi. Ngoại trừ ai đó thêm thuộc tính vào bảng của họ, chẳng hạn như
antlr4 -Dlanguage=JavaScript Chat.g4
7 hoặc
antlr4 -Dlanguage=JavaScript Chat.g4
8. Nó không quan trọng, bạn làm điều này.
antlr4 -Dlanguage=JavaScript Chat.g4
9. Tuy nhiên, bạn thực sự quan tâm đến dữ liệu bên trong bảng. Vì vậy, bây giờ bạn cần phân tích cú pháp
error[31]:  ANTLR cannot generate Javascript code as of version 4.9
0 và
error[31]:  ANTLR cannot generate Javascript code as of version 4.9
1, nhưng chúng chứa đầy các thẻ

Vì vậy, bạn cũng cần phải loại bỏ điều đó. Và ai đó thậm chí còn dám sử dụng những bình luận như

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
2. Nhận xét có thể được sử dụng ở mọi nơi và điều đó không dễ xử lý bằng biểu thức chính quy của bạn. Là nó?

Vì vậy, bạn cấm internet sử dụng nhận xét trong HTML. vấn đề được giải quyết

Hoặc cách khác, bạn sử dụng ANTLR, bất cứ điều gì có vẻ đơn giản hơn đối với bạn

ANTLR vs Viết trình phân tích cú pháp của riêng bạn bằng tay

Được rồi, bạn chắc chắn rằng bạn cần một trình phân tích cú pháp, nhưng tại sao lại sử dụng trình tạo trình phân tích cú pháp như ANTLR thay vì tạo trình tạo của riêng bạn?

Ưu điểm chính của ANTLR là năng suất

Nếu bạn thực sự phải làm việc với trình phân tích cú pháp mọi lúc vì ngôn ngữ hoặc định dạng của bạn đang phát triển, thì bạn cần có khả năng bắt kịp tốc độ. Đây là điều bạn không thể làm nếu bạn phải xử lý các chi tiết của việc triển khai trình phân tích cú pháp. Vì bạn không phân tích cú pháp vì mục đích phân tích cú pháp, nên bạn phải có cơ hội tập trung vào việc hoàn thành mục tiêu của mình. Và ANTLR giúp thực hiện điều đó dễ dàng hơn nhiều, nhanh chóng và rõ ràng

Điều thứ hai, khi bạn đã xác định ngữ pháp của mình, bạn có thể yêu cầu ANTLR tạo nhiều trình phân tích cú pháp bằng các ngôn ngữ khác nhau. Ví dụ: bạn có thể nhận một trình phân tích cú pháp trong C# và một trong JavaScript để phân tích cú pháp cùng một ngôn ngữ trong ứng dụng máy tính để bàn và trong ứng dụng web

Một số người tranh luận rằng viết trình phân tích cú pháp bằng tay, bạn có thể làm cho nó nhanh hơn và bạn có thể tạo ra các thông báo lỗi tốt hơn. Có một số sự thật trong điều này, nhưng theo kinh nghiệm của tôi, các trình phân tích cú pháp do ANTLR tạo ra luôn đủ nhanh. Bạn có thể điều chỉnh chúng và cải thiện cả hiệu suất và xử lý lỗi bằng cách làm việc với ngữ pháp của mình, nếu bạn thực sự cần. Và bạn có thể làm điều đó một khi bạn hài lòng với ngữ pháp của mình

Mục lục

Hai lưu ý nhỏ

  • trong kho lưu trữ đồng hành của hướng dẫn này, bạn sẽ tìm thấy tất cả mã có kiểm tra, ngay cả khi chúng tôi không thấy nó trong bài viết
  • các ví dụ sẽ ở các ngôn ngữ khác nhau, nhưng kiến ​​thức sẽ được áp dụng chung cho bất kỳ ngôn ngữ nào

Thành lập

  1. Thiết lập ANTLR
  2. Thiết lập Javascript
  3. Cài đặt Python
  4. Thiết lập Java
  5. Cài đặt C#

Người bắt đầu

  1. Lexers và trình phân tích cú pháp
  2. Tạo ngữ pháp
  3. Designing a Data Format
  4. Lexer Rules
  5. Parser Rules
  6. Mistakes and Adjustments

Mid-Level

  1. Setting Up the Chat Project in Javascript
  2. Antlr. js
  3. HtmlChatListener. js
  4. Working with a Listener
  5. Solving Ambiguities with Semantic Predicates
  6. Continuing the Chat in Python
  7. The Python Way of Working with a Listener
  8. Thử nghiệm với Python
  9. Parsing Markup
  10. Lexical Modes
  11. Parser Grammars

Advanced

  1. The Markup Project in Java
  2. The Main App. java
  3. Transforming Code with ANTLR
  4. Joy and Pain of Transforming Code
  5. Advanced Testing
  6. Dealing with Expressions
  7. Parsing Spreadsheets
  8. The Spreadsheet Project in C#
  9. Excel is Doomed
  10. Testing Everything

Final Remarks

  1. Tips and Tricks
  2. Conclusions

Thành lập

The ANTLR Mega Tutorial as a PDF

Get the Mega Tutorial delivered to your email and read it when you want on the device you want

Success. Now check your email to confirm your subscription

There was an error submitting your subscription. Please try again

First Name

Email Address

We use this field to detect spam bots. If you fill this in, you will be marked as a spammer.

I’d like to learn more about ANTLR and parsing

Send me the PDF Powered by ConvertKit

Trong phần này, chúng tôi chuẩn bị môi trường phát triển để làm việc với ANTLR. the parser generator tool, the supporting tools and the runtimes for each language

1. Setup ANTLR

ANTLR is actually made up of two main parts. the tool, used to generate the lexer and parser, and the runtime, needed to run them

The tool will be needed just by you, the language engineer, while the runtime will be included in the final software created by you

The tool is always the same no matter which language you are targeting. it is a Java program that you need on your development machine. It is used to generate the lexer and parser. While the runtime is different for every language and must be available both to the developer and to the user. It is needed to run the program

The only requirement for the tool is that you have installed at least Java 1. 7. To install the Java program, you need to download the latest version from the official site, which at the moment is

//www.antlr.org/download/antlr-4.9.3-complete.jar

Instructions

  1. copy the downloaded tool where you usually put third-party java libraries [ex.
    error[31]:  ANTLR cannot generate Javascript code as of version 4.9
    3 or
    error[31]:  ANTLR cannot generate Javascript code as of version 4.9
    4]
  2. add the tool to your 
    error[31]:  ANTLR cannot generate Javascript code as of version 4.9
    5. Thêm nó vào tập lệnh khởi động của bạn [ví dụ:.
    error[31]:  ANTLR cannot generate Javascript code as of version 4.9
    6]
  3. [optional] add also aliases to your startup script to simplify the usage of ANTLR

Executing the instructions on Linux/Mac OS

antlr4 -Dlanguage=JavaScript Chat.g4
2

Executing the instructions on Windows

antlr4 -Dlanguage=JavaScript Chat.g4
3

Typical Workflow

When you use ANTLR you start by writing a grammar, a file with extension

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
7, which contains the rules of the language that you are analyzing. Sau đó, bạn sử dụng chương trình
error[31]:  ANTLR cannot generate Javascript code as of version 4.9
8 để tạo các tệp mà chương trình của bạn sẽ thực sự sử dụng, chẳng hạn như từ vựng và trình phân tích cú pháp

antlr4 -Dlanguage=JavaScript Chat.g4
6

Có một số tùy chọn quan trọng mà bạn có thể chỉ định khi chạy

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
8

Đầu tiên, bạn có thể chỉ định ngôn ngữ đích, để tạo trình phân tích cú pháp bằng Python hoặc JavaScript hoặc bất kỳ mục tiêu nào khác với Java [là ngôn ngữ mặc định]. Những cái khác được sử dụng để tạo khách truy cập và người nghe [đừng lo lắng nếu bạn chưa biết chúng là gì, chúng tôi sẽ giải thích chúng sau]

Theo mặc định, chỉ trình nghe được tạo, vì vậy, để tạo khách truy cập, bạn sử dụng tùy chọn dòng lệnh 

antlr4 -Dlanguage=JavaScript Chat.g4
80 và
antlr4 -Dlanguage=JavaScript Chat.g4
81 nếu bạn không muốn tạo trình nghe. Ngoài ra còn có các tùy chọn ngược lại,
antlr4 -Dlanguage=JavaScript Chat.g4
82 và
antlr4 -Dlanguage=JavaScript Chat.g4
83, nhưng chúng đại diện cho hành vi mặc định

antlr4 -Dlanguage=JavaScript Chat.g4
2

Bạn có thể tùy ý kiểm tra ngữ pháp của mình bằng một tiện ích nhỏ có tên là

antlr4 -Dlanguage=JavaScript Chat.g4
84 [mặc dù, như chúng ta đã thấy, nó thường được đặt bí danh là
antlr4 -Dlanguage=JavaScript Chat.g4
85]

antlr4 -Dlanguage=JavaScript Chat.g4
5

[Các] tên tệp là tùy chọn và thay vào đó, bạn có thể phân tích đầu vào mà bạn nhập trên bảng điều khiển

Nếu bạn muốn sử dụng công cụ kiểm tra, bạn cần tạo trình phân tích cú pháp Java, ngay cả khi chương trình của bạn được viết bằng ngôn ngữ khác. Điều này có thể được thực hiện chỉ bằng cách chọn một tùy chọn khác với

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
8

antlr4 -Dlanguage=JavaScript Chat.g4
87 rất hữu ích khi kiểm tra thủ công bản nháp đầu tiên của ngữ pháp của bạn. Khi nó trở nên ổn định hơn, bạn có thể muốn chuyển tiếp các bài kiểm tra tự động [chúng ta sẽ xem cách viết chúng]

antlr4 -Dlanguage=JavaScript Chat.g4
87 cũng có một số tùy chọn hữu ích.
antlr4 -Dlanguage=JavaScript Chat.g4
89, để hiển thị mã thông báo được phát hiện, 
antlr4 -Dlanguage=JavaScript Chat.g4
00 để tạo hình ảnh của AST

2. Cài đặt JavaScript

Bạn có thể đặt ngữ pháp của mình vào cùng thư mục với tệp JavaScript của mình. Tệp chứa văn phạm phải trùng tên văn phạm, phải được khai báo ở đầu tệp

Trong ví dụ sau, tên là

antlr4 -Dlanguage=JavaScript Chat.g4
01 và tệp là
antlr4 -Dlanguage=JavaScript Chat.g4
02

Chúng ta có thể tạo trình phân tích cú pháp JavaScript tương ứng chỉ bằng cách chỉ định tùy chọn chính xác với chương trình Java ANTLR4

antlr4 -Dlanguage=JavaScript Chat.g4

Xin lưu ý rằng tùy chọn này phân biệt chữ hoa chữ thường, vì vậy hãy chú ý đến chữ hoa chữ 'S'. Nếu bạn làm sai, bạn sẽ nhận được thông báo như sau

error[31]:  ANTLR cannot generate Javascript code as of version 4.9

ANTLR có thể được sử dụng cả với

antlr4 -Dlanguage=JavaScript Chat.g4
03 và trong trình duyệt. Đối với trình duyệt, bạn cần sử dụng
antlr4 -Dlanguage=JavaScript Chat.g4
04 hoặc
antlr4 -Dlanguage=JavaScript Chat.g4
05. Nếu không biết cách sử dụng một trong hai cách, bạn có thể xem tài liệu chính thức để được trợ giúp hoặc đọc hướng dẫn này trên antlr trên web

Trong hướng dẫn này, chúng tôi sẽ sử dụng

antlr4 -Dlanguage=JavaScript Chat.g4
03, bạn có thể cài đặt thời gian chạy ANTLR chỉ bằng cách sử dụng lệnh tiêu chuẩn sau

antlr4 -Dlanguage=JavaScript Chat.g4
8

3. Cài đặt Python

Khi bạn có ngữ pháp, bạn đặt nó vào cùng thư mục với các tệp Python của bạn. Tệp phải trùng tên ngữ pháp, phải khai báo ở đầu tệp. Trong ví dụ sau, tên là

antlr4 -Dlanguage=JavaScript Chat.g4
01 và tệp là
antlr4 -Dlanguage=JavaScript Chat.g4
02

Chúng ta có thể tạo trình phân tích cú pháp Python tương ứng chỉ bằng cách chỉ định tùy chọn chính xác với chương trình Java ANTLR4. Đối với Python, bạn cũng cần chú ý đến phiên bản của Python, có thể là 2 hoặc 3

antlr4 -Dlanguage=JavaScript Chat.g4
0

Thời gian chạy có sẵn từ PyPi, vì vậy bạn chỉ cần cài đặt nó bằng pip

antlr4 -Dlanguage=JavaScript Chat.g4
20

Một lần nữa, bạn chỉ cần nhớ chỉ định phiên bản python phù hợp

4. Thiết lập Java

Để thiết lập một dự án Java bằng ANTLR, bạn có thể thực hiện mọi việc theo cách thủ công, sử dụng dòng lệnh đi kèm với hệ điều hành của bạn. Hoặc bạn có thể là một người văn minh và sử dụng Gradle hoặc Maven. Chúng tôi đang sử dụng Gradle tại đây, nhưng bạn có thể xem thiết lập điển hình bằng Maven trong tài liệu ANTLR. Cả 2 hệ thống build đều có cộng đồng lớn nên tùy sở thích và nhu cầu của bạn mà chọn cái nào

Ngoài ra, bạn có thể xem các plugin ANTLR cho IDE yêu thích của mình

Đây là cách chúng tôi thường thiết lập một dự án Gradle. Chúng tôi sử dụng plugin Gradle để gọi ANTLR. Vì chúng tôi sử dụng IntelliJ IDEA, nên chúng tôi cũng sử dụng plugin Gradle IDEA để tạo cấu hình chính xác cho IDE đó

antlr4 -Dlanguage=JavaScript Chat.g4
21

Chúng tôi đặt ngữ pháp của chúng tôi trực tiếp dưới

antlr4 -Dlanguage=JavaScript Chat.g4
09. Nhờ cấu hình của chúng tôi, Gradle đảm bảo rằng lexer và trình phân tích cú pháp được tạo trong thư mục tương ứng với gói của chúng. Ví dụ: nếu chúng tôi muốn trình phân tích cú pháp nằm trong gói tôi. tomassetti. mylanguage nó sẽ được tạo thành generate-src/antlr/main/me/tomassetti/mylanguage

Tại thời điểm này, chúng ta có thể chỉ cần chạy

antlr4 -Dlanguage=JavaScript Chat.g4
22

Và chúng tôi nhận được từ vựng và trình phân tích cú pháp được tạo từ [các] ngữ pháp

Sau đó, chúng ta cũng có thể chạy

antlr4 -Dlanguage=JavaScript Chat.g4
23

Và chúng tôi có một Dự án IDEA đã sẵn sàng để được mở

Có một lợi thế rõ ràng khi sử dụng Java để phát triển ngữ pháp ANTLR. có các plugin cho một số IDE và đó là ngôn ngữ mà nhà phát triển chính của công cụ thực sự làm việc trên đó. Vì vậy, chúng là những công cụ, chẳng hạn như

antlr4 -Dlanguage=JavaScript Chat.g4
200, có thể dễ dàng tích hợp vào quy trình làm việc của bạn và khá hữu ích nếu bạn muốn dễ dàng hình dung cây phân tích cú pháp của thông tin đầu vào

5. Cài đặt C#

Có hỗ trợ cho. NET Framework, Mono và. lõi mạng. Chúng tôi sẽ sử dụng Visual Studio Code để tạo dự án ANTLR của mình, vì có một tiện ích mở rộng tuyệt vời cho nó giúp tự động tạo trình phân tích cú pháp. Nó cũng có thể tạo nhiều biểu đồ để giúp bạn gỡ lỗi trình phân tích cú pháp của mình hoặc để tạo tài liệu cho người dùng trình phân tích cú pháp của bạn. Nó được gọi là hỗ trợ cú pháp ngữ pháp ANTLR4 và được tạo bởi một trong những người đóng góp chính cho ANTLR

Các lựa chọn thay thế nếu bạn không sử dụng Visual Studio Code

Ngoài ra còn có một tiện ích mở rộng đẹp cho Visual Studio 2015 và 2017 được tạo bởi cùng một tác giả của mục tiêu C#, được gọi là Hỗ trợ ngôn ngữ ANTLR. Bạn có thể cài đặt nó bằng cách vào Công cụ -> Tiện ích mở rộng và cập nhật. Tiện ích mở rộng này sẽ tự động tạo trình phân tích cú pháp, từ vựng và khách truy cập/người nghe khi bạn xây dựng dự án của mình. Hơn nữa, tiện ích mở rộng sẽ cho phép bạn tạo một tệp ngữ pháp mới, sử dụng menu nổi tiếng để thêm một mục mới. Cuối cùng nhưng không kém phần quan trọng, bạn có thể thiết lập các tùy chọn để tạo người nghe/khách truy cập ngay trong thuộc tính của từng tệp ngữ pháp. Tiện ích mở rộng này hiện đã lỗi thời một chút nhưng nó vẫn hữu ích nếu bạn muốn sử dụng Visual Studio

Bạn cũng có thể sử dụng công cụ Java thông thường để tạo mọi thứ, ngay cả trình phân tích cú pháp cho C#. Bạn có thể làm điều đó chỉ bằng cách chỉ ra đúng ngôn ngữ. Trong ví dụ này, ngữ pháp được gọi là

antlr4 -Dlanguage=JavaScript Chat.g4
201

antlr4 -Dlanguage=JavaScript Chat.g4
24

Lưu ý rằng 'S' trong CSharp là chữ hoa

Chọn thời gian chạy phù hợp

Có một số điều cần nhớ nếu bạn đang sử dụng tiện ích mở rộng Visual Studio. Cho dù bạn đang sử dụng tiện ích mở rộng hay công cụ Java tiêu chuẩn, bạn cũng cần thời gian chạy ANTLR4 cho dự án của mình và bạn có thể cài đặt nó bằng nuget tốt. Nhưng bạn phải nhớ rằng không phải tất cả thời gian chạy đều được tạo như nhau

Vấn đề là trước đây chỉ có một gói ANTLR được tối ưu hóa cho C# riêng biệt được xuất bản trên nuget. Bây giờ, thay vào đó, các tác giả chính của ANTLR đã xuất bản một gói chính thức trên nuget. Tuy nhiên, tác giả của phiên bản cũ được tối ưu hóa cho C# tiếp tục xuất bản gói riêng của mình, không tương thích với công cụ ANTLR4 tiêu chuẩn. Đây không hoàn toàn là một nhánh rẽ, vì cùng một người tiếp tục là người đóng góp cốt lõi cho công cụ ANTLR4 chính, nhưng nó là một sự phát triển song song hơn. Người tạo ra gói được tối ưu hóa cho C# cũng là tác giả của tiện ích mở rộng Visual Studio, Sam Harwell [với biệt danh

antlr4 -Dlanguage=JavaScript Chat.g4
202]

Vì vậy, chỉ khi bạn đang sử dụng Tiện ích mở rộng Visual Studio, bạn mới cần sử dụng gói nuget ANTLR4. thời gian chạy, được tác giả bởi sharwell. Nếu bạn đang sử dụng công cụ ANTLR4 hoặc tiện ích mở rộng Visual Studio Code để tạo từ vựng và trình phân tích cú pháp C# thì bạn cần sử dụng ANTLR4. thời gian chạy. Tiêu chuẩn

Lưu ý rằng bản phát hành được tối ưu hóa cho C# chậm hơn một chút so với bản phát hành chính thức. Vì lý do đó, nếu bạn mới bắt đầu, tôi khuyên bạn nên sử dụng thời gian chạy tiêu chuẩn chính thức. Do đó, sẽ tốt hơn nếu bạn sử dụng Visual Studio Code làm IDE của mình hoặc không sử dụng tiện ích mở rộng Visual Studio. Điều này giúp bạn có phiên bản cập nhật nhất của ANTLR

Bạn cũng phải nhớ rằng cả hai tiện ích mở rộng đều đi kèm với công cụ ANTLR nội bộ của riêng chúng để dễ sử dụng. Bằng cách này, bạn không cần cài đặt ANTLR trong hệ thống của mình. Tuy nhiên, điều này có nghĩa là phiên bản ANTLR đi kèm có thể đã lỗi thời. Bạn có thể kiểm tra phiên bản được đề cập trong tệp trình phân tích cú pháp đã tạo. Điều này có thể dẫn đến sự cố trình phân tích cú pháp được tạo bằng phiên bản ANTLR cũ hơn, trong khi thời gian chạy bạn nhận được với Nuget sử dụng phiên bản ANTLR mới

Người bắt đầu

Trong phần này, chúng tôi đặt nền tảng bạn cần sử dụng ANTLR. từ vựng và trình phân tích cú pháp là gì, cú pháp để xác định chúng theo ngữ pháp và các chiến lược bạn có thể sử dụng để tạo chúng. Chúng tôi cũng xem các ví dụ đầu tiên để chỉ ra cách sử dụng những gì bạn đã học. Bạn có thể quay lại phần này nếu bạn không nhớ cách thức hoạt động của ANTLR

6. Lexers và trình phân tích cú pháp

Trước khi xem xét trình phân tích cú pháp, trước tiên chúng ta cần xem xét từ vựng, còn được gọi là trình mã thông báo. Về cơ bản, chúng là bước đệm đầu tiên hướng tới trình phân tích cú pháp và tất nhiên ANTLR cũng cho phép bạn xây dựng chúng. Một lexer lấy các ký tự riêng lẻ và biến đổi chúng thành các mã thông báo, các nguyên tử mà trình phân tích cú pháp sử dụng để tạo cấu trúc logic

Hãy tưởng tượng quá trình này được áp dụng cho một ngôn ngữ tự nhiên như tiếng Anh. Bạn đang đọc các ký tự đơn lẻ, ghép chúng lại với nhau cho đến khi chúng tạo thành một từ, sau đó bạn kết hợp các từ khác nhau để tạo thành một câu

Hãy xem ví dụ sau và tưởng tượng rằng chúng ta đang cố phân tích một phép toán

antlr4 -Dlanguage=JavaScript Chat.g4
25

Từ vựng quét văn bản và tìm '4', '3', '7' và sau đó là khoảng trắng ' '. Vì vậy, nó biết rằng các ký tự đầu tiên thực sự đại diện cho một số. Sau đó, nó tìm ký hiệu '+' để biết rằng ký hiệu này đại diện cho một toán tử và cuối cùng, nó tìm thấy một số khác

Làm sao nó biết được điều đó?

antlr4 -Dlanguage=JavaScript Chat.g4
26

Đây không phải là một ngữ pháp hoàn chỉnh, nhưng chúng ta có thể thấy rằng các quy tắc từ vựng đều là chữ hoa, trong khi các quy tắc của trình phân tích cú pháp đều là chữ thường. Về mặt kỹ thuật, quy tắc về trường hợp chỉ áp dụng cho ký tự đầu tiên của tên của họ, nhưng thường thì tất cả chúng đều là chữ hoa hoặc chữ thường cho rõ ràng

Các quy tắc thường được viết theo thứ tự này. đầu tiên là các quy tắc của trình phân tích cú pháp và sau đó là các quy tắc của bộ từ vựng, mặc dù về mặt logic, chúng được áp dụng theo thứ tự ngược lại. Điều quan trọng cần nhớ là các quy tắc từ vựng được phân tích theo thứ tự xuất hiện và chúng có thể mơ hồ.

Ví dụ điển hình là định danh. trong nhiều ngôn ngữ lập trình, nó có thể là bất kỳ chuỗi ký tự nào, nhưng một số kết hợp nhất định, chẳng hạn như “lớp” hoặc “hàm” bị cấm vì chúng biểu thị một lớp hoặc một hàm. Vì vậy, thứ tự của các quy tắc giải quyết sự mơ hồ bằng cách sử dụng đối sánh đầu tiên và đó là lý do tại sao các mã xác định các từ khóa như lớp hoặc chức năng được xác định trước, trong khi mã định danh được đặt sau cùng

Cú pháp cơ bản của một quy tắc là dễ dàng. có tên, dấu hai chấm, định nghĩa của quy tắc và dấu chấm phẩy kết thúc

Định nghĩa của NUMBER chứa một dãy chữ số điển hình và ký hiệu '+' để cho biết rằng một hoặc nhiều kết quả khớp được cho phép. These are all very typical indications which I assume you are familiar with; if not, you can read more about the syntax of regular expressions

Phần thú vị nhất là ở phần cuối, quy tắc lexer xác định mã thông báo WHITESPACE. It’s interesting because it shows how to indicate to ANTLR to ignore something. Xem xét cách bỏ qua khoảng trắng đơn giản hóa quy tắc trình phân tích cú pháp. if we couldn’t say to ignore WHITESPACE we would have to include it between every single sub-rule of the parser, to let the user puts spaces where they want. Like this

antlr4 -Dlanguage=JavaScript Chat.g4
27

And the same typically applies to comments. they can appear everywhere and we do not want to handle them specifically in every single piece of our grammar so we just ignore them [at least while parsing]

7. Creating a Grammar

Now that we have seen the basic syntax of a rule, we can take a look at the two different approaches to define a grammar. top-down and bottom-up

Top-down approach

Cách tiếp cận này bao gồm việc bắt đầu từ tổ chức chung của một tệp được viết bằng ngôn ngữ của bạn

Phần chính của một tập tin là gì?

For example a Java file can be divided in three sections

  • package declaration
  • imports
  • type definitions

This approach works best when you already know the language or format that you are designing a grammar for. It is probably the strategy preferred by people with a good theoretical background or people who prefer to start with “the big plan”

When using this approach, you start by defining the rule representing the whole file. It will probably include other rules, to represent the main sections. You then define those rules and you move from the most general, abstract rules to the low-level, practical ones

Bottom-up approach

The bottom-up approach consists in focusing on the small elements first. defining how the tokens are captured, how the basic expressions are defined and so on. Then we move to higher level constructs until we define the rule representing the whole file

I personally prefer to start from the bottom, the basic items, that are analyzed with the lexer. And then you grow naturally from there to the structure, that is dealt with the parser. Cách tiếp cận này cho phép tập trung vào một phần ngữ pháp nhỏ, xây dựng các bài kiểm tra cho phần đó, đảm bảo nó hoạt động như mong đợi và sau đó chuyển sang phần tiếp theo

This approach mimics the way we learn. Hơn nữa, có lợi thế là bắt đầu bằng mã thực, điều này thực sự khá phổ biến trong nhiều ngôn ngữ. Trên thực tế, hầu hết các ngôn ngữ đều có những thứ như số nhận dạng, nhận xét, khoảng trắng, v.v. Rõ ràng, bạn có thể phải chỉnh sửa một cái gì đó, ví dụ: một nhận xét trong HTML có chức năng giống như một nhận xét trong C#, nhưng nó có các dấu phân cách khác nhau

Nhược điểm của cách tiếp cận từ dưới lên nằm ở chỗ trình phân tích cú pháp là thứ bạn thực sự quan tâm. Bạn không được yêu cầu xây dựng một từ vựng, bạn được yêu cầu xây dựng một trình phân tích cú pháp có thể cung cấp một chức năng cụ thể. Vì vậy, bằng cách bắt đầu từ phần cuối cùng, từ vựng, bạn có thể sẽ thực hiện một số thao tác tái cấu trúc, nếu bạn chưa biết phần còn lại của chương trình sẽ hoạt động như thế nào

8. Thiết kế định dạng dữ liệu

Thiết kế một ngữ pháp cho một ngôn ngữ mới là khó khăn. Bạn phải tạo một ngôn ngữ đơn giản và trực quan cho người dùng, nhưng cũng rõ ràng để làm cho ngữ pháp có thể quản lý được. Nó phải ngắn gọn, rõ ràng, tự nhiên và không cản trở người dùng

Vì vậy, chúng tôi đang bắt đầu với một cái gì đó hạn chế. một ngữ pháp cho một chương trình trò chuyện đơn giản

Hãy bắt đầu với phần mô tả rõ hơn về mục tiêu của chúng ta

  • sẽ không có đoạn văn và do đó chúng ta có thể sử dụng dòng mới làm dấu phân cách giữa các thư
  • chúng tôi muốn cho phép biểu tượng cảm xúc, đề cập và liên kết. Chúng tôi sẽ không hỗ trợ các thẻ HTML
  • vì cuộc trò chuyện của chúng tôi sẽ dành cho những thanh thiếu niên phiền phức, chúng tôi muốn cho phép người dùng một cách dễ dàng để Hét lên và định dạng màu của văn bản

Cuối cùng thanh thiếu niên có thể hét lên, và tất cả trong màu hồng. Thật là một thời gian để được sống

9. Quy tắc Lexer

Chúng tôi bắt đầu với việc xác định quy tắc từ vựng cho ngôn ngữ trò chuyện của chúng tôi. Hãy nhớ rằng các quy tắc từ vựng thực sự nằm ở cuối tệp

antlr4 -Dlanguage=JavaScript Chat.g4
28

Trong ví dụ này, chúng tôi sử dụng các đoạn quy tắc. chúng là các khối xây dựng có thể tái sử dụng cho các quy tắc lexer. Bạn xác định chúng và sau đó bạn đề cập đến chúng trong các quy tắc từ vựng. Nếu bạn xác định chúng nhưng không đưa chúng vào quy tắc từ vựng, chúng sẽ không có hiệu lực

Chúng tôi xác định một đoạn cho các chữ cái chúng tôi muốn sử dụng trong từ khóa. Tại sao vậy? . Ngoài việc tránh lặp lại trường hợp của các ký tự, chúng còn được sử dụng khi xử lý các số động. Để tránh lặp lại các chữ số, trước và sau dấu chấm/dấu phẩy. Chẳng hạn như trong ví dụ sau

antlr4 -Dlanguage=JavaScript Chat.g4
29

Mã thông báo TEXT cho biết cách ghi lại mọi thứ, ngoại trừ các ký tự theo sau dấu ngã ['~']. Chúng tôi đang loại trừ dấu ngoặc vuông đóng ']', nhưng vì đó là ký tự được sử dụng để xác định phần cuối của một nhóm ký tự, nên chúng tôi phải thoát nó bằng cách đặt trước nó bằng dấu gạch chéo ngược '\'

Quy tắc dòng mới được xây dựng theo cách đó bởi vì thực tế có nhiều cách khác nhau trong đó các hệ điều hành chỉ ra một dòng mới, một số bao gồm một

antlr4 -Dlanguage=JavaScript Chat.g4
203 một số khác là một ký tự
antlr4 -Dlanguage=JavaScript Chat.g4
204 hoặc kết hợp cả hai

10. Quy tắc phân tích cú pháp

Chúng tôi tiếp tục với các quy tắc trình phân tích cú pháp, đó là các quy tắc mà chương trình của chúng tôi sẽ tương tác trực tiếp nhất

antlr4 -Dlanguage=JavaScript Chat.g4
30

Phần thú vị đầu tiên là thông điệp, không quá nhiều về những gì nó chứa, mà là cấu trúc mà nó đại diện. Chúng tôi đang nói rằng một

antlr4 -Dlanguage=JavaScript Chat.g4
205 có thể là bất kỳ thứ gì trong số các quy tắc được liệt kê theo bất kỳ thứ tự nào. Đây là một cách đơn giản để giải quyết vấn đề xử lý khoảng trắng mà không cần lặp lại mỗi lần. Vì chúng tôi, với tư cách người dùng, thấy khoảng trắng không liên quan nên chúng tôi thấy nội dung như
antlr4 -Dlanguage=JavaScript Chat.g4
206, nhưng trình phân tích cú pháp thực sự thấy
antlr4 -Dlanguage=JavaScript Chat.g4
207

Một cách khác để xử lý khoảng trắng, khi bạn không thể loại bỏ nó, nâng cao hơn. chế độ từ vựng. Về cơ bản, nó cho phép bạn chỉ định hai phần từ vựng. one for the structured part, the other for simple text. Điều này hữu ích cho việc phân tích cú pháp những thứ như XML hoặc HTML. Chúng tôi sẽ hiển thị nó sau

Quy tắc lệnh là rõ ràng, bạn chỉ cần lưu ý rằng bạn không thể có khoảng cách giữa hai tùy chọn cho lệnh và dấu hai chấm, nhưng bạn cần có một khoảng trắng sau. Quy tắc biểu tượng cảm xúc hiển thị một ký hiệu khác để biểu thị nhiều lựa chọn, bạn có thể sử dụng ký tự ống ‘. ' không có dấu ngoặc đơn. Chúng tôi chỉ hỗ trợ hai biểu tượng cảm xúc, vui và buồn, có hoặc không có đường kẻ ở giữa

Một thứ có thể được coi là lỗi hoặc triển khai kém là quy tắc liên kết, như chúng tôi đã nói, trên thực tế, TEXT nắm bắt mọi thứ ngoại trừ một số ký tự đặc biệt. Bạn có thể muốn chỉ cho phép WORD và WHITESPACE, bên trong dấu ngoặc đơn hoặc buộc định dạng đúng cho một liên kết, bên trong dấu ngoặc vuông. Mặt khác, điều này cho phép người dùng mắc lỗi khi viết liên kết mà không khiến trình phân tích cú pháp phàn nàn

Bạn phải nhớ rằng trình phân tích cú pháp không thể kiểm tra ngữ nghĩa

Chẳng hạn, nó không thể biết liệu TỪ chỉ màu có thực sự đại diện cho một màu hợp lệ hay không. Tức là nó không biết dùng “chó” là sai, dùng “đỏ” là đúng. Điều này phải được kiểm tra bằng logic của chương trình, có thể truy cập màu nào có sẵn. Bạn phải tìm sự cân bằng phù hợp trong việc phân chia việc thực thi giữa ngữ pháp và mã của riêng bạn

Trình phân tích cú pháp chỉ nên kiểm tra cú pháp. Vì vậy, quy tắc ngón tay cái là khi có nghi ngờ, bạn để trình phân tích cú pháp chuyển nội dung lên chương trình của bạn. Sau đó, trong chương trình của bạn, bạn kiểm tra ngữ nghĩa và đảm bảo rằng quy tắc thực sự có nghĩa phù hợp

Hãy nhìn vào màu quy tắc. it can include a message,  and it itself can be part of message; this ambiguity will be solved by the context in which the rule is applied

11. Mistakes and Adjustments

Before trying our new grammar, we have to add a name for it at the beginning of the file. The name must be identical to the file name, which should have the

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
7 extension

antlr4 -Dlanguage=JavaScript Chat.g4
31

Bạn có thể tìm cách cài đặt mọi thứ cho nền tảng của mình trong tài liệu chính thức. After everything is installed, we create the grammar, compile the generated Java code and then we run the testing tool

antlr4 -Dlanguage=JavaScript Chat.g4
32

Okay, it does not work. Why is it expecting WORD? It is right there. Let’s try to find out, using the option

antlr4 -Dlanguage=JavaScript Chat.g4
89 to make it show the tokens it recognizes

antlr4 -Dlanguage=JavaScript Chat.g4
33

So it only sees the TEXT token. But if we put it at the end of the grammar, what will happen? The problem is that it always tries to match the largest possible token. And all this text is a valid TEXT token. How do we solve this problem? There are many ways, the first, of course, is just getting rid of that token. But for now we are going to see the second easiest

antlr4 -Dlanguage=JavaScript Chat.g4
34

We have changed the problematic token to make it include a preceding parenthesis or square bracket. Note that this is not exactly the same thing, because it would allow two series of parentheses or square brackets. But it is a first step and we are learning here, after all

Let’s check if it works

antlr4 -Dlanguage=JavaScript Chat.g4
35

Sử dụng tùy chọn

antlr4 -Dlanguage=JavaScript Chat.g4
00, chúng ta cũng có thể có một biểu diễn đồ họa đẹp và dễ hiểu hơn

The dot in mid air represents whitespace

This works, but it is not very smart or nice, or organized. But don’t worry, we are going to see a better way later. Một khía cạnh tích cực của giải pháp này là nó cho phép hiển thị một thủ thuật khác

antlr4 -Dlanguage=JavaScript Chat.g4
36

Đây là một công thức tương đương của mã thông báo TEXT. the

antlr4 -Dlanguage=JavaScript Chat.g4
211 matches any character,
antlr4 -Dlanguage=JavaScript Chat.g4
212 says that the preceding match can be repeated any time,
antlr4 -Dlanguage=JavaScript Chat.g4
213 indicates that the previous match is non-greedy. Điều đó có nghĩa là quy tắc phụ trước khớp với mọi thứ trừ những gì theo sau nó, cho phép khớp với dấu ngoặc đơn đóng hoặc dấu ngoặc vuông

Mid-Level

Có vẻ như có quá nhiều việc phải làm không?
…Đây là Dịch vụ ANTLR của chúng tôi

We can design parsers for new languages, or rewrite parsers for existing languages built in house

And much more…

Dịch vụ ANTLR

Trong phần này, chúng ta sẽ thấy cách sử dụng ANTLR trong các chương trình của bạn, các thư viện và chức năng bạn cần sử dụng, cách kiểm tra trình phân tích cú pháp của bạn, v.v. Chúng tôi thấy những gì là và làm thế nào để sử dụng một người nghe. We also build up on our knowledge of the basics, by looking at more advanced concepts, such as semantic predicates. Mặc dù các dự án của chúng tôi chủ yếu bằng JavaScript và Python, khái niệm này thường áp dụng cho mọi ngôn ngữ. You can come back to this section when you need to remember how to get your project organized

12. Thiết lập dự án trò chuyện bằng JavaScript

Trong các phần trước, chúng ta đã thấy cách xây dựng ngữ pháp cho chương trình trò chuyện, từng phần một. Let’s now copy that grammar we just created in the same folder of our Javascript files

antlr4 -Dlanguage=JavaScript Chat.g4
37

Chúng ta có thể tạo trình phân tích cú pháp Javascript tương ứng chỉ bằng cách chỉ định tùy chọn chính xác với chương trình Java ANTLR4

antlr4 -Dlanguage=JavaScript Chat.g4

Bây giờ bạn sẽ tìm thấy một số tệp mới trong thư mục, với các tên như

antlr4 -Dlanguage=JavaScript Chat.g4
214
antlr4 -Dlanguage=JavaScript Chat.g4
215 và cũng có *. mã thông báo, không có tệp nào chứa bất kỳ điều gì thú vị đối với chúng tôi, trừ khi bạn muốn hiểu hoạt động bên trong của ANTLR

Tệp bạn muốn xem là

antlr4 -Dlanguage=JavaScript Chat.g4
216, bạn sẽ không sửa đổi bất cứ điều gì trong đó, nhưng nó chứa các phương thức và chức năng mà chúng tôi sẽ ghi đè bằng trình lắng nghe của riêng mình. Chúng tôi sẽ không sửa đổi nó vì các thay đổi sẽ bị ghi đè mỗi khi ngữ pháp được tạo lại

Nhìn vào nó, bạn có thể thấy một số hàm nhập/thoát, một cặp cho mỗi quy tắc trình phân tích cú pháp của chúng tôi. Các chức năng này sẽ được gọi khi gặp một đoạn mã phù hợp với quy tắc. Đây là triển khai mặc định của trình nghe cho phép bạn ghi đè các chức năng mà bạn cần, trên trình nghe dẫn xuất của bạn và để nguyên phần còn lại

antlr4 -Dlanguage=JavaScript Chat.g4
39

Cách khác để tạo một

antlr4 -Dlanguage=JavaScript Chat.g4
217 là tạo một
antlr4 -Dlanguage=JavaScript Chat.g4
218. Sự khác biệt chính là bạn không thể kiểm soát luồng của người nghe cũng như không trả lại bất kỳ thứ gì từ các chức năng của nó, trong khi bạn có thể thực hiện cả hai điều đó với khách truy cập. Vì vậy, nếu bạn cần kiểm soát cách nhập các nút của cây phân tích cú pháp hoặc để thu thập thông tin từ một vài trong số chúng, bạn có thể muốn sử dụng một khách truy cập. Điều này hữu ích, ví dụ, với việc tạo mã, trong đó một số thông tin cần thiết để tạo mã nguồn mới được lan truyền khắp nhiều phần. Cả người nghe và khách truy cập đều sử dụng tìm kiếm chuyên sâu

Tìm kiếm theo chiều sâu có nghĩa là khi một nút được truy cập, các nút con của nó sẽ được truy cập và nếu một trong các nút con có các nút con của chính nó, chúng sẽ được truy cập trước khi tiếp tục với các nút con khác của nút đầu tiên. Hình ảnh sau đây sẽ làm cho khái niệm đơn giản hơn để hiểu

Vì vậy, trong trường hợp của một người nghe, một sự kiện enter sẽ được kích hoạt ở lần gặp đầu tiên với nút và một sự kiện thoát sẽ được kích hoạt sau khi đã thoát khỏi tất cả các phần tử con của nó. Trong hình ảnh sau đây, bạn có thể xem ví dụ về chức năng nào sẽ được kích hoạt khi người nghe gặp nút đường [để đơn giản, chỉ các chức năng liên quan đến đường được hiển thị]

Với một khách truy cập tiêu chuẩn, hành vi sẽ tương tự, tất nhiên, ngoại trừ, chỉ một sự kiện truy cập duy nhất sẽ được kích hoạt cho mỗi nút. Trong hình ảnh sau đây, bạn có thể xem ví dụ về chức năng nào sẽ được kích hoạt khi khách truy cập gặp nút đường [để đơn giản, chỉ chức năng liên quan đến đường được hiển thị]

Hãy nhớ rằng điều này đúng với việc triển khai mặc định của khách truy cập và nó được thực hiện bằng cách trả về phần tử con của mỗi nút trong mọi chức năng. Nếu bạn ghi đè một phương thức của khách truy cập, bạn có trách nhiệm làm cho nó tiếp tục hành trình hoặc dừng nó ngay tại đó

13. con kiến. js

Cuối cùng cũng đến lúc xem một chương trình ANTLR điển hình trông như thế nào

antlr4 -Dlanguage=JavaScript Chat.g4
60

Ở phần đầu của tệp chính, chúng tôi nhập các thư viện và tệp cần thiết,

error[31]:  ANTLR cannot generate Javascript code as of version 4.9
8 [thời gian chạy] và trình phân tích cú pháp đã tạo của chúng tôi, cùng với trình nghe mà chúng tôi sẽ xem sau

Để đơn giản, chúng tôi lấy đầu vào từ một chuỗi, trong khi trong một tình huống thực tế, nó sẽ đến từ một trình soạn thảo

Dòng 17-20 cho thấy nền tảng của mọi chương trình ANTLR. bạn tạo luồng ký tự từ đầu vào, bạn đưa nó cho lexer và nó biến đổi chúng thành mã thông báo, sau đó được trình phân tích cú pháp diễn giải

Thật hữu ích khi dành một chút thời gian để suy nghĩ về điều này. the lexer works on the characters of the input, a copy of the input to be precise, while the parser works on the tokens generated by the lexer. The lexer does not work on the input directly, and the parser does not even see the characters

This is important to remember in case you need to do something advanced like manipulating the input. In this case the input is a string, but, of course, it could be any stream of content

The line 22 is redundant, since the option already defaults to true, but it shows that you can enable or disable it

Then, on line 23, we set the root node of the tree as a chat rule. You want to invoke the parser specifying a rule, which typically is the first rule. However, you can actually invoke any rule directly, like color

Once we get the parse tree from the parser, typically we want to process it using a listener or a visitor. In this case we specify a listener. Our particular listener takes a parameter. the response object. We want to use it to put some text in the response to send to the user. After setting the listener up, we finally walk the tree with our listener

14. HtmlChatListener. js

We continue by looking at the listener for our Chat project

antlr4 -Dlanguage=JavaScript Chat.g4
61

After the required function calls, we make our HtmlChatListener to extend ChatListener. The interesting stuff starts at line 12

The ctx argument is an instance of a specific class context for the node that we are entering/exiting. So for

antlr4 -Dlanguage=JavaScript Chat.g4
220 is
antlr4 -Dlanguage=JavaScript Chat.g4
221, for
antlr4 -Dlanguage=JavaScript Chat.g4
222 is
antlr4 -Dlanguage=JavaScript Chat.g4
223, etc. This specific context will have the proper elements for the rule, that would make possible to easily access the respective tokens and sub-rules. For example,
antlr4 -Dlanguage=JavaScript Chat.g4
221 will contain fields like WORD[] and WHITESPACE[];
antlr4 -Dlanguage=JavaScript Chat.g4
225will contain fields like WHITESPACE[], SAYS[] and SHOUTS[]

These functions,

antlr4 -Dlanguage=JavaScript Chat.g4
226 and
antlr4 -Dlanguage=JavaScript Chat.g4
227 are called by the walker every time the corresponding nodes are entered or exited while it’s traversing the AST that represents the program newline. A listener allows you to execute some code, but it’s important to remember that you cannot stop the execution of the walker and the execution of the functions

On line 13, we start by printing a

antlr4 -Dlanguage=JavaScript Chat.g4
228 tag because we want the name to be bold, then on exitName we take the text from the token WORD and close the tag. Note that we ignore the WHITESPACE token, nothing says that we have to show everything. In this case we could have done everything either on the enter or exit function, since nothing is happening in between them

On the function exitEmoticon we simply transform the emoticon text into an emoji character. We get the text of the whole rule because there are no tokens defined for this parser rule. On enterCommand, instead there could be any of two tokens SAYS or SHOUTS, so we check which one is defined. And then we alter the following text, by transforming in uppercase, if it’s a SHOUT. Lưu ý rằng chúng tôi đóng thẻ

antlr4 -Dlanguage=JavaScript Chat.g4
229 ở lối ra của quy tắc dòng, bởi vì lệnh, về mặt ngữ nghĩa, thay đổi tất cả nội dung của thông báo

All we have to do now is launch node, with

antlr4 -Dlanguage=JavaScript Chat.g4
230, and point our browser at its address, usually at
antlr4 -Dlanguage=JavaScript Chat.g4
231 and we will be greeted with the following image

Vì vậy, tất cả đều tốt, chúng tôi chỉ cần thêm tất cả các trình nghe khác nhau để xử lý phần còn lại của ngôn ngữ. Hãy bắt đầu với màu sắc và thông điệp

15. Làm việc với một Listener

Chúng tôi đã thấy làm thế nào để bắt đầu xác định một người nghe. Bây giờ, hãy nghiêm túc và xem cách phát triển thành một thiết bị nghe hoàn chỉnh, mạnh mẽ. Hãy bắt đầu bằng cách thêm hỗ trợ cho màu sắc và kiểm tra kết quả công việc khó khăn của chúng tôi

antlr4 -Dlanguage=JavaScript Chat.g4
62

Ngoại trừ việc nó không hoạt động. Hoặc có thể nó hoạt động quá nhiều. chúng tôi đang viết một phần của tin nhắn hai lần [“điều này sẽ hiệu quả”]. đầu tiên khi chúng tôi kiểm tra các nút cụ thể, là nút con của thông báo, sau đó ở cuối. Chúng tôi cũng đang viết biểu tượng cảm xúc không theo thứ tự. đó là bởi vì chúng tôi đang viết trực tiếp thay vì đợi kết thúc tin nhắn

May mắn là với JavaScript, chúng ta có thể tự động thay đổi các đối tượng, vì vậy chúng ta có thể tận dụng thực tế này để tự thay đổi đối tượng

antlr4 -Dlanguage=JavaScript Chat.g4
232

antlr4 -Dlanguage=JavaScript Chat.g4
63

Chỉ những phần sửa đổi được hiển thị trong đoạn mã trên. We add a text field to every node that transforms its text, and then at the exit of every message we print the text if it is the primary message, the one that is directly child of the line rule. Nếu đó là một tin nhắn, đó cũng là một phần tử con của màu, chúng tôi thêm trường văn bản vào nút mà chúng tôi đang thoát và để màu in nó. Chúng tôi kiểm tra điều này trên dòng 30, nơi chúng tôi xem xét nút cha để xem liệu đó có phải là một thể hiện của đối tượng

antlr4 -Dlanguage=JavaScript Chat.g4
233. This is also further evidence of how each ctx argument corresponds to the proper type

Between lines 23 and 28 we can see another field of every node of the generated tree.

antlr4 -Dlanguage=JavaScript Chat.g4
234, which obviously contains the children node. You can observe that if a field text exists, we add it to the proper variable, otherwise we use the usual function to get the text of the node

16. Solving Ambiguities with Semantic Predicates

So far we have seen how to build a parser for a chat language in JavaScript. Let’s continue working on this grammar but switch to Python. Hãy nhớ rằng tất cả mã có sẵn trong kho lưu trữ. Before that, we have to solve an annoying problem. mã thông báo TEXT. Giải pháp  chúng tôi có  rất tệ và hơn nữa, nếu chúng tôi cố gắng lấy văn bản của mã thông báo, chúng tôi sẽ phải cắt bớt các cạnh, dấu ngoặc đơn hoặc dấu ngoặc vuông. Vậy chúng ta có thể làm gì?

Chúng ta có thể sử dụng một tính năng cụ thể của ANTLR được gọi là vị từ ngữ nghĩa. Như tên ngụ ý, chúng là các biểu thức tạo ra giá trị boolean. They selectively enable or disable the following rule and thus permit to solve ambiguities. Another reason why they could be used is to support different versions of the same language, for instance a version with a new construct or an old without it

Về mặt kỹ thuật, chúng là một phần của nhóm hành động lớn hơn, cho phép nhúng mã tùy ý vào ngữ pháp. Nhược điểm là ngữ pháp không còn độc lập với ngôn ngữ nữa, vì mã trong hành động phải hợp lệ cho ngôn ngữ đích. For this reason, usually it is considered a good idea to only use semantic predicates when they cannot be avoided, and leave most of the code to the visitor/listener

antlr4 -Dlanguage=JavaScript Chat.g4
64

Chúng tôi đã khôi phục liên kết về công thức ban đầu nhưng chúng tôi đã thêm một vị ngữ ngữ nghĩa vào mã thông báo TEXT, được viết bên trong dấu ngoặc nhọn và theo sau là dấu chấm hỏi. Chúng tôi sử dụng

antlr4 -Dlanguage=JavaScript Chat.g4
235 để kiểm tra ký tự trước ký tự hiện tại, nếu ký tự này là dấu ngoặc vuông hoặc dấu ngoặc đơn mở, chúng tôi kích hoạt mã thông báo TEXT. Điều quan trọng cần nhắc lại là đây phải là mã hợp lệ trong ngôn ngữ đích của chúng ta, vì nó sẽ kết thúc trong Lexer hoặc Trình phân tích cú pháp được tạo, trong trường hợp của chúng ta là vào
antlr4 -Dlanguage=JavaScript Chat.g4
236

Điều này không chỉ quan trọng đối với chính cú pháp mà còn bởi vì các mục tiêu khác nhau có thể có các trường hoặc phương thức khác nhau, chẳng hạn như

antlr4 -Dlanguage=JavaScript Chat.g4
237 trả về một
antlr4 -Dlanguage=JavaScript Chat.g4
238 trong python, vì vậy chúng tôi phải chuyển đổi
antlr4 -Dlanguage=JavaScript Chat.g4
239 thành một
antlr4 -Dlanguage=JavaScript Chat.g4
238

Hãy xem dạng tương đương trong các ngôn ngữ khác

antlr4 -Dlanguage=JavaScript Chat.g4
65

Nếu bạn muốn kiểm tra mã thông báo trước đó, bạn có thể sử dụng

antlr4 -Dlanguage=JavaScript Chat.g4
241, nhưng bạn chỉ có thể làm điều đó cho các quy tắc trình phân tích cú pháp. Ví dụ: nếu bạn chỉ muốn bật quy tắc đề cập nếu trước mã thông báo WHITESPACE

antlr4 -Dlanguage=JavaScript Chat.g4
66

17. Tiếp tục trò chuyện bằng Python

Trước khi xem ví dụ Python, chúng ta phải sửa đổi ngữ pháp của mình và đặt mã thông báo TEXT trước WORD. Nếu không, ANTLR có thể chỉ định mã thông báo không chính xác, trong trường hợp các ký tự nằm giữa dấu ngoặc đơn hoặc dấu ngoặc vuông đều hợp lệ cho WORD, chẳng hạn nếu nó ở nơi

antlr4 -Dlanguage=JavaScript Chat.g4
242

Sử dụng ANTLR trong python không khó hơn bất kỳ nền tảng nào khác, bạn chỉ cần chú ý đến phiên bản Python, 2 hoặc 3

antlr4 -Dlanguage=JavaScript Chat.g4
0

Và đó là nó. So when you have run the command, inside the directory of your python project, there will be a newly generated parser and a lexer. Bạn có thể thấy thú vị khi xem xét

antlr4 -Dlanguage=JavaScript Chat.g4
243 và đặc biệt là hàm
antlr4 -Dlanguage=JavaScript Chat.g4
244[sempred là viết tắt của vị từ ngữ nghĩa]

antlr4 -Dlanguage=JavaScript Chat.g4
68

Bạn có thể thấy vị từ của chúng tôi ngay trong mã. Điều này cũng có nghĩa là bạn phải kiểm tra xem trình phân tích cú pháp đã tạo có đáp ứng đúng yêu cầu hay không. For instance, you need to import somewhere in the lexer any necessary library for the functions used in the predicate

18. Cách Python làm việc với một Listener

The main file of a Python project is very similar to a JavaScript one, mutatis mutandis of course. That is to say we have to adapt libraries and functions to the proper version for a different language

antlr4 -Dlanguage=JavaScript Chat.g4
69

Chúng tôi cũng đã thay đổi đầu vào và đầu ra thành tệp, điều này giúp tránh phải khởi chạy máy chủ bằng Python. Điều này cũng giải quyết vấn đề là thiết bị đầu cuối mặc định trong Windows chỉ hỗ trợ một số ký tự [tôi. e. , không phải Unicode]

antlr4 -Dlanguage=JavaScript Chat.g4
20

Apart from lines 35-36, in which we introduce support for links, there is nothing new. Mặc dù bạn có thể nhận thấy rằng cú pháp Python sạch hơn và trong khi có kiểu gõ động, nó không được gõ lỏng lẻo như JavaScript. Các loại đối tượng

antlr4 -Dlanguage=JavaScript Chat.g4
232 khác nhau được viết rõ ràng. Giá như các công cụ Python dễ sử dụng như chính ngôn ngữ này. Nhưng tất nhiên chúng tôi không thể bay qua trăn như thế này, vì vậy chúng tôi cũng giới thiệu thử nghiệm

19. Thử nghiệm với Python

Mặc dù Visual Studio Code có một tiện ích mở rộng rất hay cho Python cũng hỗ trợ kiểm tra đơn vị, nhưng chúng tôi sẽ sử dụng dòng lệnh vì mục đích tương thích

antlr4 -Dlanguage=JavaScript Chat.g4
21

Đó là cách bạn chạy thử nghiệm, nhưng trước đó, chúng ta phải viết chúng. Trên thực tế, ngay cả trước đó, chúng tôi phải viết một

antlr4 -Dlanguage=JavaScript Chat.g4
246 để quản lý các lỗi mà chúng tôi có thể tìm thấy. Mặc dù chúng ta có thể chỉ cần đọc văn bản do trình xử lý lỗi mặc định xuất ra, nhưng có một lợi thế khi sử dụng triển khai của chính chúng ta, cụ thể là chúng ta có thể kiểm soát dễ dàng hơn những gì xảy ra

antlr4 -Dlanguage=JavaScript Chat.g4
22

Lớp của chúng tôi bắt nguồn từ

antlr4 -Dlanguage=JavaScript Chat.g4
246 và chúng tôi chỉ cần thực hiện
antlr4 -Dlanguage=JavaScript Chat.g4
248. Mặc dù chúng tôi cũng thêm một ký hiệu thuộc tính để dễ dàng kiểm tra xem ký hiệu nào có thể đã gây ra lỗi

antlr4 -Dlanguage=JavaScript Chat.g4
23

Phương pháp

antlr4 -Dlanguage=JavaScript Chat.g4
249 được sử dụng để đảm bảo rằng mọi thứ được đặt đúng cách; . Chúng tôi đang lắng nghe lỗi trong trình phân tích cú pháp, nhưng chúng tôi cũng có thể bắt lỗi do từ vựng tạo ra. Nó phụ thuộc vào những gì bạn muốn kiểm tra. Bạn có thể muốn kiểm tra cả hai

Hai phương pháp kiểm tra thích hợp kiểm tra tên hợp lệ và tên không hợp lệ. Các kiểm tra được liên kết với ký hiệu thuộc tính mà chúng tôi đã xác định trước đó, nếu nó trống thì mọi thứ đều ổn, nếu không thì nó chứa ký hiệu đã tạo ra lỗi. Lưu ý rằng trên dòng 28, có một khoảng trắng ở cuối chuỗi, vì chúng tôi đã xác định tên quy tắc kết thúc bằng mã thông báo WHITESPACE

20. Phân tích đánh dấu

ANTLR có thể phân tích cú pháp nhiều thứ, kể cả dữ liệu nhị phân, trong trường hợp đó, mã thông báo được tạo thành từ các ký tự không in được. Nhưng một vấn đề phổ biến hơn là phân tích ngôn ngữ đánh dấu như XML hoặc HTML. Đánh dấu cũng là một định dạng hữu ích để áp dụng cho các sáng tạo của riêng bạn vì nó cho phép kết hợp nội dung văn bản phi cấu trúc với các chú thích có cấu trúc. They fundamentally represent a form of smart document, containing both text and structured data. The technical term that describes them is island languages. Thuật ngữ này không bị giới hạn chỉ bao gồm các ngôn ngữ đánh dấu và đôi khi nó là vấn đề quan điểm

Ví dụ: bạn có thể phải xây dựng trình phân tích cú pháp chỉ xử lý các chỉ thị tiền xử lý. Trong trường hợp đó, bạn phải tìm cách phân biệt mã phù hợp với các lệnh tuân theo các quy tắc khác nhau. In such an example the preprocessor directives might be considered an island language, a separate language surrounded by meaningless [for parsing purposes] text

Trong mọi trường hợp, vấn đề đối với việc phân tích các ngôn ngữ như vậy là có rất nhiều văn bản mà chúng ta không thực sự phải phân tích cú pháp, nhưng chúng ta không thể bỏ qua hoặc loại bỏ, bởi vì văn bản chứa thông tin hữu ích cho người dùng và nó là một phần cấu trúc của . Giải pháp là các chế độ từ vựng, một cách để phân tích nội dung có cấu trúc bên trong một biển văn bản miễn phí lớn hơn

21. chế độ từ vựng

Chúng ta sẽ xem cách sử dụng các chế độ từ vựng, bằng cách bắt đầu với một ngữ pháp mới.

antlr4 -Dlanguage=JavaScript Chat.g4
24

Looking at the first line you could notice a difference. chúng tôi đang xác định một

antlr4 -Dlanguage=JavaScript Chat.g4
251, thay vì
antlr4 -Dlanguage=JavaScript Chat.g4
252 thông thường. Bạn chỉ đơn giản là không thể xác định chế độ từ vựng cùng với ngữ pháp trình phân tích cú pháp. Bạn chỉ có thể sử dụng các chế độ từ vựng trong ngữ pháp từ vựng, không phải trong ngữ pháp kết hợp. Phần còn lại không có gì đáng ngạc nhiên, như bạn có thể thấy, chúng tôi đang xác định một loại đánh dấu BBCode, với các thẻ được phân định bằng dấu ngoặc vuông

Ở các dòng 3, 7 và 9 về cơ bản bạn sẽ tìm thấy tất cả những gì bạn cần biết về chế độ từ vựng. Bạn xác định một hoặc nhiều mã thông báo có thể phân định các chế độ khác nhau và kích hoạt chúng

The default mode is already implicitly defined, if you need to define yours you simply use

antlr4 -Dlanguage=JavaScript Chat.g4
253 followed by a name. Other than for markup languages, lexical modes are typically used to deal with string interpolation. Đó là khi một chuỗi ký tự có thể chứa nhiều hơn văn bản đơn giản, chẳng hạn như các biểu thức tùy ý

Khi chúng tôi sử dụng ngữ pháp kết hợp, chúng tôi có thể định nghĩa các mã thông báo một cách ngầm định. that is what happened when we used a string like

antlr4 -Dlanguage=JavaScript Chat.g4
254 in a parser rule. Bây giờ chúng tôi đang sử dụng ngữ pháp trình phân tích cú pháp và trình phân tích cú pháp riêng biệt, chúng tôi không thể làm điều đó. Điều đó có nghĩa là mọi mã thông báo phải được xác định rõ ràng. Vì vậy, chúng tôi có các định nghĩa như SLASH hoặc EQUALS thường chỉ có thể được sử dụng trực tiếp trong quy tắc trình phân tích cú pháp. Khái niệm rất đơn giản.  in the lexer grammar, we need to define all tokens, because they cannot be defined later in the parser grammar

22. Trình phân tích ngữ pháp

Chúng tôi nhìn vào mặt khác của ngữ pháp từ vựng, có thể nói như vậy

antlr4 -Dlanguage=JavaScript Chat.g4
25

Trên dòng đầu tiên, chúng tôi xác định một

antlr4 -Dlanguage=JavaScript Chat.g4
255. Vì các mã thông báo chúng tôi cần được xác định trong ngữ pháp từ vựng, chúng tôi cần sử dụng một tùy chọn để nói với ANTLR nơi nó có thể tìm thấy chúng. Điều này không cần thiết trong ngữ pháp kết hợp, vì các mã thông báo được xác định trong cùng một tệp

Có nhiều tùy chọn khác có sẵn, trong tài liệu

Hầu như không có gì khác để thêm, ngoại trừ việc chúng tôi xác định quy tắc nội dung để chúng tôi có thể quản lý dễ dàng hơn văn bản mà chúng tôi tìm thấy sau này trong chương trình

Tôi chỉ muốn nói rằng, như bạn có thể thấy, chúng ta không cần phải sử dụng mã thông báo một cách rõ ràng mỗi lần [e. g. , SLASH], nhưng thay vào đó chúng ta có thể sử dụng văn bản tương ứng [e. g. ,

antlr4 -Dlanguage=JavaScript Chat.g4
256]

ANTLR sẽ tự động chuyển đổi văn bản trong mã thông báo tương ứng, nhưng điều này chỉ có thể xảy ra nếu chúng đã được xác định. Tóm lại, như thể chúng ta đã viết

antlr4 -Dlanguage=JavaScript Chat.g4
26

Nhưng chúng ta không thể sử dụng cách ngầm định, nếu chúng ta chưa định nghĩa rõ ràng chúng trong ngữ pháp từ vựng. Một cách khác để xem xét điều này là. khi chúng tôi xác định ngữ pháp kết hợp, ANTLR xác định cho chúng tôi tất cả các mã thông báo mà chúng tôi chưa xác định rõ ràng. Khi chúng tôi cần sử dụng ngữ pháp từ vựng và trình phân tích cú pháp riêng biệt, chúng tôi phải tự xác định rõ ràng mọi mã thông báo. Once we have done that, we can use them in every way we want

Before moving to actual Java code, let’s see the parse tree for a sample input

Bạn có thể dễ dàng nhận thấy rằng quy tắc phần tử khá minh bạch. nơi bạn mong muốn tìm thấy nó sẽ luôn có một thẻ hoặc nội dung. Vậy tại sao chúng tôi định nghĩa nó? . tránh lặp lại trong ngữ pháp của chúng tôi và đơn giản hóa việc quản lý kết quả phân tích cú pháp

We avoid repetition because if we did not have the element rule, we should repeat 

antlr4 -Dlanguage=JavaScript Chat.g4
257 everywhere it is used. Điều gì sẽ xảy ra nếu một ngày chúng ta thêm một loại phần tử mới?

Advanced

Câu hỏi ANTLR của bạn đã được trả lời

A collection of answers to common issues that you encounter and useful patterns that you can use when creating ANTLR parsers

Chúng tôi cũng bao gồm một trang phục dành cho ANTLR mà bạn có thể sử dụng làm tài liệu tham khảo hữu ích

Tìm hiểu thêm về Câu hỏi thường gặp về ANTLR

In this section we deepen our understanding of ANTLR. We will look at more complex examples and situations we may have to handle in our parsing adventures. Chúng tôi sẽ tìm hiểu cách thực hiện kiểm tra nâng cao hơn, để phát hiện nhiều lỗi hơn và đảm bảo chất lượng tốt hơn cho mã của chúng tôi. Chúng ta sẽ xem khách truy cập là gì và cách sử dụng nó. Cuối cùng, chúng ta sẽ xem cách xử lý các biểu thức và mức độ phức tạp mà chúng mang lại.
Bạn có thể quay lại phần này khi cần xử lý các sự cố phân tích cú pháp phức tạp.

23. Dự án đánh dấu trong Java

Bạn có thể làm theo hướng dẫn trong Thiết lập Java hoặc chỉ cần sao chép thư mục____1259 của kho lưu trữ đồng hành. Sau khi tệp

antlr4 -Dlanguage=JavaScript Chat.g4
260 được định cấu hình đúng cách, đây là cách bạn xây dựng và thực thi ứng dụng

antlr4 -Dlanguage=JavaScript Chat.g4
27

Như bạn có thể thấy, nó không khác bất kỳ dự án Gradle điển hình nào, mặc dù nó thực sự phức tạp hơn một dự án JavaScript hoặc Python thông thường. Tất nhiên, nếu bạn sử dụng IDE, bạn không cần phải làm bất cứ điều gì khác với quy trình làm việc điển hình của mình

24. Ứng dụng chính. java

Chúng ta sẽ xem cách viết một ứng dụng ANTLR điển hình bằng Java

antlr4 -Dlanguage=JavaScript Chat.g4
28

Có một bất ngờ nhỏ liên quan đến biến

antlr4 -Dlanguage=JavaScript Chat.g4
261. Instead of using an
antlr4 -Dlanguage=JavaScript Chat.g4
262 class we are using a
antlr4 -Dlanguage=JavaScript Chat.g4
263 one. This difference applies to Java and C# and it is due to Unicode support. Ý chính là phiên bản trước của thời gian chạy cho các ngôn ngữ này chỉ hỗ trợ một phần Unicode, do đó, để tránh bất kỳ thay đổi đáng ngạc nhiên nào về hành vi, [ANTLR]InputStream cũ không được dùng nữa. Bạn có thể đọc thêm về tài liệu ANTLR chính thức

Apart from this change, at this point the main java file should not come as a surprise. sự phát triển mới duy nhất là khách truy cập. Tất nhiên, có sự khác biệt nhỏ rõ ràng trong tên của các lớp ANTLR và như vậy. This time we are building a visitor, whose main advantage is the chance to control the flow of the program. Trong khi chúng tôi vẫn đang xử lý văn bản, chúng tôi không muốn hiển thị nó, chúng tôi muốn chuyển đổi nó từ giả BBCode sang giả Markdown

25. Chuyển đổi mã với ANTLR

Vấn đề đầu tiên cần giải quyết với bản dịch của chúng tôi từ giả BBCode sang giả Markdown là một quyết định thiết kế. Hai ngôn ngữ của chúng tôi khác nhau và thẳng thắn mà nói, cả hai ngôn ngữ gốc đều không được thiết kế tốt

BBCode được tạo ra như một biện pháp phòng ngừa an toàn, để có thể không cho phép sử dụng HTML nhưng cung cấp một số quyền lực của nó cho người dùng. Markdown được tạo ra để trở thành một định dạng dễ đọc và dễ viết, có thể dịch sang HTML. Vì vậy, cả hai đều bắt chước HTML và bạn thực sự có thể sử dụng HTML trong tài liệu Markdown. Hãy bắt đầu tìm hiểu xem một chuyển đổi thực tế sẽ lộn xộn như thế nào

antlr4 -Dlanguage=JavaScript Chat.g4
29

Phiên bản đầu tiên của khách truy cập của chúng tôi in tất cả văn bản và bỏ qua tất cả các thẻ

Bạn có thể xem cách kiểm soát luồng bằng cách gọi hàm

antlr4 -Dlanguage=JavaScript Chat.g4
264 hoặc bất kỳ hàm
antlr4 -Dlanguage=JavaScript Chat.g4
265 nào khác và quyết định nội dung trả về. Chúng tôi chỉ cần ghi đè các phương thức mà chúng tôi muốn thay đổi. Otherwise, the default implementation would just do like
antlr4 -Dlanguage=JavaScript Chat.g4
266, on line 24, it will visit the children nodes and allow the visitor to continue. Giống như đối với người nghe, đối số là loại ngữ cảnh thích hợp. Nếu bạn muốn dừng khách truy cập, chỉ cần trả về null như trên dòng 16

26. Joy and Pain of Transforming Code

Chuyển đổi mã, thậm chí ở mức rất đơn giản, đi kèm với một số phức tạp. Let’s start easy with some basic visitor methods

antlr4 -Dlanguage=JavaScript Chat.g4
50

Trước khi xem phương pháp chính, hãy xem những phương pháp hỗ trợ. Trước hết, chúng tôi đã thay đổi

antlr4 -Dlanguage=JavaScript Chat.g4
266 bằng cách làm cho nó trả về văn bản thay vì in ra. Thứ hai, chúng tôi đã ghi đè
antlr4 -Dlanguage=JavaScript Chat.g4
268 để nó in văn bản của phần tử con, nhưng chỉ khi nó là phần tử trên cùng chứ không phải bên trong thẻ. Trong cả hai trường hợp, nó đạt được điều này bằng cách gọi đúng phương thức
antlr4 -Dlanguage=JavaScript Chat.g4
265. It knows which one to call because it checks if it actually has a tag or content node

antlr4 -Dlanguage=JavaScript Chat.g4
51

antlr4 -Dlanguage=JavaScript Chat.g4
270 contains more code than every other method, because it can also contain other elements, including other tags that have to be managed themselves, and thus they cannot be simply printed. Chúng tôi lưu nội dung của ID trên dòng 7, tất nhiên chúng tôi không cần kiểm tra xem thẻ kết thúc tương ứng có khớp không, vì trình phân tích cú pháp sẽ đảm bảo điều đó, miễn là đầu vào được định dạng tốt

Biến chứng đầu tiên bắt đầu từ dòng 14-15. như thường xảy ra khi chuyển đổi một ngôn ngữ sang một ngôn ngữ khác, không có sự tương ứng hoàn hảo giữa hai ngôn ngữ. While BBCode tries to be a smarter and safer replacement for HTML, Markdown wants to accomplish the same objective of HTML, to create a structured document. Vì vậy, BBCode có thẻ gạch chân, trong khi Markdown thì không

Vì vậy chúng ta phải đưa ra quyết định

Chúng tôi có muốn loại bỏ thông tin hay in trực tiếp HTML hay cái gì khác không? . That might seem completely arbitrary, and indeed there is an element of choice in this decision. But the conversion forces us to lose some information, and both are used for emphasis, so we choose the closer thing in the new language

Trường hợp sau, ở dòng 18-22, buộc chúng ta phải đưa ra lựa chọn khác. Chúng tôi không thể duy trì thông tin về tác giả của trích dẫn theo cách có cấu trúc, vì vậy chúng tôi chọn in thông tin theo cách có ý nghĩa đối với người đọc

Trên các dòng 28-34, chúng tôi thực hiện phép thuật của mình. we visit the children and gather their text, then we close with the endDelimiter. Cuối cùng, chúng tôi trả lại văn bản mà chúng tôi đã tạo

That’s how the visitor works

  1. mọi phần tử trên cùng đều đến thăm từng phần tử con
    • nếu đó là một nút nội dung, thì nó sẽ trực tiếp trả về văn bản
    • nếu đó là một thẻ, thì nó sẽ thiết lập các dấu phân cách chính xác và sau đó, nó sẽ kiểm tra các phần tử con của nó. Nó lặp lại bước 2 cho mỗi đứa trẻ và sau đó nó trả về văn bản đã thu thập
  2. nó in văn bản được trả về

It is obviously a simple example, but it shows how you can have great freedom in managing the visitor once you have launched it. Together with the patterns that we have seen at the beginning of this section, you can see all of the options. to return null to stop the visit, to return children to continue, to return something to perform an action ordered at a higher level of the tree

27. Kiểm tra nâng cao

Việc sử dụng các chế độ từ vựng cho phép xử lý phân tích cú pháp các ngôn ngữ đảo, nhưng nó làm phức tạp việc kiểm tra

Chúng tôi sẽ không hiển thị

antlr4 -Dlanguage=JavaScript Chat.g4
271 vì chúng tôi không thay đổi nó;

Bạn có thể chạy thử nghiệm bằng cách sử dụng lệnh sau

antlr4 -Dlanguage=JavaScript Chat.g4
52

Now we are going to look at the tests code. We are skipping the setup part, because that also is obvious, we just copy the process seen on the main file, but we simply add our error listener to intercept the errors

antlr4 -Dlanguage=JavaScript Chat.g4
53

Hai phương thức đầu tiên giống hệt như trước đây, chúng tôi chỉ cần kiểm tra xem không có lỗi nào không hoặc có đúng không vì bản thân đầu vào bị sai. Ở dòng 36-38, mọi thứ bắt đầu trở nên thú vị. vấn đề là bằng cách kiểm tra từng quy tắc một, chúng tôi không tạo cơ hội cho trình phân tích cú pháp tự động chuyển sang chế độ chính xác. Vì vậy, nó luôn ở trên DEFAULT_MODE, trong trường hợp của chúng tôi làm cho mọi thứ trông giống như TEXT. Điều này rõ ràng làm cho việc phân tích cú pháp chính xác của một thuộc tính là không thể

Các dòng tương tự cũng cho biết cách bạn có thể kiểm tra chế độ hiện tại mà bạn đang sử dụng và loại mã thông báo chính xác mà trình phân tích cú pháp tìm thấy mà chúng tôi sử dụng để xác nhận rằng thực sự tất cả đều sai trong trường hợp này

Mặc dù chúng tôi có thể sử dụng một chuỗi văn bản để kích hoạt chế độ chính xác mỗi lần, nhưng điều đó sẽ khiến quá trình thử nghiệm đan xen với một số đoạn mã, đây là điều không nên. Vì vậy, giải pháp được nhìn thấy trên dòng 46. chúng tôi kích hoạt chế độ chính xác theo cách thủ công. Khi bạn đã hoàn thành việc đó, bạn có thể thấy rằng thuộc tính của chúng tôi được nhận dạng chính xác

28. Xử lý các biểu thức

Cho đến nay chúng ta đã viết các quy tắc trình phân tích cú pháp đơn giản, bây giờ chúng ta sẽ xem một trong những phần khó khăn nhất trong việc phân tích một ngôn ngữ [lập trình] thực. expressions. Mặc dù các quy tắc cho các câu lệnh thường lớn hơn, nhưng chúng khá đơn giản để xử lý. bạn chỉ cần viết một quy tắc đóng gói cấu trúc với tất cả các phần tùy chọn khác nhau. For instance, a

antlr4 -Dlanguage=JavaScript Chat.g4
272 statement can include all other kinds of statements, but we can simply include them with something like
antlr4 -Dlanguage=JavaScript Chat.g4
273An expression, instead, can be combined in many different ways

Một biểu thức thường chứa các biểu thức khác. Ví dụ: biểu thức nhị phân điển hình bao gồm một biểu thức ở bên trái, một toán tử ở giữa và một biểu thức khác ở bên phải. Điều này có thể dẫn đến sự mơ hồ. Ví dụ, hãy suy nghĩ tại biểu thức

antlr4 -Dlanguage=JavaScript Chat.g4
274, đối với ANTLR, biểu thức này không rõ ràng vì có hai cách phân tích cú pháp. Nó có thể phân tích cú pháp thành
antlr4 -Dlanguage=JavaScript Chat.g4
275 hoặc
antlr4 -Dlanguage=JavaScript Chat.g4
276

Cho đến thời điểm này, chúng tôi đã tránh được vấn đề đơn giản vì các cấu trúc đánh dấu bao quanh đối tượng mà chúng được áp dụng. Vì vậy, không có sự mơ hồ trong việc lựa chọn áp dụng cái nào trước. nó là bên ngoài nhất. Hãy tưởng tượng nếu biểu thức này được viết là.  

antlr4 -Dlanguage=JavaScript Chat.g4
54

Điều đó sẽ làm rõ ràng cho ANTLR cách phân tích nó

Các loại quy tắc này được gọi là quy tắc đệ quy trái. Bạn có thể nói. chỉ cần phân tích bất cứ điều gì đến trước. Vấn đề với điều đó là ngữ nghĩa. phép cộng có trước, nhưng chúng ta biết rằng phép nhân có trước phép cộng. Traditionally, the way to solve this problem was to create a complex cascade of specific expressions like this

antlr4 -Dlanguage=JavaScript Chat.g4
55

Bằng cách này, ANTLR sẽ biết tìm kiếm một số trước, sau đó là phép nhân và cuối cùng là phép cộng. Điều này rườm rà và cũng phản trực giác vì biểu thức cuối cùng là biểu thức đầu tiên thực sự được nhận dạng. May mắn thay, ANTLR4 có thể tự động tạo cấu trúc tương tự, vì vậy chúng tôi có thể sử dụng cú pháp tự nhiên hơn nhiều

antlr4 -Dlanguage=JavaScript Chat.g4
56

In practice ANTLR consider the order in which we defined the alternatives to decide the precedence. Bằng cách viết quy tắc theo cách này, chúng tôi đang nói với ANTLR rằng phép nhân được ưu tiên hơn phép cộng

29. Phân tích bảng tính

Bây giờ chúng tôi đã chuẩn bị để tạo ứng dụng cuối cùng của mình, trong C#. Chúng ta sẽ xây dựng trình phân tích cú pháp của một ứng dụng giống như Excel. Trong thực tế, chúng tôi muốn quản lý các biểu thức bạn viết trong các ô của bảng tính

antlr4 -Dlanguage=JavaScript Chat.g4
57

Với tất cả những kiến ​​thức bạn có được cho đến nay, mọi thứ sẽ rõ ràng, có thể ngoại trừ ba điều

  1. tại sao có dấu ngoặc đơn,
  2. những thứ bên phải là gì,
  3. thứ đó ở dòng 6

Dấu ngoặc đơn xuất hiện trước vì vai trò duy nhất của chúng là cung cấp cho người dùng cách ghi đè quyền ưu tiên của toán tử, nếu họ cần làm như vậy. Biểu diễn đồ họa này của AST sẽ làm cho nó rõ ràng

Những thứ bên phải là nhãn, chúng được sử dụng để làm cho ANTLR tạo các chức năng cụ thể cho khách truy cập hoặc người nghe. So there will be a

antlr4 -Dlanguage=JavaScript Chat.g4
277, a
antlr4 -Dlanguage=JavaScript Chat.g4
278, etc. Điều này giúp có thể tránh việc sử dụng một lượng lớn khách truy cập cho quy tắc biểu thức

Biểu thức liên quan đến lũy thừa là khác nhau vì có hai cách có thể thực hiện, để nhóm chúng, khi bạn gặp hai biểu thức liên tiếp cùng loại. The first one is to execute the one on the left first and then the one on the right, the second one is the inverse. this is called associativity. Thông thường, tùy chọn bạn muốn sử dụng là liên kết trái, đây là tùy chọn mặc định. Tuy nhiên, lũy thừa là liên kết phải, vì vậy chúng tôi phải báo hiệu điều này với ANTLR

Một cách khác để xem xét điều này là. nếu có hai biểu thức cùng loại thì biểu thức nào được ưu tiên. bên trái hay bên phải?

Chúng tôi cũng có hỗ trợ cho các hàm, biến chữ và số đại diện cho các ô và số thực

30. Dự án bảng tính trong C#

Bạn chỉ cần làm theo C# Setup. to install a nuget package for the runtime and an ANTLR4 extension for Visual Studio. Tiện ích mở rộng sẽ tự động tạo mọi thứ bất cứ khi nào bạn xây dựng dự án của mình. trình phân tích cú pháp, trình nghe và/hoặc khách truy cập

Lưu ý rằng có hai sự khác biệt nhỏ giữa mã cho dự án sử dụng tiện ích mở rộng và dự án sử dụng công cụ Java. These are noted in the README for the C# project at the repository

After you have done that, you can also add grammar files just by using the usual menu Add -> New Item. Thực hiện chính xác điều đó để tạo ngữ pháp có tên là

antlr4 -Dlanguage=JavaScript Chat.g4
279 và đặt vào đó ngữ pháp mà chúng ta vừa tạo. Bây giờ hãy xem
antlr4 -Dlanguage=JavaScript Chat.g4
280 chính

antlr4 -Dlanguage=JavaScript Chat.g4
58

Không có gì để nói, ngoài điều đó, tất nhiên, bạn phải chú ý đến một biến thể nhỏ khác trong cách đặt tên cho sự vật. chú ý đến vỏ bọc và giao diện. Chẳng hạn,

antlr4 -Dlanguage=JavaScript Chat.g4
281, trong chương trình C#, là
antlr4 -Dlanguage=JavaScript Chat.g4
263 trong chương trình Java

Ngoài ra, bạn có thể nhận thấy rằng, lần này, chúng tôi xuất ra màn hình kết quả của khách truy cập, thay vì ghi kết quả vào một tệp

31. Excel bị tiêu diệt

Chúng tôi sẽ xem xét khách truy cập của chúng tôi cho dự án Bảng tính

antlr4 -Dlanguage=JavaScript Chat.g4
59

antlr4 -Dlanguage=JavaScript Chat.g4
283 and
antlr4 -Dlanguage=JavaScript Chat.g4
284 return the actual numbers that are represented either by the literal number or the variable. Trong một kịch bản thực, Kho lưu trữ dữ liệu sẽ chứa các phương thức để truy cập dữ liệu trong ô thích hợp, nhưng trong ví dụ của chúng tôi chỉ là một Từ điển với một số khóa và số. Các phương pháp khác thực sự hoạt động theo cùng một cách. họ truy cập/gọi [các] biểu thức chứa. Sự khác biệt duy nhất là những gì họ làm với kết quả

Một số thực hiện thao tác trên kết quả, thao tác nhị phân kết hợp hai kết quả theo cách thích hợp và cuối cùng,

antlr4 -Dlanguage=JavaScript Chat.g4
285 chỉ báo cáo kết quả cao hơn trên chuỗi. Toán học là đơn giản, khi nó được thực hiện bởi một máy tính

32. Kiểm tra mọi thứ

Cho đến bây giờ, chúng tôi chỉ kiểm tra các quy tắc của trình phân tích cú pháp, nghĩa là chúng tôi chỉ kiểm tra nếu chúng tôi đã tạo đúng quy tắc để phân tích cú pháp đầu vào của mình. Bây giờ chúng tôi cũng sẽ kiểm tra các chức năng của khách truy cập. Đây là cơ hội lý tưởng vì khách truy cập của chúng tôi trả về các giá trị mà chúng tôi có thể kiểm tra riêng lẻ. Trong những trường hợp khác, chẳng hạn nếu khách truy cập của bạn in nội dung nào đó lên màn hình, bạn có thể muốn viết lại cho khách truy cập viết trên luồng. Sau đó, tại thời điểm thử nghiệm, bạn có thể dễ dàng nắm bắt đầu ra

Chúng tôi sẽ không chiếu

antlr4 -Dlanguage=JavaScript Chat.g4
286 vì nó giống với cái trước mà chúng tôi đã xem;

Để thực hiện kiểm thử đơn vị với C#, bạn cần tạo một dự án cụ thể bên trong giải pháp. Bạn có thể chọn các định dạng khác nhau, chúng tôi chọn phiên bản xUnit. Để chạy chúng, có một phần được đặt tên thích hợp là “KIỂM TRA” trên thanh menu trong Visual Studio hoặc lệnh

antlr4 -Dlanguage=JavaScript Chat.g4
287 trên dòng lệnh

antlr4 -Dlanguage=JavaScript Chat.g4
0

Chức năng kiểm tra đầu tiên tương tự như chức năng chúng ta đã thấy; . Ở dòng 11 và 13, bạn có thể ngạc nhiên khi thấy loại mã thông báo kỳ lạ đó, điều này xảy ra vì chúng tôi không tạo mã thông báo cho biểu tượng '^' một cách rõ ràng nên một mã được tạo tự động cho chúng tôi. Nếu bạn cần, bạn có thể xem tất cả các mã thông báo bằng cách xem *. tệp mã thông báo được tạo bởi ANTLR

Ở dòng 25, chúng ta truy cập nút kiểm tra và nhận kết quả mà chúng ta kiểm tra ở dòng 27. Tất cả đều rất đơn giản bởi vì khách truy cập của chúng tôi rất đơn giản. While unit testing should always be easy and made up of small parts it really cannot be easier than this

Điều duy nhất cần chú ý là liên quan đến định dạng của số; . Ở đó, chúng tôi cần đảm bảo rằng định dạng chính xác được chọn, vì các quốc gia khác nhau sử dụng các ký hiệu khác nhau làm dấu thập phân

Có một số điều phụ thuộc vào bối cảnh văn hóa

If your computer was already set to the American English Culture this would not be necessary, but to guarantee the correct testing results for everybody, we have to specify it. Keep that in mind if you are testing things that are culture-dependent. chẳng hạn như nhóm các chữ số, nhiệt độ, v.v.

Trên dòng 44-46, bạn thấy rằng khi chúng tôi kiểm tra chức năng sai, trình phân tích cú pháp thực sự hoạt động. Đó là bởi vì thực sự

antlr4 -Dlanguage=JavaScript Chat.g4
288 có giá trị về mặt cú pháp như một tên hàm, nhưng nó không đúng về mặt ngữ nghĩa. Hàm
antlr4 -Dlanguage=JavaScript Chat.g4
288 không tồn tại, vì vậy chương trình của chúng tôi không biết phải làm gì với nó. So when we visit it we get 0 as a result. Như bạn nhớ lại đây là sự lựa chọn của chúng tôi. vì chúng tôi khởi tạo kết quả thành 0 và chúng tôi không có trường hợp
antlr4 -Dlanguage=JavaScript Chat.g4
290 trong
antlr4 -Dlanguage=JavaScript Chat.g4
291 Vì vậy, nếu không có chức năng nào thì kết quả vẫn là 0. Một giải pháp thay thế khả thi có thể là ném một ngoại lệ

Final Remarks

Trong phần này, chúng tôi thấy các mẹo và thủ thuật không bao giờ xuất hiện trong ví dụ của chúng tôi, nhưng có thể hữu ích trong các chương trình của bạn. Chúng tôi đề xuất nhiều tài nguyên hơn mà bạn có thể thấy hữu ích nếu bạn muốn biết thêm về ANTLR, cả thực hành và lý thuyết hoặc bạn cần giải quyết các vấn đề phức tạp nhất

33. Các mẹo và thủ thuật

Thỉnh thoảng hãy xem một vài thủ thuật có thể hữu ích. Những thứ này không bao giờ cần thiết trong các ví dụ của chúng tôi, nhưng chúng khá hữu ích trong các tình huống khác

Quy tắc Catchall

Đầu tiên là quy tắc BẤT KỲ từ vựng nào. Đây chỉ đơn giản là một quy tắc trong định dạng sau

antlr4 -Dlanguage=JavaScript Chat.g4
1

This is a catchall rule that should be put at the end of your grammar. Nó khớp với bất kỳ ký tự nào không tìm thấy vị trí của nó trong quá trình phân tích cú pháp. So creating this rule can help you during development, when your grammar has still many holes that could cause distracting error messages. Nó thậm chí còn hữu ích trong quá trình sản xuất, khi nó hoạt động như một con chim hoàng yến trong hầm mỏ. Nếu nó xuất hiện trong chương trình của bạn, bạn biết rằng có gì đó không ổn

Kênh truyền hình

Cũng có một cái gì đó mà chúng ta đã không nói về. kênh truyền hình. Trường hợp sử dụng của họ thường là xử lý bình luận. Bạn không thực sự muốn kiểm tra các bình luận bên trong mỗi câu nói hoặc cách diễn đạt của mình, vì vậy bạn thường vứt chúng đi với

antlr4 -Dlanguage=JavaScript Chat.g4
292. Nhưng có một số trường hợp bạn có thể muốn giữ lại chúng, chẳng hạn nếu bạn đang dịch một chương trình sang ngôn ngữ khác. Khi điều này xảy ra, bạn sử dụng các kênh. Hiện đã có một tên gọi là
antlr4 -Dlanguage=JavaScript Chat.g4
293 mà bạn có thể sử dụng, nhưng bạn có thể khai báo thêm chúng ở đầu ngữ pháp từ vựng của mình

antlr4 -Dlanguage=JavaScript Chat.g4
2

Nhãn phần tử quy tắc

Có một cách sử dụng nhãn khác ngoài việc phân biệt giữa các trường hợp khác nhau của cùng một quy tắc. Chúng có thể được sử dụng để đặt tên cụ thể cho quy tắc chung hoặc các phần của quy tắc. Định dạng là

antlr4 -Dlanguage=JavaScript Chat.g4
294, được sử dụng bên trong một quy tắc khác

antlr4 -Dlanguage=JavaScript Chat.g4
3

Bằng cách này, trái và phải sẽ trở thành các trường trong các nút

antlr4 -Dlanguage=JavaScript Chat.g4
295. Và thay vì sử dụng
antlr4 -Dlanguage=JavaScript Chat.g4
296, bạn có thể tham chiếu đến cùng một thực thể bằng cách sử dụng
antlr4 -Dlanguage=JavaScript Chat.g4
297

Mã thông báo có vấn đề

Trong nhiều ngôn ngữ thực, một số ký hiệu được sử dụng lại theo những cách khác nhau, điều này trong một số trường hợp có thể dẫn đến sự mơ hồ. Một ví dụ về vấn đề phổ biến là dấu ngoặc nhọn, được sử dụng cho cả biểu thức dịch chuyển bit và để phân định các loại được tham số hóa

antlr4 -Dlanguage=JavaScript Chat.g4
4

Cách tự nhiên để xác định mã thông báo toán tử bitshift là dưới dạng một dấu ngoặc nhọn kép,

antlr4 -Dlanguage=JavaScript Chat.g4
298. Nhưng điều này có thể dẫn đến nhầm lẫn giữa định nghĩa được tham số hóa lồng nhau với toán tử dịch chuyển bit, chẳng hạn như trong ví dụ thứ hai hiển thị ở đây. Mặc dù cách đơn giản để giải quyết vấn đề là sử dụng các vị từ ngữ nghĩa, nhưng quá nhiều vị từ ngữ nghĩa sẽ làm chậm giai đoạn phân tích cú pháp. Giải pháp là tránh xác định mã thông báo toán tử bitshift và thay vào đó sử dụng dấu ngoặc nhọn hai lần trong quy tắc trình phân tích cú pháp để bản thân trình phân tích cú pháp có thể chọn ứng cử viên tốt nhất cho mọi trường hợp

antlr4 -Dlanguage=JavaScript Chat.g4
5

34. kết luận

Sử dụng ANTLR như một chuyên gia

Một khóa học video hoàn chỉnh về phân tích cú pháp và ANTLR, hướng dẫn bạn cách xây dựng trình phân tích cú pháp cho mọi thứ, từ ngôn ngữ lập trình đến định dạng dữ liệu

Bây giờ, có sẵn dưới dạng Phiên bản II cải tiến

Show Me the Course

Hôm nay chúng ta đã học được rất nhiều

  • từ vựng và trình phân tích cú pháp là gì
  • cách tạo quy tắc từ vựng và trình phân tích cú pháp
  • cách sử dụng ANTLR để tạo trình phân tích cú pháp trong Java, C#, Python và JavaScript
  • the fundamental kinds of problems you will encounter parsing and how to solve them
  • làm thế nào để hiểu lỗi
  • cách kiểm tra trình phân tích cú pháp của bạn

Đó là tất cả những gì bạn cần biết để tự mình sử dụng ANTLR. And I mean literally, you may want to know more, but now you have solid basis to explore on your own

Where to look if you need more information about ANTLR

  • Trên chính trang web này có toàn bộ danh mục dành riêng cho ANTLR
  • Trang web ANTLR chính thức là điểm khởi đầu tốt để biết trạng thái chung của dự án, các công cụ phát triển chuyên biệt và dự án liên quan, như StringTemplate
  • Tài liệu ANTLR trên GitHub;
  • The ANTLR API; it’s related to the Java version, so there might be some differences in other languages, but it’s the best place where to settle your doubts about the inner workings of this tool
  • For the very interested in the science behind ANTLR4, there is an academic paper. Phân tích cú pháp LL[*] thích ứng. The Power of Dynamic Analysis
  • Tài liệu tham khảo ANTLR 4 dứt khoát, của chính người đàn ông, Terence Parr, người tạo ra ANTLR. Tài nguyên bạn cần nếu bạn muốn biết mọi thứ về ANTLR và rất nhiều về ngôn ngữ phân tích cú pháp nói chung

Ngoài ra cuốn sách là nơi duy nhất bạn có thể tìm và trả lời những câu hỏi như thế này

ANTLR v4 là kết quả của một chặng đường vòng nhỏ [hai mươi lăm năm] mà tôi đã tốt nghiệp
trường học. Tôi đoán tôi sẽ phải thay đổi phương châm của mình một chút.

Why program by hand in five days what you can spend twenty-five years of your
life automating?

Thay vào đó, nếu bạn quyết định rằng bạn có thể sử dụng một số trợ giúp với các dự án của mình liên quan đến ANTLR, thì bạn cũng có thể sử dụng Dịch vụ tư vấn ANTLR của chúng tôi

Chúng tôi xin cảm ơn Bernard Kaiflin đã sửa đổi tài liệu và giúp chúng tôi cải thiện nó

We would like to thank. Brasilio Castilho, Andy Nicholas, grz0, lo lắng vì đã phát hiện ra lỗi và lỗi đánh máy trong bài viết

Chúng tôi đã làm việc khá chăm chỉ để xây dựng hướng dẫn lớn nhất về ANTLR. siêu hướng dẫn. Một bài viết trên 14. 000 từ dài, hoặc hơn 70 trang, để cố gắng trả lời tất cả các câu hỏi của bạn về ANTLR. Thiếu một cái gì đó?

Chủ Đề