ANTLR 및 C#을 사용하여 외부 DSL 만들기

20253 단어 csharpdslantlr


이 게시물에서는 ANTLR을 사용하여 C#에서 간단한 DSL을 작성하는 방법을 보여줍니다.

DSL이란 무엇입니까?



A domain-specific language is a computer language specialized to a particular application domain. This is in contrast to a general-purpose language, which is broadly applicable across domains.



ANTLR이란 무엇입니까?



In computer-based language recognition, ANTLR, or ANother Tool for Language Recognition, is a parser generator that uses LL for parsing. ANTLR is the successor to the Purdue Compiler Construction Tool Set, first developed in 1989, and is under active development



우리는 무엇을 만들 것입니까?



이 기사에서는 문장을 직렬화하고 데이터베이스에 저장할 수 있는 C#POCO 클래스로 변환하는 DSL을 만드는 방법을 보여줍니다.
book a hotel room for Santosh Singh and 3 guests on 23-SEP-2013 00:12

ANLTR을 사용하여 위 문장을 C#POCO 클래스로 구문 분석할 예정이며 출력은 아래와 같습니다.
{"Time":"2013-09-23T00:12:00","Person":{"FirstName":"Santosh","LastName":"Singh","NumberOfGuests":3}}

전제 조건


  • 앤트러
  • ANTLR 확장이 있는 Visual Studio Code
    작성하기 전에 문법은 먼저 DSL
  • 에서 채우려는 클래스POCO를 생성합니다.

    Booking.cs


    using System;
    
    public partial class Booking
    {
        public DateTime Time { get; set; }
        public Person Person { get; set; }
    }
    

    Person.cs


    public class Person{
    
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int NumberOfGuests { get; set; }
        public override string ToString()
        {
            return $"{FirstName}-{LastName}-{NumberOfGuests}";
        }
    }
    

    ANTLR 문법



    위의 명령문에 대한 문법 파일을 작성하는 첫 번째 작업입니다. 아래는 DSL의 문법입니다. ANTLR 문법은 두 부분으로 구성됩니다.
  • 파서
  • 렉서

  • 우리의 문법 파서는
  • 예약
  • 시간
  • 사람

  • 예약은 파싱의 시작입니다.

    Here I am using Actions and Attribute instead of Visitor. Actions are blocks of text written in the target language and enclosed in curly braces. The recognizer triggers them according to their locations within the grammar. For example, the following rule emits a Booking model after the parser has seen a valid declaration:


    booking
        returns[Booking b]:
        'book' 'a' 'hotel' 'room' 'for' person 'guests' 'on' time {
          $b=new Booking();
          $b.Time=$time.t;
          $b.Person=$person.p;
    
        };
    

    Grammar


    grammar Booking;
    
    @lexer::header {
        using System;
    }
    
    booking
        returns[Booking b]:
        'book' 'a' 'hotel' 'room' 'for' person 'guests' 'on' time {
          $b=new Booking();
          $b.Time=$time.t;
          $b.Person=$person.p;
    
        };
    time
        returns[DateTime t]:
        d = datetime {
        Console.WriteLine($d.text);
        $t=DateTime.Parse($d.text);
    
    };
    person
        returns[Person p]:
        f = firstName l = lastName 'and' n = numberOfGuests {
    
           $p=new Person();
           $p.FirstName=$f.text;
           $p.LastName=$l.text;
           $p.NumberOfGuests=int.Parse($n.text);
    
       };
    
    firstName: STRING;
    lastName: STRING;
    numberOfGuests: NUMBER;
    datetime:
        NUMBER NUMBER SEPARATOR MONTH SEPARATOR YEAR NUMBER NUMBER COLON NUMBER NUMBER;
    YEAR: NUMBER NUMBER NUMBER NUMBER;
    
    NUMBER: [0-9];
    MONTH:
        JAN
        | FEB
        | MAR
        | APR
        | MAY
        | JUN
        | JUL
        | AUG
        | SEP
        | OCT
        | NOV
        | DEC;
    
    STRING: [a-zA-Z][a-zA-Z]+;
    JAN: [Jj][Aa][Nn];
    FEB: [Ff][Ee][Bb];
    MAR: [Mm][Aa][Rr];
    APR: [Aa][Pp][Rr];
    MAY: [Mm][Aa][Yy];
    JUN: [Jj][Uu][Nn];
    JUL: [Jj][Uu][Ll];
    AUG: [Aa][Uu][Gg];
    SEP: [Ss][Ee][Pp];
    OCT: [Oo][Cc][Tt];
    NOV: [Nn][Oo][Vv];
    DEC: [Dd][Ee][Cc];
    SEPARATOR: '-';
    COLON: ':';
    
    WS: (' ' | '\r' | '\n' | '\t') -> channel(HIDDEN);
    
    

    Parse Tree





    이제 기본 메서드 내에서 다음 코드를 작성합니다.

    Assuming you have generated the parser and lexer code using ANTLR.



    Program.cs


    using System;
    using Antlr4.Runtime;
    using Newtonsoft.Json;
    
    namespace antlraction
    {
        class Program
        {
            static void Main(string[] args)
            {
                var input = "book a hotel room  for Santosh Singh and 3 guests on 23-SEP-2013 00:12";
    
                var charStream = new AntlrInputStream(input);
                var lexer = new BookingLexer(charStream);
                var tokens = new CommonTokenStream(lexer);
                var parser = new BookingParser(tokens);
    
                var t = parser.booking().b;
                System.Console.WriteLine(JsonConvert.SerializeObject(t));
            }
        }
    }
    


    {"Time":"2013-09-23T00:12:00","Person":{"FirstName":"Santosh","LastName":"Singh","NumberOfGuests":3}}
    


    My Blog
    ANTLR CSV
    Create Compiler In C# Using ANTLR-Crash Course

    좋은 웹페이지 즐겨찾기