tarballize legacies

This commit is contained in:
Tan, Kian-ting 2024-03-29 23:33:57 +08:00
parent 83f67728ff
commit 4ab5276bdc
3440 changed files with 417 additions and 339256 deletions

View file

@ -1 +0,0 @@
const { Parser } = require('jison');

View file

@ -1,321 +0,0 @@
# Ch1 定義抽象語法樹和語法
## 抽象語法樹
C語言、Python語言就算有許多的關鍵字、操作符、符號或是常數變數在編譯器分析語法以後最後會轉成編譯器可以操作的樹結構然後再轉成我們想要的另一個語言的樹最後輸出另一個語言的程式碼。
但是什麼叫做抽象語法樹呢?我們先從一點句法知識來談。
學過中學國文文法的課程,會背一堆類似「主詞+動詞+受詞」、「主詞+(有/無)+受詞」的結構。可以換個說法,是句子=「主詞+動詞+受詞」或是「主詞+(有/無)+賓詞」的形式。我們將「=」寫成「::=」,「/」(或是)寫成「|」,「動詞」擴充變成「動詞片語」,就變成:
```
句子 ::= (主詞 動詞片語 受詞) | (主詞 (有 | 無) 受詞)...
```
為了易讀所以寫成:
```
句子 ::= 主詞 動詞片語 受詞
| 主詞 (有 | 無) 受詞
| ...
```
用這種形式表示的語言句法叫做「BNF文法」。這種句法看起來很語言學但是我們想受詞和主詞可以為名詞、專有名詞或是「形容詞+名詞」;動詞片語可以為動詞或是「副詞+動詞」。因此這樣之規則,就可以生成許多句子,比如「我有筆」、「張三養貓」、「小芳慢慢移動檯燈」等等的句子。然後句子可以用上述規則,分析成語法的樹狀結構,如下圖把「我曾旅居新竹」寫成語法樹。
<figure markdown>
![「我曾旅居新竹」的語法樹](syntaxtree.svg "")
<figcaption>「我曾旅居新竹」的語法樹</figcaption>
</figure>
同理,程式語言通常也有更嚴謹的這樣生成文法,可以用幾個簡單規則生出繁多的程式碼,而且合乎語法規定。這種生成文法也可檢查輸入的程式碼有沒有符合句法的規定。而這種語法生成的程式碼,去掉不需要的逗號等等符號,當然也可以做成語法樹,就是抽象語法樹 (abstract syntax tree, AST),如下圖所示。
<figure markdown>
![「(2+2) == 4」的語法樹。注意括號已經刪除。](syntaxtree2.svg "")
<figcaption>「(2+2) == 4」的語法樹。注意括號已經刪除。</figcaption>
</figure>
而上文的抽象語法樹可以是我們把程式經過編譯器分析之後用「樹」儲存的資料結構。而樹形結構我們可以使用Lisp語言的S表達式(S-expressiom; S-exp)來表示,本文採用這樣的表示方法。所以上文的`(2+2)==4`即`(== (+ 2 2) 4)``let baz = foo("bar")`若是把foo("bar")這種函數套用(apply)寫成`(APPLY foo "bar")`則其S-exp語法樹可寫為`(let baz(APPLY foo "bar"))`。
## 決定語法
那我們要如何制定這個語言的語法這樣我們才能夠寫出符合這個語法的函數然後再用tokenizer和parser轉成AST樹。
函數可以用`ID arg1 arg2`這種方式來表示,其中`arg_x`是引數,`ID`是識別子identifier可以把它想成變函數的名字
變數可以是`ID``arg_n`可以是`ID`或常數(量)。
常數(量)的表示法可以是下列任一:
- 浮點數如0.0, 36.8BNF風格的表達法為`[0-9]+ '.' [0-9]+`。`'c'`指c這個文字`+`表示前面的重複1次以上`[0-9]`表示數字0到9。
- 整數如22、0`[0-9]+`
- 字串:`'"' (不是「"」的任一字元|('\' '"')) '"'``.`表示任何一個字元)
然而我們還是需要綁定變數`let int x = var in body`(在`body`裡面,`x`指代`var`、改變變數值、lambda`fn (int x) (int y) -> + x y`(採用前綴表示法,`+`在前。另外為了要區別要在PDF印上去的一般字元在這個檔案的常數、變數、函數、關鍵字等前後需要加@表示但是函數、lambda裡面的變數不用。比如`@foo a b@`、`@let int x = 3 in toString (+ x 2)@`、`@"IAmAString"@`、`@2.2@`、`@3@`後三者應該很少用到可是若需在PDF印`@`時怎辦?那就用`\@`。比如`foo\@example.com`。
所以我們可以定義以下的BNF風文法
```
FLO = \d+[.]\d+ // 浮點數
INT = \d+ // 整數
AT = '@' // @
ID = [_\w][_\d\w]* // 識別子
R_ARR = [-][>] // 右箭頭 ->
SEMICOLON = ";"
// 括號
L_PAR = '('
R_PAR = ')'
ASSIGN = '='
OP = [+-*/] | [=][=] | [!<>][=] // 運算子
HASH = [#]
COM = #[^#]*# # 註解 #
SPACE = \s+ # 空白字元
B_SLASH = [\\] // 反斜線
STR = \"([^"]|[\\\"])*\"
LIT_STR = ([^\\]?) // 文字模式的不貪婪模式
```
程式語法定義如下:
```BNF
Main ::= (LitStr | Prog)* ; 主體
LitStr ::= ( not(AT) | B_SLASH AT | B_SLATH HASH)+ ;基本文字模式
Prog ::= '@' BODY '@' ;程式模式
BODY ::= LET | EXPR | DEFINE
DEFINE ::= "define" TYPE VAR ASSIGN BODY SEMICOLON ; 全局定義
LET ::= "let" TYPE VAR ASSIGN "in" BODY ; 局域定義
EXPR ::= APPLY | FN | LIST | CONST | VAR | "(" EXPR ")"
APPLY ::= OP EXPR+ | EXPR EXPR+
FN ::= "fn" ARGS R_ARR BODY
ARGS ::= ARG | ARG ARGS
* ARG ::= "(" TYPE VAR ")"
* CONST ::= FLO | STR | INT
* VAR ::= ID
* TYPE ::= ID
LIST ::= [LIST_INNER]
LIST_INNER ::= EXPR | EXPR SEMICOLON LIST_INNER
```
## 用ts-parsec和regexp進行tokenize
Parser combinator分析器組合子是一種利用高階函數來簡化分析器撰寫的辦法。這講到頭來會涉及「遞歸下降分析」以及其他編譯理論的東西但太難了聽說可以讀編譯理論的「龍書我們可以製作一個小的tokenizer。但是因為自己寫parser combinator太累了所以我們就用nom來幫我們代勞。
」)。講一個簡單的案例吧:
假設我們想要將字串的開頭match 0~9 之中的其中一個我們可以寫一個函數match0to9如下
```
function match0to9(string){
if (string[0] in 0,1,..,9){
let rest = string[1:];
let matched = string[0];
return {type: "OK", rest : rest, matched : matched};
}
else{
return {type : "Nothing"};
}
}
```
假設我們要將字串`s`的前3個字的match 0~9呢如果會高階函數的話引入一個`then`函數,然後把`match0to9`傳進去,這樣寫起來比較不會太糾結,比較好維護:
```
function thenDo(input, fun){
if (input.type != "Nothing"{
middle = fun(input.rest);
if (middle.type != "Nothing"){
// add the matched character of input to the head of the result
middle.matched = input.matched + middle.matched
return middle;
}else{
return middle; // return nothing
}
}else{
input; // return nothing
}
}
// "s" should be wrapped in a object
let sWrapped = {type : "OK", rest : s, matched : ""};
// match0~9 3 times
thenDo(thenDo(thenDo(sWrapped, match0to9), match0to9), match0to9)
```
我們可以製作一個小的tokenizer。但是因為自己寫parser combinator太累了所以我們就用`ts-parsec`來幫我們代勞。
安裝`ts-parsec`可以用:`npm install -g typescript-parsec`。底下的程式使用的函數的詳細說明可以參考[官方文件](https://github.com/microsoft/ts-parsec/blob/master/doc/ParserCombinators.md)。
因為這個軟體在 tokenize 的時候使用regex所以我們就用這個東西來處理。
我們編輯Node.js的進入點程式假設為src/index.js`底下為定義tokenizer的型別和regex pattern
```typescript
```
### 常數parsing
增加儲存實際變數值的`ASTNode`型別
```typescript
// add "actualValue" in the parsed Token
export interface ASTNode extends parsec.Token<TokenKind>{
// number is for float number;
//it's optional. since keyword has no value
actualValue? : bigint | number | string;
}
```
增加處理常數的parser。`...value`有擴充object的意思。
```typescript
function applyInteger(value: parsec.Token<TokenKind.Int>): ASTNode {
// extend value to ASTNode
const newNode : ASTNode = {
actualValue : BigInt(value.text) ,
...value};
return newNode;
}
function applyFloat(value: parsec.Token<TokenKind.Flo>): ASTNode {
// extend value to ASTNode
const newNode : ASTNode = {
actualValue : parseFloat(value.text) ,
...value};
return newNode;
}
function applyString(value: parsec.Token<TokenKind.Str>): ASTNode {
// extend value to ASTNode
const newNode : ASTNode = {
// get only text[1,2,...,the second last char]
actualValue : value.text.slice(1,value.text.length-1).replace(/\\\"/g, "\"") ,
...value};
return newNode;
}
```
製作`CONST`這個parser然後再加上rule
```typescript
const CONST = parsec.rule<TokenKind, ASTNode>();
/*
CONST ::= INT | FLOAT | STRING
*/
CONST.setPattern(
parsec.alt(
parsec.apply(parsec.tok(TokenKind.Int), applyInteger),
parsec.apply(parsec.tok(TokenKind.Flo), applyFloat),
parsec.apply(parsec.tok(TokenKind.Str), applyString),
)
);
```
最後包起來進行測試:
```typescript
function mainParse(inputStr : string){
return parsec.expectSingleResult(parsec.expectEOF(
CONST.parse(tokenizer.parse(inputStr))));
}
// test
function main(){
// bigint has suffix `n`
assert.strictEqual(mainParse('123455667').actualValue, 123455667n);
assert.strictEqual(mainParse('000').actualValue, 0n);
assert.strictEqual(mainParse('1.22').actualValue, 1.22);
assert.strictEqual(mainParse('0.0').actualValue, 0.0);
assert.strictEqual(mainParse(`""`).actualValue, "");
assert.strictEqual(mainParse(`"the little town"`).actualValue, `the little town`);
assert.strictEqual(mainParse(`"\\\"Alice\\\""`).actualValue, `"Alice"`);
};
```
### 表達式
定義`AST型別`
```type AST = AST[] | ASTNode;
```
## 平面操作
### 基本函數與直譯器
我們藉由以上的概念可以定義一個將文字、線條等形狀排列到2D平面的語法畢竟不論輸出PDF、SVG等等粗略而言就是一種2D平面安放文字的語言。另外PDF的格式相當晦澀就算_PDF Explained_的PDF教學也還是要輔助使用其他的工具沒辦法看了就自己手刻PDF所以還是用`printpdf`來教學吧。
現在我們初始化一個專案目錄然後將需要的S-exp函式庫和pdf函數庫指定為相依函式庫
```
cargo init;
cargo add rsexp printpdf;
```
我們可以定義一些表達式包含函數、資料結構S-exp形式的說明如下。`'()`表示空列表(empty list),因為都要表達是函數的引用,所有的函數寫成形式`(Func "函數名稱" (引數1 引數2 ....))`。Float指64位元浮點數
```
(px Float) ; px表達pixel單位儲存浮點數
(pt Float) ; pt表達point單位儲存浮點數
(style (str pt)) ; 文字樣式。String表示字型的路徑[fontPath]Float表示字型大小(in Pt) (fontSize)
(str String) ; 儲存字串
(func "createPDF" '()) ;新增PDF
(func "createPage" '()) ;新增頁面
(func "writePdf" '(str)) ;寫入PDF頁面String是PATH
(func "putchar" '(str style x y)) ; x 軸向右y 軸向下str 表示字元(char)style 表示文字樣式
```
`main.rs`先引用函式庫:
`use printpdf::*;`
其中 `px`、`pt`是單位,所以可以在`main.rs`這樣定義:
```
enum Measure{
Pt(f64),
Px(f64)
}
```
最後一次定義expression
```
enum Expr{
Mea(Measure), // wrapper for measure
Str(&str),
Style{font_path : Measure, size : Measure},
Func(&str, Vec<Expr>),
Void // return nothing
}
```
然後我們可以這樣定義一個處理輸入輸出的interpreter於`interp`,並修改`main.rs`如下,縱使我們準時:
```
fn interp(exp : Expr)->(){
// the function will be extended.
match exp {
Expr::Mea(Measure::Pt(x)) => println!("{:?} pt", x),
Expr::Mea(Measure::Px(x)) => println!("{:?} px", x),
_ => println!("not found expression"),
};
}
// exexute interpreter
fn main() {
interp(Expr::Mea(Measure::Pt(2.2)));
interp(Expr::Flo(2.2));
}
```

View file

@ -1,26 +0,0 @@
# Another Typesetter - 另一個排版器
## 摘要
本文是講一個排版器的雛形如何製作的考察使用Rust語言。
###序言
以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。
但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的 _Digital Typography_,想要瞭解斷行演算法,結果粗估五、六十頁,所以幾乎沒有讀。
另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy G. Siek所著作之 *Essential of Complication: An Incremental Approach in Racket*編譯之要素Racket語言的遞增的方法。我想到既然編譯器這種複雜的軟體可以一層一層的用pass來遞增功能就像水彩從背景、大物體一直由少漸多的完成。而排版軟體也是把使用者輸入的排版之領域特定語言(DSL)轉換成文字、圖形和二維座標對應關係最後匯出成PDF或SVG等等的編譯器若是能夠用層層遞增的方法來完成相信也能夠避免結構的複雜化導致錯誤容易發生的挫折。
然而排版語言不只是輸入文字轉圖形而已,更重要的是還要有因應美觀的自動斷行(justification)和斷字(hyphenation)等等的演算法、還有PDF的基本知識、字型函式庫的取用、排版要求多欄、甚至還牽涉到語言特有的特性比如東亞全形文字漢字、諺文、日文假名、注音符號和非全形文字中間要加空白以及從左寫到右的文字希伯來字母和阿拉伯字母等的排版方法不一而足。
為了簡化起見且目標讀者是臺灣的受眾本書僅涉及到ASCII英文字母——頂多加些一些附加符號(diacritics)和漢字的排版。其他的功能希望讀者可以漸次由少漸多的附加。另外這邊會使用到一些LISP的表達式來表達抽象語法樹若是不懂的話可以看一點教 Lisp或是Scheme的書如SICP。另外這本書不是編譯原理和描述PDF規格的書不涉獵底層的知識有需要的可以參考相關領域的書。
### 先備知識
這不是教一位入門使用者如從零知識撰寫排版軟體的書讀者應該有知道如何使用靜態型別語言的經驗比如一點C、或是Rust等等還要會些正規表達式regex。另外抽象語法樹為求方便使用LISP撰寫所以需要會LISP和Scheme的知識知名教科書SICP的開頭可以讀一讀
這本書也不教編譯理論和tokenizing、parsing、狀態機等等的頂多只會帶到一些很基礎的知識有需要的請另外再讀。所以使用者需要會有使用正規表達式(regex)的能力。
操作環境使用Linux作業系統和TypeScript程式語言Nodejs框架。需要安裝fontconfig等套件。
- [定義抽象語法樹和語法](./defineASTandGrammar)

View file

@ -1,17 +0,0 @@
# Welcome to MkDocs
For full documentation visit [mkdocs.org](https://www.mkdocs.org).
## Commands
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.
## Project layout
mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.

Binary file not shown.

View file

@ -1,193 +0,0 @@
#set heading(numbering: "1.1.1.1.")
#show raw: set text(font: "Noto Sans Mono CJK TC")
#set page("a5")
#set text(
font: ("New Computer Modern", "AR PL UMing TW"),
size: 11pt
)
#show heading: it => [
#set text(font: "Noto Serif CJK TC",
weight: "black")
#it.body
]
#set par( justify: true,leading: 1em,
)
#align(center)[#set text(
font: ("EB Garamond 08"),
weight:"medium",
size: 20pt,
)
Clo: another typesetter]
#align(center)[#box([#set text(size: 15pt,
font: "Noto Serif CJK TC",
weight:"medium")
一個排版器的實作心得])]
#box(
height:0.5em
)
#align(center)[#box([#set text(size: 11pt,
font: "AR PL UMing TW",
weight:"light")
陳建町])]
#pagebreak()
#set page(
margin: (top: 60pt, bottom: 20pt),
header: locate(
loc => if (calc.odd(loc.page()) == true){
[#set align(right)
#numbering("i", loc.page())
]
} else {
[#set align(left)
#numbering("i", loc.page())]
}
));
#heading(level:2, "版權聲明",outlined:false)
(c) 2023 陳建町 (Tan, Kian-ting)
本書內容非經許可,禁止複製、分發、商業使用等違反著作權法之行為。
然書中之程式碼,採用 #link("https://opensource.org/license/mit/")[MIT許可證]授權。
#pagebreak()
#outline(
title: align(left, [目#box(width:1em)錄 #box(
height:1.5em)]),
target: heading.where(outlined: true),
)
#pagebreak()
#set page(
numbering: "i",
number-align: top+right)
#heading(numbering: none, "序言")
以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。
但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的 _Digital Typography_想要瞭解斷行演算法結果粗估五、六十頁所以幾乎沒有讀。
另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy G. Siek所著作之_Essential of Complication: An Incremental Approach in Racket_編譯之要素Racket語言的遞增的方法。我想到既然編譯器這種複雜的軟體可以一層一層的用pass來遞增功能就像水彩從背景、大物體一直由少漸多的完成。而排版軟體也是把使用者輸入的排版之領域特定語言(DSL)轉換成文字、圖形和二維座標對應關係最後匯出成PDF或SVG等等的編譯器若是能夠用層層遞增的方法來完成相信也能夠避免結構的複雜化導致錯誤容易發生的挫折。
然而排版語言不只是輸入文字轉圖形而已,更重要的是還要有因應美觀的自動斷行(justification)和斷字(hyphenation)等等的演算法、還有PDF的基本知識、字型函式庫的取用、排版要求多欄、甚至還牽涉到語言特有的特性比如東亞全形文字漢字、諺文、日文假名、注音符號和非全形文字中間要加空白以及從左寫到右的文字希伯來字母和阿拉伯字母等的排版方法不一而足。
為了簡化起見且目標讀者是臺灣的受眾本書僅涉及到ASCII英文字母——頂多加些一些附加符號(diacritics)和漢字的排版。其他的功能希望讀者可以漸次由少漸多的附加。另外這邊會使用到一些LISP的表達式來表達抽象語法樹若是不懂的話可以看一點教 Lisp或是Scheme的書如SICP。另外這本書不是編譯原理和描述PDF規格的書不涉獵底層的知識有需要的可以參考相關領域的書。
#heading(numbering: none, "致謝")
感謝Donald Knuth教授開發出這麼一套排版系統以及排版的演算法除了造福科學排版的諸多用戶外也間接鼓舞我想要研究排版軟體如何實作感謝Jeremy G.Siek老師的_Essential of Complication: An Incremental Approach in Racket_讓我獲得排版語言編譯器設計的啟發。感謝王垠讓我對編譯器相關的技術有興趣從而斷斷續續學習相關的資訊。
感謝愛爾蘭語除了讓我對語言和語言復興的知識打開新的世界以外這個軟體的名字Clo也是從這裡來的cló有「活字」的意思因為技術限制抱歉沒辦法輸入長音符號
感謝我的父母,雖然專長不是電腦資訊科技,但是要感謝他們讓我讓我有餘力能夠在中學的時候研究這種興趣,這條路才能走下去。
感謝這本書閱讀的人們,讓我知道筆者不是孤單的。
Siōng-āu Kám-siā góa ê Siōng Chú, nā-bô i ê hû-chhî kap pó-siú, chit-pún chheh iā bô-hó oân-sêng.(最後感謝上主,若無扶持保守,這本書也很難完成)
#pagebreak()
#set page(
margin: (top: 60pt, bottom: 20pt),
header: locate(
loc =>{
let chapter_query = query(selector(heading.where(level: 1)).after(loc),loc)
let section_query = query(selector(heading.where(level: 2)).after(loc),loc)
let chapter = "";
let section = "";
if chapter_query == (){chapter = ""}
else{chapter = chapter_query.at(0).body};
if section_query == (){section = ""}
else{section = section_query.at(0).body}
if (calc.odd(loc.page()) == true){
grid(
columns: (0.333333fr, 0.333333fr, 0.333333fr),
text(style: "italic")[ ],
[#set align(center)
#chapter],
[ #h(1fr) #loc.page-numbering()])
} else {
grid(
columns: (0.333333fr, 0.333333fr, 0.333333fr),
text(style: "italic")[#loc.page-numbering()],
[#set align(center)
#section],
[ ])
}}
));
#show heading: it => [
#set text(font: ("New Computer Modern", "Noto Serif CJK TC"),
weight: "black")
#counter(heading).display() #it
]
#set page(numbering: "1")
#counter(page).update(1)
#set heading(numbering: "1.1.1.1.1")
= 先備知識
這不是教一位入門使用者如從零知識撰寫排版軟體的書讀者應該有知道如何使用靜態型別語言的經驗比如一點C、或是Rust等等。另外抽象語法樹為求方便使用LISP撰寫所以需要會LISP和Scheme的知識知名教科書SICP的開頭可以讀一讀
這本書也不教編譯理論和tokenizing、parsing、狀態機等等的頂多只會帶到一些很基礎的知識有需要的請另外再讀。所以使用者需要會有使用正規表達式(regex)的能力。
== 抽象語法樹
C語言、Python語言就算有許多的關鍵字、操作符、符號或是常數變數在編譯器分析語法以後最後會轉成編譯器可以操作的樹結構然後再轉成我們想要的另一個語言的樹最後輸出另一個語言的程式碼。
但是什麼叫做抽象語法樹呢?我們先從一點句法知識來談。
學過中學國文文法的課程,會背一堆類似「主詞+動詞+受詞」、「主詞+(有/無)+受詞」的結構。可以換個說法,是句子=「主詞+動詞+受詞」或是「主詞+(有/無)+賓詞」的形式。我們將「=」寫成「::=」,「/」(或是)寫成「|」,動詞擴充變成「動詞片語」,就變成:
```
句子 ::= (主詞 動詞片語 受詞) | (主詞 (有 | 無) 受詞)...
```
用這種形式表示的語言句法叫做「BNF文法」。這種句法看起來很語言學但是我們想受詞和主詞可以為名詞、專有名詞或是「形容詞+名詞」;動詞片語可以為動詞或是「副詞+動詞」。因此這樣之規則就可以生成許多句子比如「我有筆」、「張三養貓」、「小芳慢慢移動檯燈」等等的句子。然後句子可以用上述規則分析成語法的樹狀結構如圖1把「我曾旅居新竹」寫成語法樹。
#figure(
image("syntaxtree.svg", width: 40%),
caption: [
「我曾旅居新竹」的語法樹
],
supplement: [圖],
)
同理,程式語言通常也有更嚴謹的這樣生成文法,可以用幾個簡單規則生出繁多的程式碼,而且合乎語法規定。這種生成文法也可檢查輸入的程式碼有沒有符合句法的規定。而這種語法生成的程式碼,去掉不需要的逗號等等符號,當然也可以做成語法樹,就是抽象語法樹 (abstract syntax tree, AST)如圖2所示。
#figure(
image("syntaxtree2.svg", width: 30%),
caption: [
`(2+2) == 4`的語法樹。注意括號已經刪除。
],
supplement: [圖],
)
而上文的抽象語法樹可以是我們把程式經過編譯器分析之後用「樹」儲存的資料結構。而樹形結構我們可以使用Lisp語言的S表達式(S-expressiom; S-exp)來表示,本文採用這樣的表示方法。所以上文的`(2+2)==4`即`(== (+ 2 2) 4)``let baz = foo("bar")`若是把foo("bar")這種函數套用(apply)寫成`(APPLY foo "bar")`則其S-exp語法樹可寫為`(let baz(APPLY foo "bar"))`。

View file

@ -1,24 +0,0 @@
[ Clo: another typesetter]{align="center"} [[
一個排版器的實作心得]{.box}]{align="center"} []{.box} [[
陳建町]{.box}]{align="center"}
版權聲明
\(c\) 2023 陳建町 (Tan, Kian-ting)
本書內容非經許可,禁止複製、分發、商業使用等違反著作權法之行為。
然書中之程式碼,採用
[MIT許可證](https://opensource.org/license/mit/)授權。
序言
以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。
但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的
*Digital
Typography*,想要瞭解斷行演算法,結果粗估五、六十頁,所以幾乎沒有讀。
另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy
G. Siek所著作之_Essential of Complication: An Incremental Approach in
Racket

View file

@ -1 +0,0 @@
<svg baseProfile="full" height="248px" preserveAspectRatio="xMidYMid meet" style="font-family: times, serif; font-weight: normal; font-style: normal; font-size: 16px;" version="1.1" viewBox="0,0,144.0,248.0" width="144px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">句子</text></svg><svg width="27.7778%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">主詞</text></svg><svg width="100%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">代詞 </text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px"></text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="72px" /></svg><line stroke="black" x1="50%" x2="50%" y1="19.2px" y2="56px" /></svg><line stroke="black" x1="50%" x2="13.8889%" y1="19.2px" y2="48px" /><svg width="72.2222%" x="27.7778%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">謂語</text></svg><svg width="69.2308%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">動詞</text><text text-anchor="middle" x="50%" y="32px">片語 </text></svg><svg width="44.4444%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">副詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px"></text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="22.2222%" y1="35.2px" y2="72px" /><svg width="55.5556%" x="44.4444%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">動詞 </text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">旅居</text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="72.2222%" y1="35.2px" y2="72px" /></svg><line stroke="black" x1="50%" x2="34.6154%" y1="19.2px" y2="48px" /><svg width="30.7692%" x="69.2308%" y="48px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">受詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">專有</text><text text-anchor="middle" x="50%" y="32px">名詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">新竹</text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="35.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="84.6154%" y1="19.2px" y2="56px" /></svg><line stroke="black" x1="50%" x2="63.8889%" y1="19.2px" y2="48px" /></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1 +0,0 @@
<svg baseProfile="full" height="120px" preserveAspectRatio="xMidYMid meet" style="font-family: times, serif; font-weight: normal; font-style: normal; font-size: 16px;" version="1.1" viewBox="0,0,72.0,120.0" width="72px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">==</text></svg><svg width="66.6667%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">+</text></svg><svg width="50%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">1</text></svg></svg><line stroke="black" x1="50%" x2="25%" y1="19.2px" y2="48px" /><svg width="50%" x="50%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">1</text></svg></svg><line stroke="black" x1="50%" x2="75%" y1="19.2px" y2="48px" /></svg><line stroke="black" x1="50%" x2="33.3333%" y1="19.2px" y2="48px" /><svg width="33.3333%" x="66.6667%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">2</text></svg></svg><line stroke="black" x1="50%" x2="83.3333%" y1="19.2px" y2="48px" /></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

View file

@ -1,11 +0,0 @@
site_name: Another Typesetter 另一個排版器
site_url: https://blog.kianting.info/pages/docs/anotherTypeSetter/
nav:
- Home: index.md
- Ch 1: defineASTandGrammar.md
- Ch 2: 2DManipulating.md
theme: readthedocs
markdown_extensions:
- attr_list
- md_in_html

View file

@ -1,128 +0,0 @@
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/pages/docs/anotherTypeSetter/img/favicon.ico">
<title>Another Typesetter 另一個排版器</title>
<link rel="stylesheet" href="/pages/docs/anotherTypeSetter/css/theme.css" />
<link rel="stylesheet" href="/pages/docs/anotherTypeSetter/css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
<script src="/pages/docs/anotherTypeSetter/js/jquery-2.1.1.min.js" defer></script>
<script src="/pages/docs/anotherTypeSetter/js/modernizr-2.8.3.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="/pages/docs/anotherTypeSetter/." class="icon icon-home"> Another Typesetter 另一個排版器</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="/pages/docs/anotherTypeSetter//search.html" method="get">
<input type="text" name="q" placeholder="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul>
<li class="toctree-l1"><a class="reference internal" href="/pages/docs/anotherTypeSetter/.">Home</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="/pages/docs/anotherTypeSetter/defineASTandGrammar/">Ch 1</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="" href="/pages/docs/anotherTypeSetter/2DManipulating.md">Ch 2</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="/pages/docs/anotherTypeSetter/.">Another Typesetter 另一個排版器</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/pages/docs/anotherTypeSetter/.">Docs</a> &raquo;</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<h1 id="404-page-not-found">404</h1>
<p><strong>Page not found</strong></p>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
</span>
</div>
<script>var base_url = '/pages/docs/anotherTypeSetter/';</script>
<script src="/pages/docs/anotherTypeSetter/js/theme.js" defer></script>
<script src="/pages/docs/anotherTypeSetter/search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -1,140 +0,0 @@
/*
* Wrap inline code samples otherwise they shoot of the side and
* can't be read at all.
*
* https://github.com/mkdocs/mkdocs/issues/313
* https://github.com/mkdocs/mkdocs/issues/233
* https://github.com/mkdocs/mkdocs/issues/834
*/
.rst-content code {
white-space: pre-wrap;
word-wrap: break-word;
padding: 2px 5px;
}
/**
* Make code blocks display as blocks and give them the appropriate
* font size and padding.
*
* https://github.com/mkdocs/mkdocs/issues/855
* https://github.com/mkdocs/mkdocs/issues/834
* https://github.com/mkdocs/mkdocs/issues/233
*/
.rst-content pre code {
white-space: pre;
word-wrap: normal;
display: block;
padding: 12px;
font-size: 12px;
}
/**
* Fix code colors
*
* https://github.com/mkdocs/mkdocs/issues/2027
*/
.rst-content code {
color: #E74C3C;
}
.rst-content pre code {
color: #000;
background: #f8f8f8;
}
/*
* Fix link colors when the link text is inline code.
*
* https://github.com/mkdocs/mkdocs/issues/718
*/
a code {
color: #2980B9;
}
a:hover code {
color: #3091d1;
}
a:visited code {
color: #9B59B6;
}
/*
* The CSS classes from highlight.js seem to clash with the
* ReadTheDocs theme causing some code to be incorrectly made
* bold and italic.
*
* https://github.com/mkdocs/mkdocs/issues/411
*/
pre .cs, pre .c {
font-weight: inherit;
font-style: inherit;
}
/*
* Fix some issues with the theme and non-highlighted code
* samples. Without and highlighting styles attached the
* formatting is broken.
*
* https://github.com/mkdocs/mkdocs/issues/319
*/
.rst-content .no-highlight {
display: block;
padding: 0.5em;
color: #333;
}
/*
* Additions specific to the search functionality provided by MkDocs
*/
.search-results {
margin-top: 23px;
}
.search-results article {
border-top: 1px solid #E1E4E5;
padding-top: 24px;
}
.search-results article:first-child {
border-top: none;
}
form .search-query {
width: 100%;
border-radius: 50px;
padding: 6px 12px; /* csslint allow: box-model */
border-color: #D1D4D5;
}
/*
* Improve inline code blocks within admonitions.
*
* https://github.com/mkdocs/mkdocs/issues/656
*/
.rst-content .admonition code {
color: #404040;
border: 1px solid #c7c9cb;
border: 1px solid rgba(0, 0, 0, 0.2);
background: #f8fbfd;
background: rgba(255, 255, 255, 0.7);
}
/*
* Account for wide tables which go off the side.
* Override borders to avoid wierdness on narrow tables.
*
* https://github.com/mkdocs/mkdocs/issues/834
* https://github.com/mkdocs/mkdocs/pull/1034
*/
.rst-content .section .docutils {
width: 100%;
overflow: auto;
display: block;
border: none;
}
td, th {
border: 1px solid #e1e4e5 !important; /* csslint allow: important */
border-collapse: collapse;
}

View file

@ -1,312 +0,0 @@
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://blog.kianting.info/pages/docs/anotherTypeSetter/defineASTandGrammar/">
<link rel="shortcut icon" href="../img/favicon.ico">
<title>Ch 1 - Another Typesetter 另一個排版器</title>
<link rel="stylesheet" href="../css/theme.css" />
<link rel="stylesheet" href="../css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
<script>
// Current page data
var mkdocs_page_name = "Ch 1";
var mkdocs_page_input_path = "defineASTandGrammar.md";
var mkdocs_page_url = "/pages/docs/anotherTypeSetter/defineASTandGrammar/";
</script>
<script src="../js/jquery-2.1.1.min.js" defer></script>
<script src="../js/modernizr-2.8.3.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href=".." class="icon icon-home"> Another Typesetter 另一個排版器</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul>
<li class="toctree-l1"><a class="reference internal" href="..">Home</a>
</li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal current" href="./">Ch 1</a>
<ul class="current">
<li class="toctree-l2"><a class="reference internal" href="#_1">抽象語法樹</a>
</li>
<li class="toctree-l2"><a class="reference internal" href="#_2">決定語法</a>
</li>
<li class="toctree-l2"><a class="reference internal" href="#parsercombinatortokenize">用ParserCombinator進行tokenize</a>
</li>
<li class="toctree-l2"><a class="reference internal" href="#_3">平面操作</a>
<ul>
<li class="toctree-l3"><a class="reference internal" href="#_4">基本函數與直譯器</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="" href="../2DManipulating.md">Ch 2</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="..">Another Typesetter 另一個排版器</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="..">Docs</a> &raquo;</li>
<li>Ch 1</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<h1 id="ch1">Ch1 定義抽象語法樹和語法</h1>
<h2 id="_1">抽象語法樹</h2>
<p>C語言、Python語言就算有許多的關鍵字、操作符、符號或是常數變數在編譯器分析語法以後最後會轉成編譯器可以操作的樹結構然後再轉成我們想要的另一個語言的樹最後輸出另一個語言的程式碼。</p>
<p>但是什麼叫做抽象語法樹呢?我們先從一點句法知識來談。</p>
<p>學過中學國文文法的課程,會背一堆類似「主詞+動詞+受詞」、「主詞+(有/無)+受詞」的結構。可以換個說法,是句子=「主詞+動詞+受詞」或是「主詞+(有/無)+賓詞」的形式。我們將「=」寫成「::=」,「/」(或是)寫成「|」,「動詞」擴充變成「動詞片語」,就變成:</p>
<pre><code> 句子 ::= (主詞 動詞片語 受詞) | (主詞 (有 | 無) 受詞)...
</code></pre>
<p>為了易讀所以寫成:</p>
<pre><code>句子 ::= 主詞 動詞片語 受詞
| 主詞 (有 | 無) 受詞
| ...
</code></pre>
<p>用這種形式表示的語言句法叫做「BNF文法」。這種句法看起來很語言學但是我們想受詞和主詞可以為名詞、專有名詞或是「形容詞+名詞」;動詞片語可以為動詞或是「副詞+動詞」。因此這樣之規則,就可以生成許多句子,比如「我有筆」、「張三養貓」、「小芳慢慢移動檯燈」等等的句子。然後句子可以用上述規則,分析成語法的樹狀結構,如下圖把「我曾旅居新竹」寫成語法樹。</p>
<figure>
<p><img alt="「我曾旅居新竹」的語法樹" src="../syntaxtree.svg" title="" />
</p>
<figcaption>「我曾旅居新竹」的語法樹</figcaption>
</figure>
<p>同理,程式語言通常也有更嚴謹的這樣生成文法,可以用幾個簡單規則生出繁多的程式碼,而且合乎語法規定。這種生成文法也可檢查輸入的程式碼有沒有符合句法的規定。而這種語法生成的程式碼,去掉不需要的逗號等等符號,當然也可以做成語法樹,就是抽象語法樹 (abstract syntax tree, AST),如下圖所示。</p>
<figure>
<p><img alt="「(2+2) == 4」的語法樹。注意括號已經刪除。" src="../syntaxtree2.svg" title="" />
</p>
<figcaption>「(2+2) == 4」的語法樹。注意括號已經刪除。</figcaption>
</figure>
<p>而上文的抽象語法樹可以是我們把程式經過編譯器分析之後用「樹」儲存的資料結構。而樹形結構我們可以使用Lisp語言的S表達式(S-expressiom; S-exp)來表示,本文採用這樣的表示方法。所以上文的<code>(2+2)==4</code><code>(== (+ 2 2) 4)</code><code>let baz = foo("bar")</code>若是把foo("bar")這種函數套用(apply)寫成<code>(APPLY foo "bar")</code>則其S-exp語法樹可寫為<code>(let baz(APPLY foo "bar"))</code></p>
<h2 id="_2">決定語法</h2>
<p>那我們要如何制定這個語言的語法這樣我們才能夠寫出符合這個語法的函數然後再用tokenizer和parser轉成AST樹。</p>
<p>不考慮<code>+ - * /</code>這種運算子,以及向量的表示子,函數可以用<code>ID(arg1, arg2, ...)</code>這種方式來表示,其中<code>arg_x</code>是引數,<code>ID</code>是識別子identifier可以把它想成變函數的名字</p>
<p>變數可以是<code>ID</code><code>arg_n</code>可以是<code>ID</code>或常數(量)。</p>
<p>常數(量)的表示法可以是下列任一:</p>
<ul>
<li>
<p>浮點數如0.0, 36.8BNF風格的表達法為<code>[0-9]+ '.' [0-9]+</code><code>'c'</code>指c這個文字<code>+</code>表示前面的重複1次以上<code>[0-9]</code>表示數字0到9。</p>
</li>
<li>
<p>整數如22、0<code>[0-9]+</code></p>
</li>
<li>
<p>字串:<code>'"' (不是「"」的任一字元|('\' '"')) '"'</code><code>.</code>表示任何一個字元)</p>
</li>
</ul>
<p>然而我們還是需要綁定變數<code>let x = var in boby</code>(在<code>body</code>裡面,<code>x</code>指代<code>var</code>)、<code>set x = var</code>改變變數值、lambda<code>lambda (x)=&gt;{body}</code>。另外為了要區別要在PDF印上去的一般字元在這個檔案的常數、變數、函數、關鍵字等前後需要加@表示但是函數、lambda裡面的變數不用。比如<code>@foo(a, b)@</code><code>@lambda(x)@</code><code>@"IAmAString"@</code><code>@2.2@</code><code>@3@</code>後三者應該很少用到可是若需在PDF印<code>@</code>時怎辦?那就用<code>\@</code>。比如<code>foo\@example.com</code></p>
<p>所以我們可以定義以下的BNF風文法</p>
<pre><code>Language ::= PrintTxt | Exprs
PrintTxt ::= (('\' '@')| 非@字元)+ //「我是一隻貓」或是「www\@example.com」
Exprs ::= @ Expr* @ // *表示前面的重複0次以上包含不出現
Expr ::= (Letting | Setting | Lambda | Apply | Var| Const) | &quot;(&quot; Expr &quot;)&quot;
Letting ::= &quot;let&quot; Var &quot;=&quot; Expr &quot;in&quot; Expr // let foo = 12 in ...
Setting ::= Var &quot;:=&quot; Expr &quot;in&quot; Expr // foo := a in ...
Lambda ::= &quot;fn&quot; Var &quot;-&gt;&quot; Expr // fn x -&gt; 12
Apply ::= Expr Expr // foo 3 即foo(3)
Var ::= ID
Const ::= String | Float | Int
Int ::= [0-9]+
Float ::= [0-9]+ &quot;.&quot; [0-9]+
String ::= '&quot;' (不是「&quot;」的任一字元|('\' '&quot;')) '&quot;'
</code></pre>
<h2 id="parsercombinatortokenize">用ParserCombinator進行tokenize</h2>
<p>Parser combinator分析器組合子是一種利用高階函數來簡化分析器撰寫的辦法。講一個簡單的案例吧</p>
<p>假設我們想要將字串的開頭match 0~9 之中的其中一個我們可以寫一個函數match0to9如下</p>
<pre><code>function match0to9(string){
if (string[0] in 0,1,..,9){
let rest = string[1:];
let matched = string[0];
return {type: &quot;OK&quot;, rest : rest, matched : matched};
}
else{
return {type : &quot;Nothing&quot;};
}
}
</code></pre>
<p>假設我們要將字串的前兩個字的match 0~9呢如果會高階函數的話引入一個<code>then</code>函數,然後把<code>match0to9</code>傳進去,這樣寫起來比較簡潔:</p>
<pre><code>function thenDo(input, fun){
if (input.type != &quot;Nothing&quot;{
middle = fun(input.rest);
if (middle.type != &quot;Nothing&quot;){
middle.matched = input.matched + middle.matched
return middle;
}else{
return middle; // return nothing
}
}else{
input; // return nothing
}
}
</code></pre>
<h2 id="_3">平面操作</h2>
<h3 id="_4">基本函數與直譯器</h3>
<p>我們藉由以上的概念可以定義一個將文字、線條等形狀排列到2D平面的語法畢竟不論輸出PDF、SVG等等粗略而言就是一種2D平面安放文字的語言。另外PDF的格式相當晦澀就算_PDF Explained_的PDF教學也還是要輔助使用其他的工具沒辦法看了就自己手刻PDF所以還是用<code>printpdf</code>來教學吧。</p>
<p>現在我們初始化一個專案目錄然後將需要的S-exp函式庫和pdf函數庫指定為相依函式庫</p>
<pre><code>cargo init;
cargo add rsexp printpdf;
</code></pre>
<p>我們可以定義一些表達式包含函數、資料結構S-exp形式的說明如下。<code>'()</code>表示空列表(empty list),因為都要表達是函數的引用,所有的函數寫成形式<code>(Func "函數名稱" (引數1 引數2 ....))</code>。Float指64位元浮點數</p>
<pre><code>(px Float) ; px表達pixel單位儲存浮點數
(pt Float) ; pt表達point單位儲存浮點數
(style (str pt)) ; 文字樣式。String表示字型的路徑[fontPath]Float表示字型大小(in Pt) (fontSize)
(str String) ; 儲存字串
(func &quot;createPDF&quot; '()) ;新增PDF
(func &quot;createPage&quot; '()) ;新增頁面
(func &quot;writePdf&quot; '(str)) ;寫入PDF頁面String是PATH
(func &quot;putchar&quot; '(str style x y)) ; x 軸向右y 軸向下str 表示字元(char)style 表示文字樣式
</code></pre>
<p><code>main.rs</code>先引用函式庫:
<code>use printpdf::*;</code></p>
<p>其中 <code>px</code><code>pt</code>是單位,所以可以在<code>main.rs</code>這樣定義:</p>
<pre><code>enum Measure{
Pt(f64),
Px(f64)
}
</code></pre>
<p>最後一次定義expression</p>
<pre><code>enum Expr{
Mea(Measure), // wrapper for measure
Str(&amp;str),
Style{font_path : Measure, size : Measure},
Func(&amp;str, Vec&lt;Expr&gt;),
Void // return nothing
}
</code></pre>
<p>然後我們可以這樣定義一個處理輸入輸出的interpreter於<code>interp</code>,並修改<code>main.rs</code>如下,縱使我們準時:</p>
<pre><code>fn interp(exp : Expr)-&gt;(){
// the function will be extended.
match exp {
Expr::Mea(Measure::Pt(x)) =&gt; println!(&quot;{:?} pt&quot;, x),
Expr::Mea(Measure::Px(x)) =&gt; println!(&quot;{:?} px&quot;, x),
_ =&gt; println!(&quot;not found expression&quot;),
};
}
// exexute interpreter
fn main() {
interp(Expr::Mea(Measure::Pt(2.2)));
interp(Expr::Flo(2.2));
}
</code></pre>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href=".." class="btn btn-neutral" title="Home"><span class="icon icon-circle-arrow-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span><a href=".." style="color: #fcfcfc;">&laquo; Previous</a></span>
</span>
</div>
<script>var base_url = '..';</script>
<script src="../js/theme.js" defer></script>
<script src="../search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,172 +0,0 @@
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="None">
<link rel="canonical" href="https://blog.kianting.info/pages/docs/anotherTypeSetter/">
<link rel="shortcut icon" href="img/favicon.ico">
<title>Another Typesetter 另一個排版器</title>
<link rel="stylesheet" href="css/theme.css" />
<link rel="stylesheet" href="css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
<script>
// Current page data
var mkdocs_page_name = "Home";
var mkdocs_page_input_path = "index.md";
var mkdocs_page_url = "/pages/docs/anotherTypeSetter/";
</script>
<script src="js/jquery-2.1.1.min.js" defer></script>
<script src="js/modernizr-2.8.3.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="." class="icon icon-home"> Another Typesetter 另一個排版器</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="./search.html" method="get">
<input type="text" name="q" placeholder="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal current" href=".">Home</a>
<ul class="current">
<li class="toctree-l2"><a class="reference internal" href="#_1">摘要</a>
<ul>
<li class="toctree-l3"><a class="reference internal" href="#_2">序言</a>
</li>
<li class="toctree-l3"><a class="reference internal" href="#_3">先備知識</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="defineASTandGrammar/">Ch 1</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="" href="2DManipulating.md">Ch 2</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href=".">Another Typesetter 另一個排版器</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href=".">Docs</a> &raquo;</li>
<li>Home</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<h1 id="another-typesetter-">Another Typesetter - 另一個排版器</h1>
<h2 id="_1">摘要</h2>
<p>本文是講一個排版器的雛形如何製作的考察使用Rust語言。</p>
<h3 id="_2">序言</h3>
<p>以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。</p>
<p>但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的 <em>Digital Typography</em>,想要瞭解斷行演算法,結果粗估五、六十頁,所以幾乎沒有讀。</p>
<p>另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy G. Siek所著作之 <em>Essential of Complication: An Incremental Approach in Racket</em>編譯之要素Racket語言的遞增的方法。我想到既然編譯器這種複雜的軟體可以一層一層的用pass來遞增功能就像水彩從背景、大物體一直由少漸多的完成。而排版軟體也是把使用者輸入的排版之領域特定語言(DSL)轉換成文字、圖形和二維座標對應關係最後匯出成PDF或SVG等等的編譯器若是能夠用層層遞增的方法來完成相信也能夠避免結構的複雜化導致錯誤容易發生的挫折。</p>
<p>然而排版語言不只是輸入文字轉圖形而已,更重要的是還要有因應美觀的自動斷行(justification)和斷字(hyphenation)等等的演算法、還有PDF的基本知識、字型函式庫的取用、排版要求多欄、甚至還牽涉到語言特有的特性比如東亞全形文字漢字、諺文、日文假名、注音符號和非全形文字中間要加空白以及從左寫到右的文字希伯來字母和阿拉伯字母等的排版方法不一而足。</p>
<p>為了簡化起見且目標讀者是臺灣的受眾本書僅涉及到ASCII英文字母——頂多加些一些附加符號(diacritics)和漢字的排版。其他的功能希望讀者可以漸次由少漸多的附加。另外這邊會使用到一些LISP的表達式來表達抽象語法樹若是不懂的話可以看一點教 Lisp或是Scheme的書如SICP。另外這本書不是編譯原理和描述PDF規格的書不涉獵底層的知識有需要的可以參考相關領域的書。</p>
<h3 id="_3">先備知識</h3>
<p>這不是教一位入門使用者如從零知識撰寫排版軟體的書讀者應該有知道如何使用靜態型別語言的經驗比如一點C、或是Rust等等。另外抽象語法樹為求方便使用LISP撰寫所以需要會LISP和Scheme的知識知名教科書SICP的開頭可以讀一讀</p>
<p>這本書也不教編譯理論和tokenizing、parsing、狀態機等等的頂多只會帶到一些很基礎的知識有需要的請另外再讀。所以使用者需要會有使用正規表達式(regex)的能力。</p>
<p>操作環境使用Linux。需要安裝fontconfig等套件。</p>
<ul>
<li><a href="./defineASTandGrammar">定義抽象語法樹和語法</a></li>
</ul>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="defineASTandGrammar/" class="btn btn-neutral float-right" title="Ch 1">Next <span class="icon icon-circle-arrow-right"></span></a>
</div>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span style="margin-left: 15px"><a href="defineASTandGrammar/" style="color: #fcfcfc">Next &raquo;</a></span>
</span>
</div>
<script>var base_url = '.';</script>
<script src="js/theme.js" defer></script>
<script src="search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>
<!--
MkDocs version : 1.1.2
Build Date UTC : 2023-12-01 16:29:33.709363+00:00
-->

View file

@ -1,17 +0,0 @@
# Welcome to MkDocs
For full documentation visit [mkdocs.org](https://www.mkdocs.org).
## Commands
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.
## Project layout
mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.

Binary file not shown.

View file

@ -1,193 +0,0 @@
#set heading(numbering: "1.1.1.1.")
#show raw: set text(font: "Noto Sans Mono CJK TC")
#set page("a5")
#set text(
font: ("New Computer Modern", "AR PL UMing TW"),
size: 11pt
)
#show heading: it => [
#set text(font: "Noto Serif CJK TC",
weight: "black")
#it.body
]
#set par( justify: true,leading: 1em,
)
#align(center)[#set text(
font: ("EB Garamond 08"),
weight:"medium",
size: 20pt,
)
Clo: another typesetter]
#align(center)[#box([#set text(size: 15pt,
font: "Noto Serif CJK TC",
weight:"medium")
一個排版器的實作心得])]
#box(
height:0.5em
)
#align(center)[#box([#set text(size: 11pt,
font: "AR PL UMing TW",
weight:"light")
陳建町])]
#pagebreak()
#set page(
margin: (top: 60pt, bottom: 20pt),
header: locate(
loc => if (calc.odd(loc.page()) == true){
[#set align(right)
#numbering("i", loc.page())
]
} else {
[#set align(left)
#numbering("i", loc.page())]
}
));
#heading(level:2, "版權聲明",outlined:false)
(c) 2023 陳建町 (Tan, Kian-ting)
本書內容非經許可,禁止複製、分發、商業使用等違反著作權法之行為。
然書中之程式碼,採用 #link("https://opensource.org/license/mit/")[MIT許可證]授權。
#pagebreak()
#outline(
title: align(left, [目#box(width:1em)錄 #box(
height:1.5em)]),
target: heading.where(outlined: true),
)
#pagebreak()
#set page(
numbering: "i",
number-align: top+right)
#heading(numbering: none, "序言")
以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。
但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的 _Digital Typography_想要瞭解斷行演算法結果粗估五、六十頁所以幾乎沒有讀。
另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy G. Siek所著作之_Essential of Complication: An Incremental Approach in Racket_編譯之要素Racket語言的遞增的方法。我想到既然編譯器這種複雜的軟體可以一層一層的用pass來遞增功能就像水彩從背景、大物體一直由少漸多的完成。而排版軟體也是把使用者輸入的排版之領域特定語言(DSL)轉換成文字、圖形和二維座標對應關係最後匯出成PDF或SVG等等的編譯器若是能夠用層層遞增的方法來完成相信也能夠避免結構的複雜化導致錯誤容易發生的挫折。
然而排版語言不只是輸入文字轉圖形而已,更重要的是還要有因應美觀的自動斷行(justification)和斷字(hyphenation)等等的演算法、還有PDF的基本知識、字型函式庫的取用、排版要求多欄、甚至還牽涉到語言特有的特性比如東亞全形文字漢字、諺文、日文假名、注音符號和非全形文字中間要加空白以及從左寫到右的文字希伯來字母和阿拉伯字母等的排版方法不一而足。
為了簡化起見且目標讀者是臺灣的受眾本書僅涉及到ASCII英文字母——頂多加些一些附加符號(diacritics)和漢字的排版。其他的功能希望讀者可以漸次由少漸多的附加。另外這邊會使用到一些LISP的表達式來表達抽象語法樹若是不懂的話可以看一點教 Lisp或是Scheme的書如SICP。另外這本書不是編譯原理和描述PDF規格的書不涉獵底層的知識有需要的可以參考相關領域的書。
#heading(numbering: none, "致謝")
感謝Donald Knuth教授開發出這麼一套排版系統以及排版的演算法除了造福科學排版的諸多用戶外也間接鼓舞我想要研究排版軟體如何實作感謝Jeremy G.Siek老師的_Essential of Complication: An Incremental Approach in Racket_讓我獲得排版語言編譯器設計的啟發。感謝王垠讓我對編譯器相關的技術有興趣從而斷斷續續學習相關的資訊。
感謝愛爾蘭語除了讓我對語言和語言復興的知識打開新的世界以外這個軟體的名字Clo也是從這裡來的cló有「活字」的意思因為技術限制抱歉沒辦法輸入長音符號
感謝我的父母,雖然專長不是電腦資訊科技,但是要感謝他們讓我讓我有餘力能夠在中學的時候研究這種興趣,這條路才能走下去。
感謝這本書閱讀的人們,讓我知道筆者不是孤單的。
Siōng-āu Kám-siā góa ê Siōng Chú, nā-bô i ê hû-chhî kap pó-siú, chit-pún chheh iā bô-hó oân-sêng.(最後感謝上主,若無扶持保守,這本書也很難完成)
#pagebreak()
#set page(
margin: (top: 60pt, bottom: 20pt),
header: locate(
loc =>{
let chapter_query = query(selector(heading.where(level: 1)).after(loc),loc)
let section_query = query(selector(heading.where(level: 2)).after(loc),loc)
let chapter = "";
let section = "";
if chapter_query == (){chapter = ""}
else{chapter = chapter_query.at(0).body};
if section_query == (){section = ""}
else{section = section_query.at(0).body}
if (calc.odd(loc.page()) == true){
grid(
columns: (0.333333fr, 0.333333fr, 0.333333fr),
text(style: "italic")[ ],
[#set align(center)
#chapter],
[ #h(1fr) #loc.page-numbering()])
} else {
grid(
columns: (0.333333fr, 0.333333fr, 0.333333fr),
text(style: "italic")[#loc.page-numbering()],
[#set align(center)
#section],
[ ])
}}
));
#show heading: it => [
#set text(font: ("New Computer Modern", "Noto Serif CJK TC"),
weight: "black")
#counter(heading).display() #it
]
#set page(numbering: "1")
#counter(page).update(1)
#set heading(numbering: "1.1.1.1.1")
= 先備知識
這不是教一位入門使用者如從零知識撰寫排版軟體的書讀者應該有知道如何使用靜態型別語言的經驗比如一點C、或是Rust等等。另外抽象語法樹為求方便使用LISP撰寫所以需要會LISP和Scheme的知識知名教科書SICP的開頭可以讀一讀
這本書也不教編譯理論和tokenizing、parsing、狀態機等等的頂多只會帶到一些很基礎的知識有需要的請另外再讀。所以使用者需要會有使用正規表達式(regex)的能力。
== 抽象語法樹
C語言、Python語言就算有許多的關鍵字、操作符、符號或是常數變數在編譯器分析語法以後最後會轉成編譯器可以操作的樹結構然後再轉成我們想要的另一個語言的樹最後輸出另一個語言的程式碼。
但是什麼叫做抽象語法樹呢?我們先從一點句法知識來談。
學過中學國文文法的課程,會背一堆類似「主詞+動詞+受詞」、「主詞+(有/無)+受詞」的結構。可以換個說法,是句子=「主詞+動詞+受詞」或是「主詞+(有/無)+賓詞」的形式。我們將「=」寫成「::=」,「/」(或是)寫成「|」,動詞擴充變成「動詞片語」,就變成:
```
句子 ::= (主詞 動詞片語 受詞) | (主詞 (有 | 無) 受詞)...
```
用這種形式表示的語言句法叫做「BNF文法」。這種句法看起來很語言學但是我們想受詞和主詞可以為名詞、專有名詞或是「形容詞+名詞」;動詞片語可以為動詞或是「副詞+動詞」。因此這樣之規則就可以生成許多句子比如「我有筆」、「張三養貓」、「小芳慢慢移動檯燈」等等的句子。然後句子可以用上述規則分析成語法的樹狀結構如圖1把「我曾旅居新竹」寫成語法樹。
#figure(
image("syntaxtree.svg", width: 40%),
caption: [
「我曾旅居新竹」的語法樹
],
supplement: [圖],
)
同理,程式語言通常也有更嚴謹的這樣生成文法,可以用幾個簡單規則生出繁多的程式碼,而且合乎語法規定。這種生成文法也可檢查輸入的程式碼有沒有符合句法的規定。而這種語法生成的程式碼,去掉不需要的逗號等等符號,當然也可以做成語法樹,就是抽象語法樹 (abstract syntax tree, AST)如圖2所示。
#figure(
image("syntaxtree2.svg", width: 30%),
caption: [
`(2+2) == 4`的語法樹。注意括號已經刪除。
],
supplement: [圖],
)
而上文的抽象語法樹可以是我們把程式經過編譯器分析之後用「樹」儲存的資料結構。而樹形結構我們可以使用Lisp語言的S表達式(S-expressiom; S-exp)來表示,本文採用這樣的表示方法。所以上文的`(2+2)==4`即`(== (+ 2 2) 4)``let baz = foo("bar")`若是把foo("bar")這種函數套用(apply)寫成`(APPLY foo "bar")`則其S-exp語法樹可寫為`(let baz(APPLY foo "bar"))`。

View file

@ -1,148 +0,0 @@
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://blog.kianting.info/pages/docs/anotherTypeSetter/index2/">
<link rel="shortcut icon" href="../img/favicon.ico">
<title>Index2 - Another Typesetter 另一個排版器</title>
<link rel="stylesheet" href="../css/theme.css" />
<link rel="stylesheet" href="../css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
<script>
// Current page data
var mkdocs_page_name = "Index2";
var mkdocs_page_input_path = "index2.md";
var mkdocs_page_url = "/pages/docs/anotherTypeSetter/index2/";
</script>
<script src="../js/jquery-2.1.1.min.js" defer></script>
<script src="../js/modernizr-2.8.3.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href=".." class="icon icon-home"> Another Typesetter 另一個排版器</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul>
<li class="toctree-l1"><a class="reference internal" href="..">Home</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../defineASTandGrammar/">Ch 1</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="" href="../2DManipulating.md">Ch 2</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="..">Another Typesetter 另一個排版器</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="..">Docs</a> &raquo;</li>
<li>Index2</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<p>[ Clo: another typesetter]{align="center"} [[
一個排版器的實作心得]{.box}]{align="center"} []{.box} [[
陳建町]{.box}]{align="center"}</p>
<p>版權聲明</p>
<p>(c) 2023 陳建町 (Tan, Kian-ting)</p>
<p>本書內容非經許可,禁止複製、分發、商業使用等違反著作權法之行為。</p>
<p>然書中之程式碼,採用
<a href="https://opensource.org/license/mit/">MIT許可證</a>授權。</p>
<p>序言</p>
<p>以前從國中時候試用Linux以及架站以後就開始想用LaTeX排版些自己所寫的東西其中包含覺得LaTeX的語法不好想要重造輪子。就算後來大學沒有走上資訊工程這條路還是希望有天至少能夠完成個能用的雛形。</p>
<p>但是這是涉及字體檔案的處理、PDF的處理、語法分析後來自己因為不知道如何開發所以一直停擺。不是遇到很多蟲就是效能問題有缺失。因為時間繁忙很少更不消說了。甚至買了Knuth教授的
<em>Digital
Typography</em>,想要瞭解斷行演算法,結果粗估五、六十頁,所以幾乎沒有讀。</p>
<p>另外筆者一個分支興趣是編譯器的相關知識所以開始讀和王垠的編譯器思想系出同門的Jeremy
G. Siek所著作之_Essential of Complication: An Incremental Approach in
Racket</p>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
</span>
</div>
<script>var base_url = '..';</script>
<script src="../js/theme.js" defer></script>
<script src="../search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,265 +0,0 @@
var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery');
// Sphinx theme nav state
function ThemeNav () {
var nav = {
navBar: null,
win: null,
winScroll: false,
winResize: false,
linkScroll: false,
winPosition: 0,
winHeight: null,
docHeight: null,
isRunning: false
};
nav.enable = function (withStickyNav) {
var self = this;
// TODO this can likely be removed once the theme javascript is broken
// out from the RTD assets. This just ensures old projects that are
// calling `enable()` get the sticky menu on by default. All other cals
// to `enable` should include an argument for enabling the sticky menu.
if (typeof(withStickyNav) == 'undefined') {
withStickyNav = true;
}
if (self.isRunning) {
// Only allow enabling nav logic once
return;
}
self.isRunning = true;
jQuery(function ($) {
self.init($);
self.reset();
self.win.on('hashchange', self.reset);
if (withStickyNav) {
// Set scroll monitor
self.win.on('scroll', function () {
if (!self.linkScroll) {
if (!self.winScroll) {
self.winScroll = true;
requestAnimationFrame(function() { self.onScroll(); });
}
}
});
}
// Set resize monitor
self.win.on('resize', function () {
if (!self.winResize) {
self.winResize = true;
requestAnimationFrame(function() { self.onResize(); });
}
});
self.onResize();
});
};
// TODO remove this with a split in theme and Read the Docs JS logic as
// well, it's only here to support 0.3.0 installs of our theme.
nav.enableSticky = function() {
this.enable(true);
};
nav.init = function ($) {
var doc = $(document),
self = this;
this.navBar = $('div.wy-side-scroll:first');
this.win = $(window);
// Set up javascript UX bits
$(document)
// Shift nav in mobile when clicking the menu.
.on('click', "[data-toggle='wy-nav-top']", function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
})
// Nav menu link click operations
.on('click', ".wy-menu-vertical .current ul li a", function() {
var target = $(this);
// Close menu when you click a link.
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
// Handle dynamic display of l3 and l4 nav lists
self.toggleCurrent(target);
self.hashChange();
})
.on('click', "[data-toggle='rst-current-version']", function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up");
})
// Make tables responsive
$("table.docutils:not(.field-list,.footnote,.citation)")
.wrap("<div class='wy-table-responsive'></div>");
// Add extra class to responsive tables that contain
// footnotes or citations so that we can target them for styling
$("table.docutils.footnote")
.wrap("<div class='wy-table-responsive footnote'></div>");
$("table.docutils.citation")
.wrap("<div class='wy-table-responsive citation'></div>");
// Add expand links to all parents of nested ul
$('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
var link = $(this);
expand =
$('<button class="toctree-expand" title="Open/close menu"></button>');
expand.on('click', function (ev) {
self.toggleCurrent(link);
ev.stopPropagation();
return false;
});
link.prepend(expand);
});
};
nav.reset = function () {
// Get anchor from URL and open up nested nav
var anchor = encodeURI(window.location.hash) || '#';
try {
var vmenu = $('.wy-menu-vertical');
var link = vmenu.find('[href="' + anchor + '"]');
if (link.length === 0) {
// this link was not found in the sidebar.
// Find associated id element, then its closest section
// in the document and try with that one.
var id_elt = $('.document [id="' + anchor.substring(1) + '"]');
var closest_section = id_elt.closest('div.section');
link = vmenu.find('[href="#' + closest_section.attr("id") + '"]');
if (link.length === 0) {
// still not found in the sidebar. fall back to main section
link = vmenu.find('[href="#"]');
}
}
// If we found a matching link then reset current and re-apply
// otherwise retain the existing match
if (link.length > 0) {
$('.wy-menu-vertical .current')
.removeClass('current')
.attr('aria-expanded','false');
link.addClass('current')
.attr('aria-expanded','true');
link.closest('li.toctree-l1')
.parent()
.addClass('current')
.attr('aria-expanded','true');
for (let i = 1; i <= 10; i++) {
link.closest('li.toctree-l' + i)
.addClass('current')
.attr('aria-expanded','true');
}
link[0].scrollIntoView();
}
}
catch (err) {
console.log("Error expanding nav for anchor", err);
}
};
nav.onScroll = function () {
this.winScroll = false;
var newWinPosition = this.win.scrollTop(),
winBottom = newWinPosition + this.winHeight,
navPosition = this.navBar.scrollTop(),
newNavPosition = navPosition + (newWinPosition - this.winPosition);
if (newWinPosition < 0 || winBottom > this.docHeight) {
return;
}
this.navBar.scrollTop(newNavPosition);
this.winPosition = newWinPosition;
};
nav.onResize = function () {
this.winResize = false;
this.winHeight = this.win.height();
this.docHeight = $(document).height();
};
nav.hashChange = function () {
this.linkScroll = true;
this.win.one('hashchange', function () {
this.linkScroll = false;
});
};
nav.toggleCurrent = function (elem) {
var parent_li = elem.closest('li');
parent_li
.siblings('li.current')
.removeClass('current')
.attr('aria-expanded','false');
parent_li
.siblings()
.find('li.current')
.removeClass('current')
.attr('aria-expanded','false');
var children = parent_li.find('> ul li');
// Don't toggle terminal elements.
if (children.length) {
children
.removeClass('current')
.attr('aria-expanded','false');
parent_li
.toggleClass('current')
.attr('aria-expanded', function(i, old) {
return old == 'true' ? 'false' : 'true';
});
}
}
return nav;
};
_ThemeNav = ThemeNav();
if (typeof(window) != 'undefined') {
window.SphinxRtdTheme = {
Navigation: _ThemeNav,
// TODO remove this once static assets are split up between the theme
// and Read the Docs. For now, this patches 0.3.0 to be backwards
// compatible with a pre-0.3.0 layout.html
StickyNav: _ThemeNav,
};
}
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// https://gist.github.com/paulirish/1579671
// MIT license
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|| window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());

View file

@ -1,135 +0,0 @@
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="./img/favicon.ico">
<title>Another Typesetter 另一個排版器</title>
<link rel="stylesheet" href="./css/theme.css" />
<link rel="stylesheet" href="./css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
<script src="./js/jquery-2.1.1.min.js" defer></script>
<script src="./js/modernizr-2.8.3.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="./." class="icon icon-home"> Another Typesetter 另一個排版器</a>
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="./search.html" method="get">
<input type="text" name="q" placeholder="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul>
<li class="toctree-l1"><a class="reference internal" href="./.">Home</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="./defineASTandGrammar/">Ch 1</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="" href="./2DManipulating.md">Ch 2</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="./.">Another Typesetter 另一個排版器</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="./.">Docs</a> &raquo;</li>
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
<div class="section">
<h1 id="search">Search Results</h1>
<form id="content_search" action="search.html">
<span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span>
<input name="q" id="mkdocs-search-query" type="text" class="search_input search-query ui-autocomplete-input" placeholder="Search the Docs" autocomplete="off" autofocus title="Type search term here">
</form>
<div id="mkdocs-search-results" class="search-results">
Searching...
</div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
</span>
</div>
<script>var base_url = '.';</script>
<script src="./js/theme.js" defer></script>
<script src="./search/main.js" defer></script>
<script defer>
window.onload = function () {
SphinxRtdTheme.Navigation.enable(true);
};
</script>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,98 +0,0 @@
function getSearchTermFromLocation() {
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++) {
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == 'q') {
return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20'));
}
}
}
function joinUrl (base, path) {
if (path.substring(0, 1) === "/") {
// path starts with `/`. Thus it is absolute.
return path;
}
if (base.substring(base.length-1) === "/") {
// base ends with `/`
return base + path;
}
return base + "/" + path;
}
function formatResult (location, title, summary) {
return '<article><h3><a href="' + joinUrl(base_url, location) + '">'+ title + '</a></h3><p>' + summary +'</p></article>';
}
function displayResults (results) {
var search_results = document.getElementById("mkdocs-search-results");
while (search_results.firstChild) {
search_results.removeChild(search_results.firstChild);
}
if (results.length > 0){
for (var i=0; i < results.length; i++){
var result = results[i];
var html = formatResult(result.location, result.title, result.summary);
search_results.insertAdjacentHTML('beforeend', html);
}
} else {
search_results.insertAdjacentHTML('beforeend', "<p>No results found</p>");
}
}
function doSearch () {
var query = document.getElementById('mkdocs-search-query').value;
if (query.length > min_search_length) {
if (!window.Worker) {
displayResults(search(query));
} else {
searchWorker.postMessage({query: query});
}
} else {
// Clear results for short queries
displayResults([]);
}
}
function initSearch () {
var search_input = document.getElementById('mkdocs-search-query');
if (search_input) {
search_input.addEventListener("keyup", doSearch);
}
var term = getSearchTermFromLocation();
if (term) {
search_input.value = term;
doSearch();
}
}
function onWorkerMessage (e) {
if (e.data.allowSearch) {
initSearch();
} else if (e.data.results) {
var results = e.data.results;
displayResults(results);
} else if (e.data.config) {
min_search_length = e.data.config.min_search_length-1;
}
}
if (!window.Worker) {
console.log('Web Worker API not supported');
// load index in main thread
$.getScript(joinUrl(base_url, "search/worker.js")).done(function () {
console.log('Loaded worker');
init();
window.postMessage = function (msg) {
onWorkerMessage({data: msg});
};
}).fail(function (jqxhr, settings, exception) {
console.error('Could not load worker.js');
});
} else {
// Wrap search in a web worker
var searchWorker = new Worker(joinUrl(base_url, "search/worker.js"));
searchWorker.postMessage({init: true});
searchWorker.onmessage = onWorkerMessage;
}

File diff suppressed because one or more lines are too long

View file

@ -1,130 +0,0 @@
var base_path = 'function' === typeof importScripts ? '.' : '/search/';
var allowSearch = false;
var index;
var documents = {};
var lang = ['en'];
var data;
function getScript(script, callback) {
console.log('Loading script: ' + script);
$.getScript(base_path + script).done(function () {
callback();
}).fail(function (jqxhr, settings, exception) {
console.log('Error: ' + exception);
});
}
function getScriptsInOrder(scripts, callback) {
if (scripts.length === 0) {
callback();
return;
}
getScript(scripts[0], function() {
getScriptsInOrder(scripts.slice(1), callback);
});
}
function loadScripts(urls, callback) {
if( 'function' === typeof importScripts ) {
importScripts.apply(null, urls);
callback();
} else {
getScriptsInOrder(urls, callback);
}
}
function onJSONLoaded () {
data = JSON.parse(this.responseText);
var scriptsToLoad = ['lunr.js'];
if (data.config && data.config.lang && data.config.lang.length) {
lang = data.config.lang;
}
if (lang.length > 1 || lang[0] !== "en") {
scriptsToLoad.push('lunr.stemmer.support.js');
if (lang.length > 1) {
scriptsToLoad.push('lunr.multi.js');
}
for (var i=0; i < lang.length; i++) {
if (lang[i] != 'en') {
scriptsToLoad.push(['lunr', lang[i], 'js'].join('.'));
}
}
}
loadScripts(scriptsToLoad, onScriptsLoaded);
}
function onScriptsLoaded () {
console.log('All search scripts loaded, building Lunr index...');
if (data.config && data.config.separator && data.config.separator.length) {
lunr.tokenizer.separator = new RegExp(data.config.separator);
}
if (data.index) {
index = lunr.Index.load(data.index);
data.docs.forEach(function (doc) {
documents[doc.location] = doc;
});
console.log('Lunr pre-built index loaded, search ready');
} else {
index = lunr(function () {
if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) {
this.use(lunr[lang[0]]);
} else if (lang.length > 1) {
this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility
}
this.field('title');
this.field('text');
this.ref('location');
for (var i=0; i < data.docs.length; i++) {
var doc = data.docs[i];
this.add(doc);
documents[doc.location] = doc;
}
});
console.log('Lunr index built, search ready');
}
allowSearch = true;
postMessage({config: data.config});
postMessage({allowSearch: allowSearch});
}
function init () {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", onJSONLoaded);
var index_path = base_path + '/search_index.json';
if( 'function' === typeof importScripts ){
index_path = 'search_index.json';
}
oReq.open("GET", index_path);
oReq.send();
}
function search (query) {
if (!allowSearch) {
console.error('Assets for search still loading');
return;
}
var resultDocuments = [];
var results = index.search(query);
for (var i=0; i < results.length; i++){
var result = results[i];
doc = documents[result.ref];
doc.summary = doc.text.substring(0, 200);
resultDocuments.push(doc);
}
return resultDocuments;
}
if( 'function' === typeof importScripts ) {
onmessage = function (e) {
if (e.data.init) {
init();
} else if (e.data.query) {
postMessage({ results: search(e.data.query) });
} else {
console.error("Worker - Unrecognized message: " + e);
}
};
}

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url>
<loc>https://blog.kianting.info/pages/docs/anotherTypeSetter/</loc>
<lastmod>2023-12-01</lastmod>
<changefreq>daily</changefreq>
</url><url>
<loc>https://blog.kianting.info/pages/docs/anotherTypeSetter/defineASTandGrammar/</loc>
<lastmod>2023-12-01</lastmod>
<changefreq>daily</changefreq>
</url>
</urlset>

Binary file not shown.

View file

@ -1 +0,0 @@
<svg baseProfile="full" height="248px" preserveAspectRatio="xMidYMid meet" style="font-family: times, serif; font-weight: normal; font-style: normal; font-size: 16px;" version="1.1" viewBox="0,0,144.0,248.0" width="144px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">句子</text></svg><svg width="27.7778%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">主詞</text></svg><svg width="100%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">代詞 </text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px"></text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="72px" /></svg><line stroke="black" x1="50%" x2="50%" y1="19.2px" y2="56px" /></svg><line stroke="black" x1="50%" x2="13.8889%" y1="19.2px" y2="48px" /><svg width="72.2222%" x="27.7778%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">謂語</text></svg><svg width="69.2308%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">動詞</text><text text-anchor="middle" x="50%" y="32px">片語 </text></svg><svg width="44.4444%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">副詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px"></text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="22.2222%" y1="35.2px" y2="72px" /><svg width="55.5556%" x="44.4444%" y="64px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">動詞 </text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">旅居</text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="72.2222%" y1="35.2px" y2="72px" /></svg><line stroke="black" x1="50%" x2="34.6154%" y1="19.2px" y2="48px" /><svg width="30.7692%" x="69.2308%" y="48px"><defs /><svg width="100%" x="0" y="8px"><defs /><text text-anchor="middle" x="50%" y="16px">受詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">專有</text><text text-anchor="middle" x="50%" y="32px">名詞</text></svg><svg width="100%" x="0%" y="64px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">新竹</text></svg></svg><line stroke="black" x1="50%" x2="50%" y1="35.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="50%" y1="27.2px" y2="64px" /></svg><line stroke="black" x1="50%" x2="84.6154%" y1="19.2px" y2="56px" /></svg><line stroke="black" x1="50%" x2="63.8889%" y1="19.2px" y2="48px" /></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1 +0,0 @@
<svg baseProfile="full" height="120px" preserveAspectRatio="xMidYMid meet" style="font-family: times, serif; font-weight: normal; font-style: normal; font-size: 16px;" version="1.1" viewBox="0,0,72.0,120.0" width="72px" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">==</text></svg><svg width="66.6667%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">+</text></svg><svg width="50%" x="0%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">1</text></svg></svg><line stroke="black" x1="50%" x2="25%" y1="19.2px" y2="48px" /><svg width="50%" x="50%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">1</text></svg></svg><line stroke="black" x1="50%" x2="75%" y1="19.2px" y2="48px" /></svg><line stroke="black" x1="50%" x2="33.3333%" y1="19.2px" y2="48px" /><svg width="33.3333%" x="66.6667%" y="48px"><defs /><svg width="100%" x="0" y="0px"><defs /><text text-anchor="middle" x="50%" y="16px">2</text></svg></svg><line stroke="black" x1="50%" x2="83.3333%" y1="19.2px" y2="48px" /></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1 +0,0 @@
../esprima/bin/esparse.js

View file

@ -1 +0,0 @@
../esprima/bin/esvalidate.js

View file

@ -1 +0,0 @@
../js-yaml/bin/js-yaml.js

View file

@ -1 +0,0 @@
../mkdirp/bin/cmd.js

View file

@ -1 +0,0 @@
../resolve/bin/resolve

View file

@ -1 +0,0 @@
../semver/bin/semver.js

View file

@ -1 +0,0 @@
../tslint/bin/tslint

View file

@ -1,116 +0,0 @@
{
"systemParams": "linux-x64-93",
"modulesFolders": [
"node_modules"
],
"flags": [],
"linkedModules": [],
"topLevelPatterns": [
"@types/node@^20.10.4",
"@typescript-eslint/eslint-plugin@^6.13.2",
"@typescript-eslint/parser@^6.13.2",
"tslint@^6.1.3",
"typescript-parsec@^0.3.4"
],
"lockfileEntries": {
"@babel/code-frame@^7.0.0": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
"@babel/helper-validator-identifier@^7.22.20": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"@babel/highlight@^7.23.4": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
"@eslint-community/eslint-utils@^4.4.0": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
"@eslint-community/regexpp@^4.5.1": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
"@nodelib/fs.scandir@2.1.5": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"@nodelib/fs.stat@2.0.5": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"@nodelib/fs.stat@^2.0.2": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"@nodelib/fs.walk@^1.2.3": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"@types/json-schema@^7.0.12": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"@types/node@^20.10.4": "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198",
"@types/semver@^7.5.0": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
"@typescript-eslint/eslint-plugin@^6.13.2": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz",
"@typescript-eslint/parser@^6.13.2": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz",
"@typescript-eslint/scope-manager@6.13.2": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz",
"@typescript-eslint/type-utils@6.13.2": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz",
"@typescript-eslint/types@6.13.2": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz",
"@typescript-eslint/typescript-estree@6.13.2": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz",
"@typescript-eslint/utils@6.13.2": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz",
"@typescript-eslint/visitor-keys@6.13.2": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz",
"ansi-styles@^3.2.1": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"argparse@^1.0.7": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"array-union@^2.1.0": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"balanced-match@^1.0.0": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"brace-expansion@^1.1.7": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"braces@^3.0.2": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"builtin-modules@^1.1.1": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"chalk@^2.3.0": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"chalk@^2.4.2": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"color-convert@^1.9.0": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"color-name@1.1.3": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"commander@^2.12.1": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"concat-map@0.0.1": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"debug@^4.3.4": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"diff@^4.0.1": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"dir-glob@^3.0.1": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"escape-string-regexp@^1.0.5": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"eslint-visitor-keys@^3.3.0": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"eslint-visitor-keys@^3.4.1": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"esprima@^4.0.0": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"fast-glob@^3.2.9": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
"fastq@^1.6.0": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
"fill-range@^7.0.1": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"fs.realpath@^1.0.0": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"function-bind@^1.1.2": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"glob-parent@^5.1.2": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"glob@^7.1.1": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"globby@^11.1.0": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"graphemer@^1.4.0": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"has-flag@^3.0.0": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"hasown@^2.0.0": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
"ignore@^5.2.0": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
"ignore@^5.2.4": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
"inflight@^1.0.4": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"inherits@2": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"is-core-module@^2.13.0": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"is-extglob@^2.1.1": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"is-glob@^4.0.1": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"is-glob@^4.0.3": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"is-number@^7.0.0": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"js-tokens@^4.0.0": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"js-yaml@^3.13.1": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"lru-cache@^6.0.0": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"merge2@^1.3.0": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"merge2@^1.4.1": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"micromatch@^4.0.4": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"minimatch@^3.0.4": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"minimatch@^3.1.1": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"minimist@^1.2.6": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"mkdirp@^0.5.3": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"ms@2.1.2": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"natural-compare@^1.4.0": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"once@^1.3.0": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"path-is-absolute@^1.0.0": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"path-parse@^1.0.7": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"path-type@^4.0.0": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"picomatch@^2.3.1": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"queue-microtask@^1.2.2": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"resolve@^1.3.2": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"reusify@^1.0.4": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"run-parallel@^1.1.9": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"semver@^5.3.0": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"semver@^7.5.4": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"slash@^3.0.0": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"sprintf-js@~1.0.2": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"supports-color@^5.3.0": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"supports-preserve-symlinks-flag@^1.0.0": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"to-regex-range@^5.0.1": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"ts-api-utils@^1.0.1": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
"tslib@^1.13.0": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"tslib@^1.8.1": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"tslint@^6.1.3": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
"tsutils@^2.29.0": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"typescript-parsec@^0.3.4": "https://registry.npmjs.org/typescript-parsec/-/typescript-parsec-0.3.4.tgz",
"undici-types@~5.26.4": "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617",
"wrappy@1": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"yallist@^4.0.0": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
},
"files": [],
"artifacts": {}
}

View file

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,19 +0,0 @@
# @babel/code-frame
> Generate errors that contain a code frame that point to source locations.
See our website [@babel/code-frame](https://babeljs.io/docs/babel-code-frame) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/code-frame
```
or using yarn:
```sh
yarn add @babel/code-frame --dev
```

View file

@ -1,157 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.codeFrameColumns = codeFrameColumns;
exports.default = _default;
var _highlight = require("@babel/highlight");
var _chalk = _interopRequireWildcard(require("chalk"), true);
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
let chalkWithForcedColor = undefined;
function getChalk(forceColor) {
if (forceColor) {
var _chalkWithForcedColor;
(_chalkWithForcedColor = chalkWithForcedColor) != null ? _chalkWithForcedColor : chalkWithForcedColor = new _chalk.default.constructor({
enabled: true,
level: 1
});
return chalkWithForcedColor;
}
return _chalk.default;
}
let deprecationWarningShown = false;
function getDefs(chalk) {
return {
gutter: chalk.grey,
marker: chalk.red.bold,
message: chalk.red.bold
};
}
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
function getMarkerLines(loc, source, opts) {
const startLoc = Object.assign({
column: 0,
line: -1
}, loc.start);
const endLoc = Object.assign({}, startLoc, loc.end);
const {
linesAbove = 2,
linesBelow = 3
} = opts || {};
const startLine = startLoc.line;
const startColumn = startLoc.column;
const endLine = endLoc.line;
const endColumn = endLoc.column;
let start = Math.max(startLine - (linesAbove + 1), 0);
let end = Math.min(source.length, endLine + linesBelow);
if (startLine === -1) {
start = 0;
}
if (endLine === -1) {
end = source.length;
}
const lineDiff = endLine - startLine;
const markerLines = {};
if (lineDiff) {
for (let i = 0; i <= lineDiff; i++) {
const lineNumber = i + startLine;
if (!startColumn) {
markerLines[lineNumber] = true;
} else if (i === 0) {
const sourceLength = source[lineNumber - 1].length;
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
} else if (i === lineDiff) {
markerLines[lineNumber] = [0, endColumn];
} else {
const sourceLength = source[lineNumber - i].length;
markerLines[lineNumber] = [0, sourceLength];
}
}
} else {
if (startColumn === endColumn) {
if (startColumn) {
markerLines[startLine] = [startColumn, 0];
} else {
markerLines[startLine] = true;
}
} else {
markerLines[startLine] = [startColumn, endColumn - startColumn];
}
}
return {
start,
end,
markerLines
};
}
function codeFrameColumns(rawLines, loc, opts = {}) {
const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts);
const chalk = getChalk(opts.forceColor);
const defs = getDefs(chalk);
const maybeHighlight = (chalkFn, string) => {
return highlighted ? chalkFn(string) : string;
};
const lines = rawLines.split(NEWLINE);
const {
start,
end,
markerLines
} = getMarkerLines(loc, lines, opts);
const hasColumns = loc.start && typeof loc.start.column === "number";
const numberMaxWidth = String(end).length;
const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines;
let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => {
const number = start + 1 + index;
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
const gutter = ` ${paddedNumber} |`;
const hasMarker = markerLines[number];
const lastMarkerLine = !markerLines[number + 1];
if (hasMarker) {
let markerLine = "";
if (Array.isArray(hasMarker)) {
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
const numberOfMarkers = hasMarker[1] || 1;
markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), " ", markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join("");
if (lastMarkerLine && opts.message) {
markerLine += " " + maybeHighlight(defs.message, opts.message);
}
}
return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
} else {
return ` ${maybeHighlight(defs.gutter, gutter)}${line.length > 0 ? ` ${line}` : ""}`;
}
}).join("\n");
if (opts.message && !hasColumns) {
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
}
if (highlighted) {
return chalk.reset(frame);
} else {
return frame;
}
}
function _default(rawLines, lineNumber, colNumber, opts = {}) {
if (!deprecationWarningShown) {
deprecationWarningShown = true;
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
if (process.emitWarning) {
process.emitWarning(message, "DeprecationWarning");
} else {
const deprecationError = new Error(message);
deprecationError.name = "DeprecationWarning";
console.warn(new Error(message));
}
}
colNumber = Math.max(colNumber, 0);
const location = {
start: {
column: colNumber,
line: lineNumber
}
};
return codeFrameColumns(rawLines, location, opts);
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,30 +0,0 @@
{
"name": "@babel/code-frame",
"version": "7.23.5",
"description": "Generate errors that contain a code frame that point to source locations.",
"author": "The Babel Team (https://babel.dev/team)",
"homepage": "https://babel.dev/docs/en/next/babel-code-frame",
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-code-frame"
},
"main": "./lib/index.js",
"dependencies": {
"@babel/highlight": "^7.23.4",
"chalk": "^2.4.2"
},
"devDependencies": {
"import-meta-resolve": "^4.0.0",
"strip-ansi": "^4.0.0"
},
"engines": {
"node": ">=6.9.0"
},
"type": "commonjs"
}

View file

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,19 +0,0 @@
# @babel/helper-validator-identifier
> Validate identifier/keywords name
See our website [@babel/helper-validator-identifier](https://babeljs.io/docs/babel-helper-validator-identifier) for more information.
## Install
Using npm:
```sh
npm install --save @babel/helper-validator-identifier
```
or using yarn:
```sh
yarn add @babel/helper-validator-identifier
```

View file

@ -1,70 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isIdentifierChar = isIdentifierChar;
exports.isIdentifierName = isIdentifierName;
exports.isIdentifierStart = isIdentifierStart;
let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65";
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 4026, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 757, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191];
const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 81, 2, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 9, 5351, 0, 7, 14, 13835, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 983, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
function isInAstralSet(code, set) {
let pos = 0x10000;
for (let i = 0, length = set.length; i < length; i += 2) {
pos += set[i];
if (pos > code) return false;
pos += set[i + 1];
if (pos >= code) return true;
}
return false;
}
function isIdentifierStart(code) {
if (code < 65) return code === 36;
if (code <= 90) return true;
if (code < 97) return code === 95;
if (code <= 122) return true;
if (code <= 0xffff) {
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
}
return isInAstralSet(code, astralIdentifierStartCodes);
}
function isIdentifierChar(code) {
if (code < 48) return code === 36;
if (code < 58) return true;
if (code < 65) return false;
if (code <= 90) return true;
if (code < 97) return code === 95;
if (code <= 122) return true;
if (code <= 0xffff) {
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
}
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
}
function isIdentifierName(name) {
let isFirst = true;
for (let i = 0; i < name.length; i++) {
let cp = name.charCodeAt(i);
if ((cp & 0xfc00) === 0xd800 && i + 1 < name.length) {
const trail = name.charCodeAt(++i);
if ((trail & 0xfc00) === 0xdc00) {
cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);
}
}
if (isFirst) {
isFirst = false;
if (!isIdentifierStart(cp)) {
return false;
}
} else if (!isIdentifierChar(cp)) {
return false;
}
}
return !isFirst;
}
//# sourceMappingURL=identifier.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,57 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "isIdentifierChar", {
enumerable: true,
get: function () {
return _identifier.isIdentifierChar;
}
});
Object.defineProperty(exports, "isIdentifierName", {
enumerable: true,
get: function () {
return _identifier.isIdentifierName;
}
});
Object.defineProperty(exports, "isIdentifierStart", {
enumerable: true,
get: function () {
return _identifier.isIdentifierStart;
}
});
Object.defineProperty(exports, "isKeyword", {
enumerable: true,
get: function () {
return _keyword.isKeyword;
}
});
Object.defineProperty(exports, "isReservedWord", {
enumerable: true,
get: function () {
return _keyword.isReservedWord;
}
});
Object.defineProperty(exports, "isStrictBindOnlyReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictBindOnlyReservedWord;
}
});
Object.defineProperty(exports, "isStrictBindReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictBindReservedWord;
}
});
Object.defineProperty(exports, "isStrictReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictReservedWord;
}
});
var _identifier = require("./identifier.js");
var _keyword = require("./keyword.js");
//# sourceMappingURL=index.js.map

View file

@ -1 +0,0 @@
{"version":3,"names":["_identifier","require","_keyword"],"sources":["../src/index.ts"],"sourcesContent":["export {\n isIdentifierName,\n isIdentifierChar,\n isIdentifierStart,\n} from \"./identifier.ts\";\nexport {\n isReservedWord,\n isStrictBindOnlyReservedWord,\n isStrictBindReservedWord,\n isStrictReservedWord,\n isKeyword,\n} from \"./keyword.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAKA,IAAAC,QAAA,GAAAD,OAAA"}

View file

@ -1,35 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isKeyword = isKeyword;
exports.isReservedWord = isReservedWord;
exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord;
exports.isStrictBindReservedWord = isStrictBindReservedWord;
exports.isStrictReservedWord = isStrictReservedWord;
const reservedWords = {
keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"],
strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"],
strictBind: ["eval", "arguments"]
};
const keywords = new Set(reservedWords.keyword);
const reservedWordsStrictSet = new Set(reservedWords.strict);
const reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
function isReservedWord(word, inModule) {
return inModule && word === "await" || word === "enum";
}
function isStrictReservedWord(word, inModule) {
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
}
function isStrictBindOnlyReservedWord(word) {
return reservedWordsStrictBindSet.has(word);
}
function isStrictBindReservedWord(word, inModule) {
return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);
}
function isKeyword(word) {
return keywords.has(word);
}
//# sourceMappingURL=keyword.js.map

View file

@ -1 +0,0 @@
{"version":3,"names":["reservedWords","keyword","strict","strictBind","keywords","Set","reservedWordsStrictSet","reservedWordsStrictBindSet","isReservedWord","word","inModule","isStrictReservedWord","has","isStrictBindOnlyReservedWord","isStrictBindReservedWord","isKeyword"],"sources":["../src/keyword.ts"],"sourcesContent":["const reservedWords = {\n keyword: [\n \"break\",\n \"case\",\n \"catch\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"return\",\n \"switch\",\n \"throw\",\n \"try\",\n \"var\",\n \"const\",\n \"while\",\n \"with\",\n \"new\",\n \"this\",\n \"super\",\n \"class\",\n \"extends\",\n \"export\",\n \"import\",\n \"null\",\n \"true\",\n \"false\",\n \"in\",\n \"instanceof\",\n \"typeof\",\n \"void\",\n \"delete\",\n ],\n strict: [\n \"implements\",\n \"interface\",\n \"let\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"static\",\n \"yield\",\n ],\n strictBind: [\"eval\", \"arguments\"],\n};\nconst keywords = new Set(reservedWords.keyword);\nconst reservedWordsStrictSet = new Set(reservedWords.strict);\nconst reservedWordsStrictBindSet = new Set(reservedWords.strictBind);\n\n/**\n * Checks if word is a reserved word in non-strict mode\n */\nexport function isReservedWord(word: string, inModule: boolean): boolean {\n return (inModule && word === \"await\") || word === \"enum\";\n}\n\n/**\n * Checks if word is a reserved word in non-binding strict mode\n *\n * Includes non-strict reserved words\n */\nexport function isStrictReservedWord(word: string, inModule: boolean): boolean {\n return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode, but it is allowed as\n * a normal identifier.\n */\nexport function isStrictBindOnlyReservedWord(word: string): boolean {\n return reservedWordsStrictBindSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode\n *\n * Includes non-strict reserved words and non-binding strict reserved words\n */\nexport function isStrictBindReservedWord(\n word: string,\n inModule: boolean,\n): boolean {\n return (\n isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word)\n );\n}\n\nexport function isKeyword(word: string): boolean {\n return keywords.has(word);\n}\n"],"mappings":";;;;;;;;;;AAAA,MAAMA,aAAa,GAAG;EACpBC,OAAO,EAAE,CACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,UAAU,EACV,SAAS,EACT,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,MAAM,EACN,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,QAAQ,CACT;EACDC,MAAM,EAAE,CACN,YAAY,EACZ,WAAW,EACX,KAAK,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,OAAO,CACR;EACDC,UAAU,EAAE,CAAC,MAAM,EAAE,WAAW;AAClC,CAAC;AACD,MAAMC,QAAQ,GAAG,IAAIC,GAAG,CAACL,aAAa,CAACC,OAAO,CAAC;AAC/C,MAAMK,sBAAsB,GAAG,IAAID,GAAG,CAACL,aAAa,CAACE,MAAM,CAAC;AAC5D,MAAMK,0BAA0B,GAAG,IAAIF,GAAG,CAACL,aAAa,CAACG,UAAU,CAAC;AAK7D,SAASK,cAAcA,CAACC,IAAY,EAAEC,QAAiB,EAAW;EACvE,OAAQA,QAAQ,IAAID,IAAI,KAAK,OAAO,IAAKA,IAAI,KAAK,MAAM;AAC1D;AAOO,SAASE,oBAAoBA,CAACF,IAAY,EAAEC,QAAiB,EAAW;EAC7E,OAAOF,cAAc,CAACC,IAAI,EAAEC,QAAQ,CAAC,IAAIJ,sBAAsB,CAACM,GAAG,CAACH,IAAI,CAAC;AAC3E;AAMO,SAASI,4BAA4BA,CAACJ,IAAY,EAAW;EAClE,OAAOF,0BAA0B,CAACK,GAAG,CAACH,IAAI,CAAC;AAC7C;AAOO,SAASK,wBAAwBA,CACtCL,IAAY,EACZC,QAAiB,EACR;EACT,OACEC,oBAAoB,CAACF,IAAI,EAAEC,QAAQ,CAAC,IAAIG,4BAA4B,CAACJ,IAAI,CAAC;AAE9E;AAEO,SAASM,SAASA,CAACN,IAAY,EAAW;EAC/C,OAAOL,QAAQ,CAACQ,GAAG,CAACH,IAAI,CAAC;AAC3B"}

View file

@ -1,28 +0,0 @@
{
"name": "@babel/helper-validator-identifier",
"version": "7.22.20",
"description": "Validate identifier/keywords name",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-helper-validator-identifier"
},
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"exports": {
".": "./lib/index.js",
"./package.json": "./package.json"
},
"devDependencies": {
"@unicode/unicode-15.1.0": "^1.5.2",
"charcodes": "^0.2.0"
},
"engines": {
"node": ">=6.9.0"
},
"author": "The Babel Team (https://babel.dev/team)",
"type": "commonjs"
}

View file

@ -1,73 +0,0 @@
"use strict";
// Always use the latest available version of Unicode!
// https://tc39.github.io/ecma262/#sec-conformance
const version = "15.1.0";
const start = require(
"@unicode/unicode-" + version + "/Binary_Property/ID_Start/code-points.js"
).filter(function (ch) {
return ch > 0x7f;
});
let last = -1;
const cont = require(
"@unicode/unicode-" + version + "/Binary_Property/ID_Continue/code-points.js"
).filter(function (ch) {
return ch > 0x7f && search(start, ch, last + 1) == -1;
});
function search(arr, ch, starting) {
for (let i = starting; arr[i] <= ch && i < arr.length; last = i++) {
if (arr[i] === ch) return i;
}
return -1;
}
function pad(str, width) {
while (str.length < width) str = "0" + str;
return str;
}
function esc(code) {
const hex = code.toString(16);
if (hex.length <= 2) return "\\x" + pad(hex, 2);
else return "\\u" + pad(hex, 4);
}
function generate(chars) {
const astral = [];
let re = "";
for (let i = 0, at = 0x10000; i < chars.length; i++) {
const from = chars[i];
let to = from;
while (i < chars.length - 1 && chars[i + 1] == to + 1) {
i++;
to++;
}
if (to <= 0xffff) {
if (from == to) re += esc(from);
else if (from + 1 == to) re += esc(from) + esc(to);
else re += esc(from) + "-" + esc(to);
} else {
astral.push(from - at, to - from);
at = to;
}
}
return { nonASCII: re, astral: astral };
}
const startData = generate(start);
const contData = generate(cont);
console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierStartChars = "' + startData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierChars = "' + contData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"
);
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"
);

View file

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,19 +0,0 @@
# @babel/highlight
> Syntax highlight JavaScript strings for output in terminals.
See our website [@babel/highlight](https://babeljs.io/docs/babel-highlight) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/highlight
```
or using yarn:
```sh
yarn add @babel/highlight --dev
```

View file

@ -1,105 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = highlight;
exports.shouldHighlight = shouldHighlight;
var _jsTokens = require("js-tokens");
var _helperValidatorIdentifier = require("@babel/helper-validator-identifier");
var _chalk = _interopRequireWildcard(require("chalk"), true);
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
function getDefs(chalk) {
return {
keyword: chalk.cyan,
capitalized: chalk.yellow,
jsxIdentifier: chalk.yellow,
punctuator: chalk.yellow,
number: chalk.magenta,
string: chalk.green,
regex: chalk.magenta,
comment: chalk.grey,
invalid: chalk.white.bgRed.bold
};
}
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
const BRACKET = /^[()[\]{}]$/;
let tokenize;
{
const JSX_TAG = /^[a-z][\w-]*$/i;
const getTokenType = function (token, offset, text) {
if (token.type === "name") {
if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isStrictReservedWord)(token.value, true) || sometimesKeywords.has(token.value)) {
return "keyword";
}
if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) == "</")) {
return "jsxIdentifier";
}
if (token.value[0] !== token.value[0].toLowerCase()) {
return "capitalized";
}
}
if (token.type === "punctuator" && BRACKET.test(token.value)) {
return "bracket";
}
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
return "punctuator";
}
return token.type;
};
tokenize = function* (text) {
let match;
while (match = _jsTokens.default.exec(text)) {
const token = _jsTokens.matchToToken(match);
yield {
type: getTokenType(token, match.index, text),
value: token.value
};
}
};
}
function highlightTokens(defs, text) {
let highlighted = "";
for (const {
type,
value
} of tokenize(text)) {
const colorize = defs[type];
if (colorize) {
highlighted += value.split(NEWLINE).map(str => colorize(str)).join("\n");
} else {
highlighted += value;
}
}
return highlighted;
}
function shouldHighlight(options) {
return _chalk.default.level > 0 || options.forceColor;
}
let chalkWithForcedColor = undefined;
function getChalk(forceColor) {
if (forceColor) {
var _chalkWithForcedColor;
(_chalkWithForcedColor = chalkWithForcedColor) != null ? _chalkWithForcedColor : chalkWithForcedColor = new _chalk.default.constructor({
enabled: true,
level: 1
});
return chalkWithForcedColor;
}
return _chalk.default;
}
{
exports.getChalk = options => getChalk(options.forceColor);
}
function highlight(code, options = {}) {
if (code !== "" && shouldHighlight(options)) {
const defs = getDefs(getChalk(options.forceColor));
return highlightTokens(defs, code);
} else {
return code;
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,29 +0,0 @@
{
"name": "@babel/highlight",
"version": "7.23.4",
"description": "Syntax highlight JavaScript strings for output in terminals.",
"author": "The Babel Team (https://babel.dev/team)",
"homepage": "https://babel.dev/docs/en/next/babel-highlight",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-highlight"
},
"main": "./lib/index.js",
"dependencies": {
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"devDependencies": {
"strip-ansi": "^4.0.0"
},
"engines": {
"node": ">=6.9.0"
},
"type": "commonjs"
}

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Toru Nagashima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,37 +0,0 @@
# @eslint-community/eslint-utils
[![npm version](https://img.shields.io/npm/v/@eslint-community/eslint-utils.svg)](https://www.npmjs.com/package/@eslint-community/eslint-utils)
[![Downloads/month](https://img.shields.io/npm/dm/@eslint-community/eslint-utils.svg)](http://www.npmtrends.com/@eslint-community/eslint-utils)
[![Build Status](https://github.com/eslint-community/eslint-utils/workflows/CI/badge.svg)](https://github.com/eslint-community/eslint-utils/actions)
[![Coverage Status](https://codecov.io/gh/eslint-community/eslint-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/eslint-community/eslint-utils)
## 🏁 Goal
This package provides utility functions and classes for make ESLint custom rules.
For examples:
- [`getStaticValue`](https://eslint-community.github.io/eslint-utils/api/ast-utils.html#getstaticvalue) evaluates static value on AST.
- [`ReferenceTracker`](https://eslint-community.github.io/eslint-utils/api/scope-utils.html#referencetracker-class) checks the members of modules/globals as handling assignments and destructuring.
## 📖 Usage
See [documentation](https://eslint-community.github.io/eslint-utils).
## 📰 Changelog
See [releases](https://github.com/eslint-community/eslint-utils/releases).
## ❤️ Contributing
Welcome contributing!
Please use GitHub's Issues/PRs.
### Development Tools
- `npm test` runs tests and measures coverage.
- `npm run clean` removes the coverage result of `npm test` command.
- `npm run coverage` shows the coverage result of the last `npm test` command.
- `npm run lint` runs ESLint.
- `npm run watch` runs tests on each file change.

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,73 +0,0 @@
{
"name": "@eslint-community/eslint-utils",
"version": "4.4.0",
"description": "Utilities for ESLint plugins.",
"keywords": [
"eslint"
],
"homepage": "https://github.com/eslint-community/eslint-utils#readme",
"bugs": {
"url": "https://github.com/eslint-community/eslint-utils/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint-community/eslint-utils"
},
"license": "MIT",
"author": "Toru Nagashima",
"sideEffects": false,
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js"
},
"./package.json": "./package.json"
},
"main": "index",
"module": "index.mjs",
"files": [
"index.*"
],
"scripts": {
"prebuild": "npm run -s clean",
"build": "rollup -c",
"clean": "rimraf .nyc_output coverage index.*",
"coverage": "opener ./coverage/lcov-report/index.html",
"docs:build": "vitepress build docs",
"docs:watch": "vitepress dev docs",
"format": "npm run -s format:prettier -- --write",
"format:prettier": "prettier .",
"format:check": "npm run -s format:prettier -- --check",
"lint": "eslint .",
"test": "c8 mocha --reporter dot \"test/*.mjs\"",
"preversion": "npm test && npm run -s build",
"postversion": "git push && git push --tags",
"prewatch": "npm run -s clean",
"watch": "warun \"{src,test}/**/*.mjs\" -- npm run -s test:mocha"
},
"dependencies": {
"eslint-visitor-keys": "^3.3.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-mysticatea": "^15.2.0",
"c8": "^7.12.0",
"dot-prop": "^6.0.1",
"eslint": "^8.28.0",
"mocha": "^9.2.2",
"npm-run-all": "^4.1.5",
"opener": "^1.5.2",
"prettier": "2.8.4",
"rimraf": "^3.0.2",
"rollup": "^2.79.1",
"rollup-plugin-sourcemaps": "^0.6.3",
"semver": "^7.3.8",
"vitepress": "^1.0.0-alpha.40",
"warun": "^1.0.0"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
}

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Toru Nagashima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,177 +0,0 @@
# @eslint-community/regexpp
[![npm version](https://img.shields.io/npm/v/@eslint-community/regexpp.svg)](https://www.npmjs.com/package/@eslint-community/regexpp)
[![Downloads/month](https://img.shields.io/npm/dm/@eslint-community/regexpp.svg)](http://www.npmtrends.com/@eslint-community/regexpp)
[![Build Status](https://github.com/eslint-community/regexpp/workflows/CI/badge.svg)](https://github.com/eslint-community/regexpp/actions)
[![codecov](https://codecov.io/gh/eslint-community/regexpp/branch/main/graph/badge.svg)](https://codecov.io/gh/eslint-community/regexpp)
A regular expression parser for ECMAScript.
## 💿 Installation
```bash
$ npm install @eslint-community/regexpp
```
- require Node@^12.0.0 || ^14.0.0 || >=16.0.0.
## 📖 Usage
```ts
import {
AST,
RegExpParser,
RegExpValidator,
RegExpVisitor,
parseRegExpLiteral,
validateRegExpLiteral,
visitRegExpAST
} from "@eslint-community/regexpp"
```
### parseRegExpLiteral(source, options?)
Parse a given regular expression literal then make AST object.
This is equivalent to `new RegExpParser(options).parseLiteral(source)`.
- **Parameters:**
- `source` (`string | RegExp`) The source code to parse.
- `options?` ([`RegExpParser.Options`]) The options to parse.
- **Return:**
- The AST of the regular expression.
### validateRegExpLiteral(source, options?)
Validate a given regular expression literal.
This is equivalent to `new RegExpValidator(options).validateLiteral(source)`.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `options?` ([`RegExpValidator.Options`]) The options to validate.
### visitRegExpAST(ast, handlers)
Visit each node of a given AST.
This is equivalent to `new RegExpVisitor(handlers).visit(ast)`.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
### RegExpParser
#### new RegExpParser(options?)
- **Parameters:**
- `options?` ([`RegExpParser.Options`]) The options to parse.
#### parser.parseLiteral(source, start?, end?)
Parse a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"/abc/g"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression.
#### parser.parsePattern(source, start?, end?, flags?)
Parse a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"abc"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
- **Return:**
- The AST of the regular expression pattern.
#### parser.parseFlags(source, start?, end?)
Parse a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"gim"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression flags.
### RegExpValidator
#### new RegExpValidator(options)
- **Parameters:**
- `options` ([`RegExpValidator.Options`]) The options to validate.
#### validator.validateLiteral(source, start, end)
Validate a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
#### validator.validatePattern(source, start, end, flags)
Validate a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
#### validator.validateFlags(source, start, end)
Validate a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
### RegExpVisitor
#### new RegExpVisitor(handlers)
- **Parameters:**
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
#### visitor.visit(ast)
Validate a regular expression literal.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
## 📰 Changelog
- [GitHub Releases](https://github.com/eslint-community/regexpp/releases)
## 🍻 Contributing
Welcome contributing!
Please use GitHub's Issues/PRs.
### Development Tools
- `npm test` runs tests and measures coverage.
- `npm run build` compiles TypeScript source code to `index.js`, `index.js.map`, and `index.d.ts`.
- `npm run clean` removes the temporary files which are created by `npm test` and `npm run build`.
- `npm run lint` runs ESLint.
- `npm run update:test` updates test fixtures.
- `npm run update:ids` updates `src/unicode/ids.ts`.
- `npm run watch` runs tests with `--watch` option.
[`AST.Node`]: src/ast.ts#L4
[`RegExpParser.Options`]: src/parser.ts#L743
[`RegExpValidator.Options`]: src/validator.ts#L220
[`RegExpVisitor.Handlers`]: src/visitor.ts#L291

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,93 +0,0 @@
{
"name": "@eslint-community/regexpp",
"version": "4.10.0",
"description": "Regular expression parser for ECMAScript.",
"keywords": [
"regexp",
"regular",
"expression",
"parser",
"validator",
"ast",
"abstract",
"syntax",
"tree",
"ecmascript",
"es2015",
"es2016",
"es2017",
"es2018",
"es2019",
"es2020",
"es2021",
"annexB"
],
"homepage": "https://github.com/eslint-community/regexpp#readme",
"bugs": {
"url": "https://github.com/eslint-community/regexpp/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint-community/regexpp"
},
"license": "MIT",
"author": "Toru Nagashima",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.mjs",
"default": "./index.js"
},
"./package.json": "./package.json"
},
"main": "index",
"files": [
"index.*"
],
"scripts": {
"prebuild": "npm run -s clean",
"build": "run-s build:*",
"build:tsc": "tsc --module es2015",
"build:rollup": "rollup -c",
"build:dts": "npm run -s build:tsc -- --removeComments false && dts-bundle --name @eslint-community/regexpp --main .temp/index.d.ts --out ../index.d.ts && prettier --write index.d.ts",
"clean": "rimraf .temp index.*",
"lint": "eslint . --ext .ts",
"test": "nyc _mocha \"test/*.ts\" --reporter dot --timeout 10000",
"debug": "mocha --require ts-node/register/transpile-only \"test/*.ts\" --reporter dot --timeout 10000",
"update:test": "ts-node scripts/update-fixtures.ts",
"update:unicode": "run-s update:unicode:*",
"update:unicode:ids": "ts-node scripts/update-unicode-ids.ts",
"update:unicode:props": "ts-node scripts/update-unicode-properties.ts",
"update:test262:extract": "ts-node -T scripts/extract-test262.ts",
"preversion": "npm test && npm run -s build",
"postversion": "git push && git push --tags",
"prewatch": "npm run -s clean",
"watch": "_mocha \"test/*.ts\" --require ts-node/register --reporter dot --timeout 10000 --watch-extensions ts --watch --growl"
},
"dependencies": {},
"devDependencies": {
"@eslint-community/eslint-plugin-mysticatea": "^15.5.1",
"@rollup/plugin-node-resolve": "^14.1.0",
"@types/eslint": "^8.44.3",
"@types/jsdom": "^16.2.15",
"@types/mocha": "^9.1.1",
"@types/node": "^12.20.55",
"dts-bundle": "^0.7.3",
"eslint": "^8.50.0",
"js-tokens": "^8.0.2",
"jsdom": "^19.0.0",
"mocha": "^9.2.2",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.79.1",
"rollup-plugin-sourcemaps": "^0.6.3",
"test262": "git+https://github.com/tc39/test262.git",
"test262-stream": "^1.4.0",
"ts-node": "^10.9.1",
"typescript": "~5.0.2"
},
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
}

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) Denis Malinochkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,171 +0,0 @@
# @nodelib/fs.scandir
> List files and directories inside the specified directory.
## :bulb: Highlights
The package is aimed at obtaining information about entries in the directory.
* :moneybag: Returns useful information: `name`, `path`, `dirent` and `stats` (optional).
* :gear: On Node.js 10.10+ uses the mechanism without additional calls to determine the entry type. See [`old` and `modern` mode](#old-and-modern-mode).
* :link: Can safely work with broken symbolic links.
## Install
```console
npm install @nodelib/fs.scandir
```
## Usage
```ts
import * as fsScandir from '@nodelib/fs.scandir';
fsScandir.scandir('path', (error, stats) => { /* … */ });
```
## API
### .scandir(path, [optionsOrSettings], callback)
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path with standard callback-style.
```ts
fsScandir.scandir('path', (error, entries) => { /* … */ });
fsScandir.scandir('path', {}, (error, entries) => { /* … */ });
fsScandir.scandir('path', new fsScandir.Settings(), (error, entries) => { /* … */ });
```
### .scandirSync(path, [optionsOrSettings])
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path.
```ts
const entries = fsScandir.scandirSync('path');
const entries = fsScandir.scandirSync('path', {});
const entries = fsScandir.scandirSync(('path', new fsScandir.Settings());
```
#### path
* Required: `true`
* Type: `string | Buffer | URL`
A path to a file. If a URL is provided, it must use the `file:` protocol.
#### optionsOrSettings
* Required: `false`
* Type: `Options | Settings`
* Default: An instance of `Settings` class
An [`Options`](#options) object or an instance of [`Settings`](#settingsoptions) class.
> :book: When you pass a plain object, an instance of the `Settings` class will be created automatically. If you plan to call the method frequently, use a pre-created instance of the `Settings` class.
### Settings([options])
A class of full settings of the package.
```ts
const settings = new fsScandir.Settings({ followSymbolicLinks: false });
const entries = fsScandir.scandirSync('path', settings);
```
## Entry
* `name` — The name of the entry (`unknown.txt`).
* `path` — The path of the entry relative to call directory (`root/unknown.txt`).
* `dirent` — An instance of [`fs.Dirent`](./src/types/index.ts) class. On Node.js below 10.10 will be emulated by [`DirentFromStats`](./src/utils/fs.ts) class.
* `stats` (optional) — An instance of `fs.Stats` class.
For example, the `scandir` call for `tools` directory with one directory inside:
```ts
{
dirent: Dirent { name: 'typedoc', /* … */ },
name: 'typedoc',
path: 'tools/typedoc'
}
```
## Options
### stats
* Type: `boolean`
* Default: `false`
Adds an instance of `fs.Stats` class to the [`Entry`](#entry).
> :book: Always use `fs.readdir` without the `withFileTypes` option. ??TODO??
### followSymbolicLinks
* Type: `boolean`
* Default: `false`
Follow symbolic links or not. Call `fs.stat` on symbolic link if `true`.
### `throwErrorOnBrokenSymbolicLink`
* Type: `boolean`
* Default: `true`
Throw an error when symbolic link is broken if `true` or safely use `lstat` call if `false`.
### `pathSegmentSeparator`
* Type: `string`
* Default: `path.sep`
By default, this package uses the correct path separator for your OS (`\` on Windows, `/` on Unix-like systems). But you can set this option to any separator character(s) that you want to use instead.
### `fs`
* Type: [`FileSystemAdapter`](./src/adapters/fs.ts)
* Default: A default FS methods
By default, the built-in Node.js module (`fs`) is used to work with the file system. You can replace any method with your own.
```ts
interface FileSystemAdapter {
lstat?: typeof fs.lstat;
stat?: typeof fs.stat;
lstatSync?: typeof fs.lstatSync;
statSync?: typeof fs.statSync;
readdir?: typeof fs.readdir;
readdirSync?: typeof fs.readdirSync;
}
const settings = new fsScandir.Settings({
fs: { lstat: fakeLstat }
});
```
## `old` and `modern` mode
This package has two modes that are used depending on the environment and parameters of use.
### old
* Node.js below `10.10` or when the `stats` option is enabled
When working in the old mode, the directory is read first (`fs.readdir`), then the type of entries is determined (`fs.lstat` and/or `fs.stat` for symbolic links).
### modern
* Node.js 10.10+ and the `stats` option is disabled
In the modern mode, reading the directory (`fs.readdir` with the `withFileTypes` option) is combined with obtaining information about its entries. An additional call for symbolic links (`fs.stat`) is still present.
This mode makes fewer calls to the file system. It's faster.
## Changelog
See the [Releases section of our GitHub project](https://github.com/nodelib/nodelib/releases) for changelog for each release version.
## License
This software is released under the terms of the MIT license.

View file

@ -1,20 +0,0 @@
import type * as fsStat from '@nodelib/fs.stat';
import type { Dirent, ErrnoException } from '../types';
export interface ReaddirAsynchronousMethod {
(filepath: string, options: {
withFileTypes: true;
}, callback: (error: ErrnoException | null, files: Dirent[]) => void): void;
(filepath: string, callback: (error: ErrnoException | null, files: string[]) => void): void;
}
export interface ReaddirSynchronousMethod {
(filepath: string, options: {
withFileTypes: true;
}): Dirent[];
(filepath: string): string[];
}
export declare type FileSystemAdapter = fsStat.FileSystemAdapter & {
readdir: ReaddirAsynchronousMethod;
readdirSync: ReaddirSynchronousMethod;
};
export declare const FILE_SYSTEM_ADAPTER: FileSystemAdapter;
export declare function createFileSystemAdapter(fsMethods?: Partial<FileSystemAdapter>): FileSystemAdapter;

View file

@ -1,19 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0;
const fs = require("fs");
exports.FILE_SYSTEM_ADAPTER = {
lstat: fs.lstat,
stat: fs.stat,
lstatSync: fs.lstatSync,
statSync: fs.statSync,
readdir: fs.readdir,
readdirSync: fs.readdirSync
};
function createFileSystemAdapter(fsMethods) {
if (fsMethods === undefined) {
return exports.FILE_SYSTEM_ADAPTER;
}
return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods);
}
exports.createFileSystemAdapter = createFileSystemAdapter;

View file

@ -1,4 +0,0 @@
/**
* IS `true` for Node.js 10.10 and greater.
*/
export declare const IS_SUPPORT_READDIR_WITH_FILE_TYPES: boolean;

View file

@ -1,17 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0;
const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.');
if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) {
throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);
}
const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10);
const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10);
const SUPPORTED_MAJOR_VERSION = 10;
const SUPPORTED_MINOR_VERSION = 10;
const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION;
const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION;
/**
* IS `true` for Node.js 10.10 and greater.
*/
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR;

View file

@ -1,12 +0,0 @@
import type { FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod } from './adapters/fs';
import * as async from './providers/async';
import Settings, { Options } from './settings';
import type { Dirent, Entry } from './types';
declare type AsyncCallback = async.AsyncCallback;
declare function scandir(path: string, callback: AsyncCallback): void;
declare function scandir(path: string, optionsOrSettings: Options | Settings, callback: AsyncCallback): void;
declare namespace scandir {
function __promisify__(path: string, optionsOrSettings?: Options | Settings): Promise<Entry[]>;
}
declare function scandirSync(path: string, optionsOrSettings?: Options | Settings): Entry[];
export { scandir, scandirSync, Settings, AsyncCallback, Dirent, Entry, FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod, Options };

Some files were not shown because too many files have changed in this diff Show more