{"id":20435808,"url":"https://github.com/zsyty/posfol","last_synced_at":"2026-06-10T07:31:34.729Z","repository":{"id":70496196,"uuid":"370755693","full_name":"ZSYTY/posfol","owner":"ZSYTY","description":null,"archived":false,"fork":false,"pushed_at":"2021-06-13T16:41:09.000Z","size":1222,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-08T15:53:01.264Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZSYTY.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-25T16:16:20.000Z","updated_at":"2021-06-13T17:00:45.000Z","dependencies_parsed_at":"2023-03-11T08:41:24.950Z","dependency_job_id":null,"html_url":"https://github.com/ZSYTY/posfol","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ZSYTY/posfol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZSYTY%2Fposfol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZSYTY%2Fposfol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZSYTY%2Fposfol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZSYTY%2Fposfol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZSYTY","download_url":"https://codeload.github.com/ZSYTY/posfol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZSYTY%2Fposfol/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34142637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T08:37:49.256Z","updated_at":"2026-06-10T07:31:34.710Z","avatar_url":"https://github.com/ZSYTY.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"#### 程序基本元素分解\n\n\u003e   program -\u003e stmts -\u003e stmt \n\n#### 程序分解\n\n\u003ccenter\u003e\u003cimg src=\"./node.png\" /\u003e\u003c/center\u003e\n\n##### declaration\n\n声明：\n\n-   变量声明(variable)：\n    -   纯声明：`int a;`、`A a;`\n    -   声明+定义：`int a = b + 1;`、`A a = new A();`\n-   函数声明(function)：\n    -   纯声明：`int f(int a, int b);`\n    -   声明+定义：`int f(int a, int b){...}`\n-   类声明(class)：\n    -   纯声明：`class A;`\n    -   声明+定义：`class A{...}`\n\n##### expression\n\n表达式：\n\n-   赋值语句：`a = 1;`\n-   基本运算：`a = b + c;`\n-   调用函数：`a = f(b);`\n\n##### statement\n\n语句：\n\n-   if语句：`if cond {...} else {...}`\n-   for语句：`for(...){...}`\n-   while语句：`while(...){...}`\n\n#### 作用域说明\n\n##### scope\n\n作用域：进入if/for/while的{}、function的{}、以及class的{}内，都会得到一个新的local scope，变量的引用从本作用域内到外层再一直到全局作用域为止\n\n#### 词法/语法分析、语义分析、LLVM\n\n\u003e   词法/语法分析相对独立，语义分析和LLVM可以并行做\n\n##### 词法/语法分析\n\n词法分析主要用lex从字符流中生成token，语法分析则是yacc利用BNF表达式将token list转化为AST\n\n注意，此时终结符(如基本变量)作为AST里的基本节点，都已经被赋好了值\n\n##### 语义分析\n\nyacc的{}里的动作属于语义分析：\n\n所有new节点的操作都只能在yacc的{}里做，`node.h`的所有类成员变量都只保存：\n\n-   指向非终结符的指针\n-   终结符的值\n\n以`int f(int a, int b, ...)`为例：\n\n~~~cpp\nclass FunctionDeclaration {\n    Identifier returnType;\n    Identifier func;\n    std::vector\u003cVariableDeclaration*\u003e* paramList;\n}\n~~~\n\nint和f都是终结符，只需要给Identifier赋上type类型和name名称即可\n\n而param list作为一个整体是非终结符，需要用一个BNF的yacc推导来完成，在推导过程中，每个变量声明VariableDeclaration作为一个基本单元(向下还会继续解析，这里不再阐述)，可以看做是一个子树，我们需要返回该子树的root指针，这么些root指针组成一个vector就是param list的子树了，同样的，我们要把param list的子树的root指针返回给FunctionDeclaration节点，因此FunctionDeclaration类中会有`vector\u003cVariableDeclaration*\u003e*`这个成员变量，来接收param list子树\n\n\n\n此外，语义分析还需要对AST进行类型检查，只要保证每条赋值语句、运算语句、函数调用语句的相关变量类型是对的，代码最后必然就能够成功执行\n\n这里我选择用unordered_map来做{name: type}的映射，方便做类型检查，像之前说的，不同作用域下的map不同，需要利用栈结构来保证合理的变量引用\n\n通常有三种类型错误：范围包括变量、函数和类，这里统称为\"对象\"\n\n-   未定义：stack里的map都没有该对象\n\n-   重复定义：stack.top()的map里已经有重名对象，此时为重复定义\n\n    注：若栈顶的map里没有重名对象，但栈内的其他map里存在重名对象，此时栈顶作用域优先，不算重复定义\n\n-   类型不匹配：表达式类型不匹配，如`int a = 1 + \"2\"`\n\n##### LLVM\n\nLLVM负责把AST转化为可执行的目标代码，我们只需要生成LLVM IR即可\n\n注意，词法/语法分析中已经完成了AST，因此即使没有语法分析的类型检查，LLVM这一阶段照样可以进行，故语法分析与LLVM是可以并行开发的\n\n#### Visualization\n\n因为CORS的缘故不能直接打开.html，最简单的办法是在`visualization/`下用`python -m server`建立本地服务器后打开。","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzsyty%2Fposfol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzsyty%2Fposfol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzsyty%2Fposfol/lists"}