CompilerDev 板


LINE

※ 引述《Matz (void (*一资米)())》之铭言: : 各位前辈大神好。 : 本鲁最近想自己写一个精简C语言的编译器。 : 看惹很多书,但都感觉有点拿以下手,中间卡住超多次。 : 最近看到C4 C in four function,程式码很少大概500多行而已。 : 想问C4拿来入门合适吗??? 安安 小弟私立科大学店生,误信对岸知乎 「程序员的三大浪漫」 https://www.zhihu.com/question/27323148 抄了jserv大大的MazuCC,然後到处抄,什麽都抄一点,然後再加上自己的劣化,最後生 出了一陀不三不四的东西,然後我还拿去骗惹毕业专题 虽然我八成以後不会再写编译器惹,但还是整理一下抄编译的流程八 首先实作编译器很简单,分三个部份,词汇分析器、语法分析器、程式码产生器 概念的部份可以看这个 https://www.youtube.com/watch?v=4LZkf64APx8
完全不懂的情况下「编译器概念」这一节能大概知道什麽是编译器 然後看完这个,词汇分析器大概就完成了,反正我的程式最後开放四个函式 int is_punct(token *tok, int c); /*判断tok是否是punct且符合c*/ void unget_token(token *tok); /*将tok还回去*/ token *peek_token(void); /*预先得知下个token,但不读入*/ token *read_token(void); /*读入下个token*/ 细节和功能边做边想就好了 然後语法分析器,可以跳着看和边看边睡对岸的开放式课程,作为参考 https://www.bilibili.com/video/av17404276/ 然後语法当然不可能自己设计,所以继续抄,有人已经整理好了C语言的BNF 既然是从The C programming language, 2nd整理出来的,那应该和C89差不远 https://reurl.cc/V6Z22Y 再来就是看jserv大大的MazuCC https://github.com/jserv/MazuCC 可以跪着看,如果膝盖会痛,可以休息一下再继续跪 我自己写的编译器,list.h直接抄,typedef struct __Ast也直接抄 其他部份虽然名义上没抄,但实际上大概就像写数学想半天写不出来,然後去看後面解答 一样 如果前面看开放式课程没有睡的很死,那应该会知道,里面实作解析运算子的方法是LR的 运算子优先序解析器 static int priority(const Token tok) { switch (get_punct(tok)) { case '[': case '.': case PUNCT_ARROW: return 1; case PUNCT_INC: case PUNCT_DEC: return 2; case '*': case '/': return 3; case '+': case '-': return 4; case PUNCT_LSHIFT: case PUNCT_RSHIFT: return 5; case '<': case '>': return 6; case '&': return 8; case '|': return 10; case PUNCT_EQ: return 7; case PUNCT_LOGAND: return 11; case PUNCT_LOGOR: return 12; case '?': return 13; case '=': return 14; default: return -1; } } 因为LR解析器我从来都没有看懂过,所以去瞄了一眼放在MazuCC简介的8cc原始码 https://github.com/rui314/8cc 好的,是LL的递回下降解析器 基本上就是把BNF的C语法直接转成程式码,一层一层的递回下去 恩,看的懂,那就选这个八,所以全部改写成递回下降的形式(原来连这个都是抄的) 像是 <conditional-expression> ::= <logical-or-expression> | <logical-or-expression> ? <expression> : <conditional-expression> <logical-or-expression> ::= <logical-and-expression> | <logical-or-expression> || <logical-and-expression> <logical-and-expression> ::= <inclusive-or-expression> | <logical-and-expression> && <inclusive-or-expression> <inclusive-or-expression> ::= <exclusive-or-expression> | <inclusive-or-expression> | <exclusive-or-expression> <exclusive-or-expression> ::= <and-expression> | <exclusive-or-expression> ^ <and-expression> <and-expression> ::= <equality-expression> | <and-expression> & <equality-expression> <equality-expression> ::= <relational-expression> | <equality-expression> == <relational-expression> | <equality-expression> != <relational-expression> 给个图 https://i.imgur.com/NtOmOxL.png 就能写成 static Ast *conditional_expr() { Ast *ast = logical_or_expr(); token *tok = read_token(); if(is_punct(tok, '?')) { Ast *r = expr(); token *rtok = read_token(); if(!is_punct(rtok, ':')) error("next is ':' "); Ast *l = conditional_expr(); r = ast_binop(rtok->punct, r, l); return ast_binop(tok->punct, ast, r); } unget_token(tok); return ast; } static Ast *logical_or_expr() { Ast *ast = logical_and_expr(); token *tok = read_token(); while(is_punct(tok, PUNCT_LOGOR)) { ast = ast_binop(tok->punct, ast, logical_and_expr()); tok = read_token(); } unget_token(tok); return ast; } static Ast *logical_and_expr() { Ast *ast = inclusive_or_expr(); token *tok = read_token(); while(is_punct(tok, PUNCT_LOGAND)) { ast = ast_binop(tok->punct, ast, inclusive_or_expr()); tok = read_token(); } unget_token(tok); return ast; } static Ast *inclusive_or_expr() { Ast *ast = exclusive_or_expr(); token *tok = read_token(); while(is_punct(tok, '|')) { ast = ast_binop(tok->punct, ast, exclusive_or_expr()); tok = read_token(); } unget_token(tok); return ast; } static Ast *exclusive_or_expr() { Ast *ast = and_expr(); token *tok = read_token(); while(is_punct(tok, '^')) { ast = ast_binop(tok->punct, ast, and_expr()); tok = read_token(); } unget_token(tok); return ast; } static Ast *and_expr() { Ast *ast = equality_expr(); token *tok = read_token(); while(is_punct(tok, '&')) { ast = ast_binop(tok->punct, ast, equality_expr()); tok = read_token(); } unget_token(tok); return ast; } static Ast *equality_expr() { Ast *ast = relational_expr(); token *tok = read_token(); while(is_punct(tok, PUNCT_EQ) || is_punct(tok, PUNCT_NE)) { ast = ast_binop(tok->punct, ast, relational_expr()); tok = read_token(); } unget_token(tok); return ast; } 484简单很多 然後写到这里大概会发现,恩,全部都能用Lex和yacc完成呢~,原理一样,成果一样, 不一样的只是他是自动的,你是手动的(笑 然後陷入了某种无力感,隔了几天接受了这个事实,然後继续写八 再来就是C语言的精随指标和阵列拉 因为是精随,所以你要懂一点点C语言才能写出来 建议去看jserv大大的「你所不知道的C语言」系列讲座 https://hackmd.io/@sysprog/c-prog/%2F%40sysprog%2Fc-programming 通常我是听不懂,但只要开着直播,就能感受到经验值往上涨 然後是《C专家编程》(Expert C Programming: Deep C Secrets) 因为英文很烂,所以我就看简中版,可以当故事书看,轻松有趣 其中的一些故事可以对C的指标有更深入的理解 看完之後有总结出一些规律拉,大概是这样 https://i.imgur.com/dXluSNc.png 指标解析方向由中间开始,然後是右边、左边 不知道对不对拉,不过目前都还能当人肉cdecl还蛮爽的 然後你会发现一件事,就是关於type的问题 阵列在运算式中会强制表示为指标+偏移的形式,但偏移的单位是「指标指向type的大小 」 例如 int a[2][3]; 在运算式中a[1][1]会表示成 *(*(a + 1) + 2)_ a就会加上sizeof(int) * 3 * 1个单位再加上sizeof(int) * 1 * 2个单位 也就是说在AST中表示成这样 * | + / \ * 2 | + / \ a 1 但是a和1相加的时候,可以明确知道a的type,但*和2相加的时候,就不知道a的type了 所以需要将type往上传让其他节点也拥有type的资讯,这样在*与2相加的时候,就能知道 要偏移sizeof(int) * 1 * 2 那要如何将变数往上传?喔,首先你要在运算的时候得知他当初宣告时的type,这需要一 个symbol table,然後其他的我直接抄MazuCC了嘻嘻 然後就是程式码产生器,我的程式码产生器产生两种目标语言 一种是Mano machine的组合语言,另一种是S-expression Mano machine是一个教学用的计算机结构 https://en.wikipedia.org/wiki/Mano_machine 为什麽选这个?因为我在旧书店买到了这本书阿 https://i.imgur.com/emCYran.jpg 然後自己学了好几章 我一直觉得组合语言不是人写的,所以一直想要一个编译器,难得有机会当然要做做看 然後是S-expression,这是我又听信知乎 https://www.zhihu.com/question/26549715/answer/34336593 跑去买了SICP的中译本,然後看了几节SICP的影片,虽然最後还是没学会 只学会了 https://i.imgur.com/BBHdDlN.jpg 不过还是有所启发,所以写了S表达式的程式码产生器 例如 int main() { int sum = 0; for(int i = 0; i < 10; i++) sum = sum + i; return sum; } 可以产生出这样的形式 (AST_FUNC (main (int)) (AST_DECL (= ((int) sum) 0)) (AST_FOR (INIT (AST_DECL (= ((int) i) 0))) (COND (< ((int) i) 10)) (STEP (++ ((int) i))) (BODY (= ((int) sum) (+ ((int) sum) ((int) i))))) (AST_RETURN ((int) sum))) 当然输出的都是没排版的,这时可以写一个简单的排版程式,和编译器有点像 然後组合语言产生器吗.......就组合语言产生器阿 选的组合语言不要太简单,像是我选的就太简单的,很多指令要另外写副程式 像是PUSH和POP要自己写,还因为没办法把PC的值抓出来(只有呼叫副程式的只能碰到PC) ,所以要用很迂回的手法才能抓到PC 然後也要有symbol table,因为你前面宣告,後面要用,除了要判断变数是否存在,还要 知道区域变数与BP的偏移位置 再来要对lvalue有概念,第一次写的时候以为我有概念,但写出来的扣说我没概念 重写的时候我以为我有概念了,但写到後来发现我好像搞错了什麽?因为扣比第一次简单 很多,而且快到deadline了,所以我现在还在想我搞错什麽? 大概是这样 这版的大大的程度应该都高我很多,我的学习历程应该没什麽参考性 如果有错或冒犯到大大,请多见谅 会写出来只是报告还没做完+深夜情绪 做这个花了我七、八个月,前面几个月常常「陷入我是谁?我要做什麽?」的状态 然後中间遇到问题没人可以问,只能自己找资料,也不知道找到的资料有没有用(当然也 是我个性的问题拉,不擅长社交,只在讨论区问问题,强者我朋友遇到同样的问题可能会 直接私讯大大八:P) 还有没人监督+没明确截止日+糟糕的时间管理的随意浪费时间 虽然对未来找工作没什麽帮助,没有强到不看学历那就只看学历,以我私立科大的学历, 第一份工作八成不到30K 业界最多工作还是web,对我这种能拿出来现的只有一点计算机冷知识和C语言,还是去学 比较实用的技术八:P 最後人还是要脚踏实地,不要被浪漫冲昏头,虽然真的很浪漫就是了 https://www.zhihu.com/question/27323148/answer/36153626 -- https://youtu.be/o6-na8AVSqI
天.....天才 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.126.202.172 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/CompilerDev/M.1592682144.A.C8B.html ※ 编辑: wei115 (59.126.202.172 台湾), 06/21/2020 03:59:40 ※ 编辑: wei115 (59.126.202.172 台湾), 06/21/2020 04:06:49
1F:推 flypaper: 不会什麽都没留下啦 至少你C语言掌握度提高了? 06/21 09:43
2F:→ flypaper: 也证明你可以写个规模不小的程式了 06/21 09:45
3F:推 decheng: 高手推! 06/21 12:17
4F:推 descent: 很厉害了, 我花了一年才有类似成果 06/24 22:13
5F:推 Matz: 真的好猛 07/04 20:57







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Boy-Girl站内搜寻

TOP