PL0语法,分析器实现!

发布于:2025-06-08 ⋅ 阅读:(17) ⋅ 点赞:(0)

简介

PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。

PL/0 语法规范

PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核心概念。以下是完整的 PL/0 语法规范(使用扩展巴科斯范式 EBNF 描述):

1. 字符集

digit   = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
letter  = "a" | "b" | ... | "z" | "A" | "B" | ... | "Z" ;
symbol  = "+" | "-" | "*" | "/" | "(" | ")" | "=" | "," | "." | ";" | ":" | "<" | ">" | "#" ;

2. 词法单元

ident   = letter { letter | digit } ;             (* 标识符 *)
number  = digit { digit } ;                       (* 无符号整数 *)
operator = "+" | "-" | "*" | "/" | "=" | "#" | "<" | ">" | "<=" | ">=" ; (* 运算符 *)
delimiter = "(" | ")" | "," | "." | ";" | ":" ;   (* 分隔符 *)
keyword = "begin" | "call" | "const" | "do" | "end" | "if" | "odd" | "procedure" 
        | "read" | "then" | "var" | "while" | "write"; (* 关键字 *)

3. 语法结构(EBNF)

程序结构
program = block "." ;  (* 程序由块和句点组成 *)

block = [ "const" ident "=" number {"," ident "=" number} ";" ]
        [ "var" ident {"," ident} ";" ]
        { "procedure" ident ";" block ";" } 
        statement ;  (* 块包含常量/变量声明和过程 *)
语句
statement = [ ident ":=" expression                (* 赋值语句 *)
           | "call" ident                         (* 过程调用 *)
           | "begin" statement { ";" statement } "end"  (* 复合语句 *)
           | "if" condition "then" statement      (* 条件语句 *)
           | "while" condition "do" statement     (* 循环语句 *)
           | "read" ident                         (* 输入语句 *)
           | "write" expression                   (* 输出语句 *)
           | "skip"                               (* 空语句 *)
           ] ;
条件表达式
condition = "odd" expression                     (* 奇偶判断 *)
          | expression ("=" | "#" | "<" | "<=" | ">" | ">=") expression ;  (* 关系运算 *)
算术表达式
expression = [ "+" | "-" ] term { ( "+" | "-" ) term } ;  (* 可带符号的表达式 *)

term = factor { ( "*" | "/" ) factor } ;         (* 项 *)

factor = ident | number | "(" expression ")" ;   (* 因子:标识符/数字/子表达式 *)

4. 语法图示(语法图)

Program
┌───────────────┐
│     Block     │
└──────┬────────┘
       │
       ●
       
Block
┌─────┬───────────┬───────────────┬────────────┐
│const│ Ident = Num│ ( , Ident=Num)│     ;      │
├─────┼───────────┼───────────────┼────────────┤
│ var │  Ident    │ ( , Ident)    │     ;      │
├─────┼───────────┼───────────────┼────────────┤
│ proc│  Ident ;  │    Block      │     ;      │
├─────┴───────────┴───────────────┴────────────┤
│                 Statement                    │
└──────────────────────────────────────────────┘

Statement
┌───────────────────────────────────────────────────────────────────────────────┐
│  ┌───────────┐        ┌─────────┐        ┌─────────┐        ┌────────────┐   │
├──┤ Ident :=  ├──Expr──┤  call   ├─Ident──┤  begin  ├─Stmt─(─┤ ; Stmt )─end│   │
│  └───────────┘        └─────────┘        └─────────┘        └────────────┘   │
│  ┌───────────┐        ┌─────────┐        ┌─────────┐        ┌───────────┐    │
├──┤   if      ├─Cond──┤ then    ├─Stmt──┤  while  ├─Cond──┤ do Stmt    │    │
│  └───────────┘        └─────────┘        └─────────┘        └───────────┘    │
│  ┌───────────┐        ┌───────────┐                                          │
└──┤  read     ├─Ident─┤  write    ├─Expr──┐                                   │
   └───────────┘        └───────────┘      │                                   │
   ┌───────────┐                           │                                   │
   └─── skip ──┘                           │                                   │
   ┌───────────────────────────────────────┘                                   │
   └───────────────────────────────────────────────────────────────────────────┘

5. 语义规则

  1. 作用域规则

    • 嵌套过程结构(最多3层)

    • 静态作用域(词法作用域)

    • 标识符必须先声明后使用

  2. 类型系统

    • 仅支持整数类型

    • 无类型声明(所有变量默认为整数)

  3. 过程调用

    • 无参数传递

    • 递归调用支持(通过栈实现)

    • 最大调用深度由实现决定

6. PL/0 程序示例

const max = 100;
var n, f;

procedure factorial;
begin
    if n <= 1 then
        f := 1
    else begin
        n := n - 1;
        call factorial;
        n := n + 1;
        f := n * f
    end
end;

begin
    read n;
    call factorial;
    write f
end.

7. PL/0 语言特性总结

特性 支持情况 限制
数据类型 仅整数 无浮点数/字符串
控制结构 if-then, while-do 无for循环,无switch
过程 支持嵌套过程 无参数,无返回值
输入输出 read/write 基本I/O 仅控制台操作
数据结构 简单变量 无数组/记录结构
作用域 静态作用域(3层嵌套) 无全局变量
异常处理 运行时错误导致终止

PL/0 的设计体现了编译器的核心组成部分:

  1. 词法分析(识别标识符/数字/关键字)

  2. 语法分析(递归下降法)

  3. 语义分析(符号表管理)

  4. 代码生成(栈式虚拟机指令)

  5. 解释执行(P-code 解释器)

这种精简的设计使其成为学习编译原理的理想教学语言,实际编译器实现通常只需 1000-2000 行代码。

PL/0 语法分析器实现

下面是一个完整的 PL/0 语法分析器实现,使用 JavaScript 构建,包含可视化界面和交互功能。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PL/0 语法分析器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1e3c72, #2a5298);
            color: #f0f0f0;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 25px;
        }
        
        @media (max-width: 768px) {
            .container {
                grid-template-columns: 1fr;
            }
        }
        
        header {
            grid-column: 1 / -1;
            text-align: center;
            padding: 20px 0;
            margin-bottom: 20px;
            border-bottom: 2px solid #4cc9f0;
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            color: #4cc9f0;
            text-shadow: 0 0 10px rgba(76, 201, 240, 0.5);
        }
        
        .subtitle {
            font-size: 1.2rem;
            color: #a1c4fd;
            max-width: 800px;
            margin: 0 auto;
        }
        
        .panel {
            background: rgba(30, 30, 46, 0.8);
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            backd

网站公告

今日签到

点亮在社区的每一天
去签到