실수로 멋진 HTML 전처리기를 작성한 방법

프로그래머로서 나에게 컴파일러는 항상 운영 체제를 만드는 것만으로도 벅찬 백만 줄의 블랙 박스처럼 보였습니다. 하지만 어려운 도전이 최고의 도전이기에 얼마전 스스로 도전해 보기로 했습니다.

확인.

컴파일러를 작성하려면 세 가지 주요 부분이 있습니다. Lexer, Parser 및 코드 생성기. Java 및 C#을 비롯한 다양한 언어로 이 프로젝트를 시작했지만 성공적인 구현은 현재 JavaScript로 이루어지고 있습니다.

1) 렉싱



Lexing 또는 Lexical Analysis 프로세스는 이 프로세스의 나머지 부분에 비해 실제로 매우 간단합니다. 다음 코드를 고려하십시오.

const hello = "Hello, " + "World!";
const sum = 4 + 5;


코드 조각을 렉싱할 때 전체 소스를 살펴보고 문자열을 토큰 모음으로 변환해야 합니다. 토큰은 소스 코드의 작은 조각에 대한 정보를 저장하는 간단한 구조입니다. 내가 작성한 렉서에는 Keyword , Word , StringSymbol 의 네 가지 주요 토큰 유형을 사용합니다. 따라서 위의 코드는 렉싱 후 다음과 같이 보일 수 있습니다.

Keyword<"const">
Word<"hello">
Symbol<"=">
String<"Hello, ">
Symbol<"+">
String<"World">
Symbol<";">
Keyword<"const">
Word<"sum">
Symbol<"=">
Word<"4">
Symbol<"+">
Word<"5">
Symbol<";">


여기까지 했다면 Awesome!

내 프로젝트인 Mantle은 mantle.lexer.Lexer라는 확장할 수 있는 추상 클래스를 통해 이 슈퍼*를 수행하도록 합니다. 키워드, 기호 및 문자열 구분 기호 목록을 정의하고 주석을 허용할지 여부를 지정하고 문자를 단어에 사용할 수 있는지 정의하는 함수를 전달하기만 하면 됩니다. 그런 다음 위의 목록을 만드는 것은 Lexer.parse()를 호출하는 것만큼 쉬워지지만 계속 진행하면 직접 parse()를 호출하지 않을 것입니다.

맨틀에 대한 자세한 내용은 https://github.com/Nektro/mantle.js에서 확인할 수 있습니다.

2) 파싱



이것은 어려운 부분입니다.

구문 분석을 위해서는 토큰 목록을 단일 노드로 압축할 수 있는 토큰 패턴을 파악해야 합니다. 이것은 제대로 되기까지 많은 시행착오를 겪었고, 이 프로젝트가 그렇게 오래 걸린 주된 이유입니다.

예를 들어 위에 있는 코드의 경우 다음 규칙을 정의할 수 있습니다.

Add <= String + String
Add <= Integer + Integer
AssignmentConst <= const Word = Add
StatementList <= Add Add


더 복잡한 규칙이 있을수록 내가 곧 발견한 더 복잡한 언어가 있습니다.
mantle.parser.Parser에 대한 JSON 예제는 https://github.com/Nektro/mantle.js/blob/master/langs/mantle-json.js에서 찾을 수 있습니다.

3) 코드 생성



이는 추상 구문 트리라고도 하는 최종 압축 노드를 통과하고 새 출력을 얻을 때까지 모두 처리하는 프로세스입니다toString().

Note:
Optimization of higher-level languages requires a lot more work than calling toString(), but is way above my scope



4) Corgi - 새로운 HTML 전처리기



이 시점에서 나는 황홀했다. JSON 파서를 성공적으로 만들었습니다. 하지만 조금 더 복잡하게 만들고 싶었습니다. 그래서 HTML로 옮겼습니다. 그러나 문제는 HTML이 잘 구성되어 있지 않다는 것입니다. 그래서 Mantle이 파싱하기 좀 더 쉬운 버전을 만들어야겠다고 생각했습니다. 그리고 그것이 Corgi에게 온 방법입니다.

Corgi 구문은 Pug에서 영감을 받았지만 탭 기반이 아니므로 이론적으로 파일을 한 줄로 압축할 수 있습니다. Pug에서 코스메틱 HTML 태그를 사용하여 만든 탭 구조를 강제로 적용하는 것이 정말 어색하기 때문에 이 기능이 마음에 들었습니다. 따라서 Corgi는 HTML을 구조와 스타일에 적합하게 만듭니다.

Corgi 문서의 예는 다음과 같습니다.

doctype html
html(
    head(
        title("Corgi Example")
        meta[charset="UTF-8"]
        meta[name="viewport",content="width=device-width,initial-scale=1"]
    )
    body(
        h1("Corgi Example")
        p("This is an example HTML document written in "a[href="https://github.com/corgi-lang/corgi"]("Corgi")".")
        p("Follow Nektro on Twitter @Nektro")
    )
)


폐쇄



컴파일러를 만드는 것은 어렵지만 확실히 즐거웠습니다. 이것이 컴파일러를 이해하는 데 도움이 되기를 바랍니다.

그리고 이제 HTML Proprocessor도 가지고 있습니다. 가능한 한 많은 프로젝트에서 사용할 것입니다.

자원:
  • https://github.com/Nektro/mantle.js
  • https://github.com/corgi-lang/corgi

  • 나를 따르라:
  • https://dev.nektro.net/

  • 좋은 웹페이지 즐겨찾기