235 lines
5.5 KiB
Text
235 lines
5.5 KiB
Text
|
|
|||
|
|
|||
|
#set text(
|
|||
|
font : ("Noto Serif CJK TC"),
|
|||
|
size : 12pt,
|
|||
|
)
|
|||
|
|
|||
|
#show heading: set block(below: 1.5em)
|
|||
|
|
|||
|
#set heading(numbering: "1.")
|
|||
|
|
|||
|
#set align(center)
|
|||
|
#block(
|
|||
|
|
|||
|
[#set text(
|
|||
|
font : ("Noto Serif CJK TC"),
|
|||
|
size : 20pt,
|
|||
|
)
|
|||
|
*Ataabu 語言的實作*
|
|||
|
])
|
|||
|
|
|||
|
|
|||
|
#block(above : 2em,
|
|||
|
[#set text(
|
|||
|
font : ("Noto Serif CJK TC"),
|
|||
|
size : 14pt,
|
|||
|
)
|
|||
|
Tan, Kian-ting
|
|||
|
|
|||
|
#set text(
|
|||
|
font : ("Noto Serif CJK TC"),
|
|||
|
size : 10pt,
|
|||
|
)])
|
|||
|
|
|||
|
#set align(left)
|
|||
|
|
|||
|
|
|||
|
#outline(title:"目錄", indent: auto)
|
|||
|
#pagebreak()
|
|||
|
|
|||
|
#set par(
|
|||
|
first-line-indent: 2em,
|
|||
|
justify: true,
|
|||
|
leading: 1.1em,
|
|||
|
)
|
|||
|
|
|||
|
= 句法解釋
|
|||
|
|
|||
|
以下針對這個語言的句法 (syntax),進行解釋。
|
|||
|
== 語法草稿
|
|||
|
|
|||
|
+ 該語法範例碼如下,AST以後再行生成:
|
|||
|
+ 一些注意事項:
|
|||
|
+ 不支援可變變數
|
|||
|
+ 不支援迴圈
|
|||
|
|
|||
|
#block(
|
|||
|
```
|
|||
|
int x = 10; # 常數定義法,這是註解
|
|||
|
flo y = 10.1 + int2flo(x) / 3.0; # 浮點數
|
|||
|
str name = "John"; # 字串,預設用utf-8
|
|||
|
bool c = True; # 布林值,或是 False
|
|||
|
int x = ({int x -> int : return x + 1;})(5); # gets 6
|
|||
|
|
|||
|
'''
|
|||
|
這是多行註解
|
|||
|
函數上面的多行註解會轉成 docString,先用 markdown 做子語言吧;
|
|||
|
底下爲列表和陣列
|
|||
|
'''
|
|||
|
List(int) a_list = [1, 2, 3, 4, 5];
|
|||
|
Array(int) a_array = array!([1, 2, 3, 4, 5]);
|
|||
|
|
|||
|
# 以下是 doc string 的範例,前面要加 @doc:
|
|||
|
@doc '''
|
|||
|
# Desc
|
|||
|
find the sqrt sum of x and y
|
|||
|
|
|||
|
# Args
|
|||
|
- x : lfs value
|
|||
|
- y : rhs value
|
|||
|
|
|||
|
# Eg
|
|||
|
sqrtsum(3, 4) == 25; # True
|
|||
|
'''
|
|||
|
fn sqrtSum = int x, int y -> int :
|
|||
|
int z = x ** 2 + y ** 2;
|
|||
|
return z;
|
|||
|
|
|||
|
fn isJohn = str s -> bool :
|
|||
|
return case {
|
|||
|
#print! 是巨集。!結尾是巨集名稱。 ++ 是字串相加
|
|||
|
s == john -> {print!("Hi, " ++ s ++ "!\n");
|
|||
|
True;}
|
|||
|
else -> False;
|
|||
|
};
|
|||
|
|
|||
|
#不返回值(void)的時候也要標註 return;
|
|||
|
fn printCat = void -> void :
|
|||
|
print!("cat!");
|
|||
|
return ;
|
|||
|
|
|||
|
# 多型:
|
|||
|
# @{} vars of Type with constraints
|
|||
|
fn map = @(A, B : Any) # or @(A, B in Any)
|
|||
|
(List A) origList; ( A -> B ) aFunction -> (List B) :
|
|||
|
return match origList{
|
|||
|
[] -> origList;
|
|||
|
[x:xs] -> cons(aFunction(origList),
|
|||
|
map(origList[1:], aFunction));
|
|||
|
};
|
|||
|
|
|||
|
# 定義自定型別:
|
|||
|
type Person = Person(str name, int age);
|
|||
|
type Person = Person(str , int );
|
|||
|
type TrafficLight = Red | Yellow | Green;
|
|||
|
type List a = @(a : Any) Nil | Cons(a, List(a));
|
|||
|
|
|||
|
Person peter = Person{"Peter", 17};
|
|||
|
|
|||
|
print!(peter.name); # print "Peter"
|
|||
|
|
|||
|
debug!(peter); #印出 Person{name : "Peter", age : 17}這樣。
|
|||
|
|
|||
|
str myNameIsPeter = match peter
|
|||
|
{
|
|||
|
"Peter" _ -> "Is Peter ainm dom",
|
|||
|
_ _ -> "Ní Peter ainm dom"
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
str t = peter.name[5];
|
|||
|
|
|||
|
#分行字串
|
|||
|
str multilineString = '''
|
|||
|
jumps over the lazy dog.
|
|||
|
'''
|
|||
|
|
|||
|
# 將peter的內容克隆一份,然後屬性name改成"John",傳予john
|
|||
|
Person john = peter[name <- "John"];
|
|||
|
```)
|
|||
|
|
|||
|
|
|||
|
#block(```
|
|||
|
@lang DSL # 匯入語言
|
|||
|
import datetime; #匯入模組
|
|||
|
importPath "/path/to/file.toy" #匯入路徑程式檔
|
|||
|
|
|||
|
|
|||
|
@doc '''
|
|||
|
這是給模組的 @doc,表示資訊
|
|||
|
'''
|
|||
|
|
|||
|
```)
|
|||
|
|
|||
|
== 語法生成文法
|
|||
|
|
|||
|
以下用類似 BNF 文法來表示這個玩具語言:
|
|||
|
|
|||
|
- `a{n}` 表示a出現n次
|
|||
|
- `a?` 表示a出現0,1次
|
|||
|
- `a*` 表示a出現0次以上
|
|||
|
- `a+` 表示a出現1次以上
|
|||
|
- `#` 註解
|
|||
|
- `\x` 脫逸字元 \x
|
|||
|
- `ID` identifier
|
|||
|
- `(not a [b…])` 不是 a (, b…) 的字元,方括號[]內表示非必要,可選。
|
|||
|
- `ASCII_SPACE` : Ascii 的半形空白字元
|
|||
|
- `CHAR`:任意字元
|
|||
|
- `$`:指1個以上空白或縮排字元。
|
|||
|
- `$*`:指0個以上空白或縮排字元。
|
|||
|
|
|||
|
`
|
|||
|
ALL = LANG_HEADER? EMPTY_LINE* IMPORTS? EMPTY_LINE* (DOCSTRING)? BODY # 所有的內容
|
|||
|
|
|||
|
#匯入
|
|||
|
IMPORTS = IMPORT {EMPTY_LINE* IMPORT}+
|
|||
|
IMPORT = IMPORTLIB $ NL | IMPORT_PATH $ NL
|
|||
|
IMPORTLIB = import $ ID # 匯入自函式庫
|
|||
|
IMPORT_PATH = importPath $ ( $ " NON_EMPTY_STRING " $ ) #匯入自檔案路徑
|
|||
|
|
|||
|
#定義DSL
|
|||
|
LANG_HEADER = # $ lang $ ID #使用語言的模式
|
|||
|
|
|||
|
# 定義DocumentString
|
|||
|
DOCSTRING = @ $ doc $ DOCSTR_CONTENT
|
|||
|
|
|||
|
#定義DocumentString的細部。本段放在另一個解析器,x = anotherParser(DOCSTRCONTENT)
|
|||
|
DOCSTR_CONTENT = ''' NL # $ DOCSTR_SECTION $ NL DOCSTR_SECTION_EXPLANATION'''
|
|||
|
DOCSTR_SECTION = ID
|
|||
|
|
|||
|
# docstring的各項解釋,開頭不能用井號
|
|||
|
DOCSTR_SECTION_EXPLANATION = {NON_HASH_CHAR NON_EMPTY_STRING NL}+
|
|||
|
|
|||
|
BODY = BODY_LINE*
|
|||
|
BODY_LINE = INLINE_COMMENT | VAR_DEF | EXPR | TYPE_DEF | MACRO_DEF | EMPTY_LINE
|
|||
|
INLINE_COMMENT = $* # NON_NL_CHAR+ NL
|
|||
|
|
|||
|
VAR_DEF = $* TYPE_ID $ VAR_ID $* = $* EXPR $* ;
|
|||
|
|
|||
|
# Type Definition, eg.
|
|||
|
# type List a = @(a : Any) Nil | Cons(a, List(a));
|
|||
|
TYPE_DEF = Type $ TYPEID $* = $* POLYMOR? $ SUM_TYPE ;
|
|||
|
|
|||
|
SUM_TYPE = PRODUCT_TYPE $* { | $* PRODUCT_TYPE $*}*
|
|||
|
PRODUCT_TYPE = UNIRY_CONSTRUCT | RECORD | STRUCT;
|
|||
|
UNIRY_CONSTRUCT = CONSTRUCT_ID;
|
|||
|
RECORD = CONSTRUCT_ID $* ( $* CONSTRUCT_LIST $* )
|
|||
|
CONSTRUCT_LIST = CONSTRUCT {$*, $* CONSTRUCT}*
|
|||
|
CONSTRUCT = TYPE_VAR TYPE_AUG?
|
|||
|
TYPE_AUG = $* ( $* TYPE_VAR TYPE_AUG_REMAINED* $* )
|
|||
|
TYPE_AUG_REMAINED = $*, $* TYPE_VAR
|
|||
|
|
|||
|
# 定義 structure 和 attribution
|
|||
|
STRUCT = ATTR_ID $* ( $* ATTR_LIST $* )
|
|||
|
ATTR_LIST= ATTR {$*, $* ATTR}+
|
|||
|
ATTR = CONSTRUCT ATTR_ID
|
|||
|
ATTR_ID = ID
|
|||
|
TYPE_ID = ID
|
|||
|
|
|||
|
# 空行
|
|||
|
EMPTY_LINE = SPACE_TAB* NL
|
|||
|
#換行
|
|||
|
NL = \n | \r
|
|||
|
|
|||
|
#非半形井號字元
|
|||
|
NON_HASH_CHAR = (not #)
|
|||
|
|
|||
|
#非換行字元
|
|||
|
NON_NL_CHAR = (not \n \r)
|
|||
|
NON_EMPTY_STRING = CHAR+ #非空串
|
|||
|
EMPTY_STRING = CHAR{0} #空字串
|
|||
|
STRING = NON_EMPTY_STRING | EMPTY_STRING
|
|||
|
SPACE_TAB = ASCII_SPACE | \t #空白與縮排字元,簡稱為 $
|
|||
|
ID = [a-zA-Z_][_a-zA-Z0-9]* # identifier, in regexp
|
|||
|
```
|