语法分析器终于完成了,总共花了7个小时的时间。其中遇到了一些小问题,譬如lambda expression的\param->expression和let-in expression的let declaration-list in expression里面的expression需要尽可能长的解决办法。因为用了Vczh Syngram,所以不得不调整出符合需求的文法。
为了大概看一看文法有没有写对,我写了一个程序,读入
KernelFP语言写的一份代码,将其格式化并输出。
输入代码如下:
1 type int
2 type char
3 type bool = true | false
4 type list T = empty | list T (list T)
5
6 func iadd::int->int->int alias "add"
7 func isub::int->int->int alias "sub"
8 func imul::int->int->int alias "mul"
9 func idiv::int->int->int alias "div"
10 func imod::int->int->int alias "mod"
11 func ilg::int->int->bool alias "ilg"
12 func ism::int->int->bool alias "ism"
13 func iequ::int->int->bool alias "iequ"
14 func chr::int->char alias "chr"
15 func ord::char->int alias "ord"
16
17 func not::bool->bool
18 def not a = select a of
19 case true : false
20 case false : true
21 end
22
23 func and::bool->bool->bool
24 def and a b = select a of
25 case true : b
26 case false : false
27 end
28
29 func or::bool->bool->bool
30 def or a b = select a of
31 case true : true
32 case false : b
33 end
34
35 func xor::bool->bool->bool
36 def xor a b = select a of
37 case true : not b
38 case false : b
39 end
40
41 func T if::bool->T->T
42 def if cond t f = select cond of
43 case true : t
44 case false : f
45 end
46
47 func ineg::int->int
48 def ineg num = isub 0 num
49
50 func coffset::char->int->char
51 def coffset c i = chr (iadd (ord c) i)
52
53 func itoa::int->list char
54 def itoa a = if (iequ a 0) (list '0' empty) (if (ism a 0)
55 (list '-' (itoa (ineg a)))
56 let
57 func _itoa::int->(list char)->(list char)
58 def _itoa a chs = select a of
59 case 0 : chs
60 else : _itoa (div a 10) (list (coffset '0' (mod a 10)) chs)
61 end
62 in _itoa a empty)
63
64 func atoi::list char->int
65 def atoi chs = select chs of
66 case empty : 0
67 case list '-' chs : ineg (atoi chs)
68 case c chs : iadd (imul 10 (isub (ord c) (ord '0'))) (atoi chs)
69 end
输出代码如下:
1 表达式1/1
2 type int
3
4 type char
5
6 type bool = (true | false)
7
8 type list T = (empty | (list T (list T)))
9
10 func iadd :: ((int -> int) -> int) alias "add"
11
12 func isub :: ((int -> int) -> int) alias "sub"
13
14 func imul :: ((int -> int) -> int) alias "mul"
15
16 func idiv :: ((int -> int) -> int) alias "div"
17
18 func imod :: ((int -> int) -> int) alias "mod"
19
20 func ilg :: ((int -> int) -> bool) alias "ilg"
21
22 func ism :: ((int -> int) -> bool) alias "ism"
23
24 func iequ :: ((int -> int) -> bool) alias "iequ"
25
26 func chr :: (int -> char) alias "chr"
27
28 func ord :: (char -> int) alias "ord"
29
30 func not :: (bool -> bool)
31 def not a =
32 select a of
33 case true : false
34 case false : true
35 end
36
37 func and :: ((bool -> bool) -> bool)
38 def and a b =
39 select a of
40 case true : b
41 case false : false
42 end
43
44 func or :: ((bool -> bool) -> bool)
45 def or a b =
46 select a of
47 case true : true
48 case false : b
49 end
50
51 func xor :: ((bool -> bool) -> bool)
52 def xor a b =
53 select a of
54 case true : (not b)
55 case false : b
56 end
57
58 func T if :: ((bool -> T) -> T)
59 def if cond t f =
60 select cond of
61 case true : t
62 case false : f
63 end
64
65 func ineg :: (int -> int)
66 def ineg num = ((isub 0) num)
67
68 func coffset :: ((char -> int) -> char)
69 def coffset c i = (chr ((iadd (ord c)) i))
70
71 func itoa :: (int -> (list char))
72 def itoa a = (((if ((iequ a) 0)) ((list '0') empty)) (((if ((ism a) 0)) ((list '-') (itoa (ineg a))))
73 (let
74 func _itoa :: ((int -> (list char)) -> (list char))
75 def _itoa a chs =
76 select a of
77 case 0 : chs
78 else : ((_itoa ((div a) 10)) ((list ((coffset '0') ((mod a) 10))) chs))
79 end
80 in((_itoa a) empty))))
81
82 func atoi :: ((list char) -> int)
83 def atoi chs =
84 select chs of
85 case empty : 0
86 case ((list '-') chs) : (ineg (atoi chs))
87 case (c chs) : ((iadd ((imul 10) ((isub (ord c)) (ord '0')))) (atoi chs))
88 end
89
今晚和明天要想出一个解决带有模板参数的类型推导的解决办法。因为实际上当你写下
func T1 T2 name::T1->T2
def name a = ....
的时候,T1和T2不一定能够取到所有类型,而且T1和T2也不一定没有关系。所以如果你不写func头的话,一个默认的,不影响语义的func头是可以生成出来的,直接用模板就可以了。所以对于这门最小内核语言来说,这个语法糖是可以省略的。
譬如说:
func T1 T2 T3 makelist :: T1 -> T2 -> T3
def makelist a b = list a (list b empty)
在这个描述下,T1必须跟T2相同,而且T3必须是list T1这种类型。所以,你把函数头改成了func T makelist::T->T->list T,也是丝毫没有影响的。
posted on 2008-10-01 01:31
陈梓瀚(vczh) 阅读(1564)
评论(0) 编辑 收藏 引用 所属分类:
脚本技术