zoukankan      html  css  js  c++  java
  • PL/0语言词法分析器

    前言:关于词法分析的基础知识的介绍可以看一下这篇博客,我再累述估计也不会有这篇讲的清楚QAQ。 https://www.cnblogs.com/yanlingyin/archive/2012/04/17/2451717.html    默认大家已经对词法分析有了基本的了解了。

    一:下面讨论PL/0语言的词法分析器的单词结构

    1、关键字     

      关键字(11):空格分隔列表如下

      begin  end  if  then  while  do  const  var  call  procedure  odd

    2、运算符和界符  

      算符和界符(14个):空格分隔列表如下

      +  -  *  /  =  #  <  >  :=  (  )  ,  .  ;

    3、标示符

            PL/0语言中标示符的定义为:开头可以是下划线或字母,后面可以是下划线、字母或数字。

    4、常数

      整形数和浮点数

    5、空白符

      PL/0语言中的空白符有:空格符、制表符、换行符,这些空白符在词法分析阶段可以被忽略。

    6、注释

             PL/0语言中的注释形式为//,可以多行注释(*…*)。

    二:PL/0的语言的词法分析器将要完成以下工作

    (1) 跳过分隔符(如空格,回车,制表符);

    (2) 识别诸如beginendifwhile等关键字;

    (3) 识别非关键字的一般标识符。

    (4) 识别常数数字序列。

    (5) 识别前面列出的单字符操作符和:=双字符特殊符号。

    (6)词法分析器的输出形式(种别,属性值)其中:种别在2、单词的种别”中进行了定义;

                  属性值:若单词种别只代表唯一单词,属性值为空;

                  若单词种别是标识符,为该单词在标识符表中的位置;

                  若单词种别是常数,属性值为对应常数值。

    三:代码实现

    测试程序如下(我放置的路径为D:/b.txt,根据自己情况自行修改)

     1 // PL/0 语法示例程序 
     2 
     3 (*
     4     计算1~10的阶乘
     5     多行注释    
     6 *)
     7 
     8 var n, f;
     9 begin
    10      n := 0;
    11      f := 1;
    12      while n # 10 do
    13      begin
    14           n := n + 1;
    15           f := f * n;
    16      end;
    17      call print;// 用于输出结果,假设预先声明
    18 end.
    View Code

    种别码如下(我放置的路径为D:/a.txt,根据自己情况自行修改)

     1 begin  1
     2 end  2
     3 if  3
     4 then 4
     5 while  5
     6 do  6
     7 const  7
     8 var  8
     9 call  9
    10 procedure  10
    11 odd  11
    12 +  12
    13 -  13
    14 *  14
    15 /  15
    16 =  16
    17 #  17
    18 <  18
    19 >  19
    20 :=  20
    21 (  21
    22 )  22
    23 ,  23
    24 .  24
    25 ;  25
    26 (*多行注释*)    26
    27 //单行注释  27
    28 常数    28
    29 标识符    29
    View Code

    实现代码如下

      1 // pL/0语言词法分析器
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 struct _2tup
      5 {
      6     string token;
      7     int id;
      8 };
      9 bool is_blank(char ch)
     10 {
     11     return ch == ' ' || ch == '    ';//空格或控制字符
     12 }
     13 bool gofor(char& ch, string::size_type& pos, const string& prog)//返回指定位置的字符
     14 {
     15     ++pos;
     16     if (pos >= prog.size())
     17     {
     18         return false;
     19     }
     20     else
     21     {
     22         ch = prog[pos];
     23         return true;
     24     }
     25 }
     26 
     27 _2tup scanner(const string& prog, string::size_type& pos, const map<string, int>& keys, int& row)
     28 {
     29     /*
     30     if
     31         标示符
     32     else if
     33         数字
     34     else
     35         符号
     36     */
     37     _2tup ret;
     38     string token;
     39     int id = 0;
     40 
     41     char ch;
     42     ch = prog[pos];
     43 
     44     while(is_blank(ch))
     45     {
     46         ++pos;
     47         ch = prog[pos];
     48     }
     49     // 判断标示符、关键字
     50     if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')
     51     {
     52         //保证读取一个单词
     53         while((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')
     54         {
     55             token += ch;//追加标示符、关键字
     56             if (!gofor(ch, pos, prog))
     57             {
     58                 break;
     59             }
     60         }
     61         // 这里先看做都是其他标示符
     62         id = keys.size();
     63 
     64         // 验证是否是关键字
     65         map<string, int>::const_iterator cit = keys.find(token);//根据string类型的token返回int类型的id赋值给cit
     66         if (cit != keys.end())
     67         {
     68             id = cit->second;//此时是关键字,记录他的id
     69         }
     70     }
     71     // 识别常数
     72     else if ((ch >= '0' && ch <= '9') || ch == '.')
     73     {
     74         while (ch >= '0' && ch <= '9' || ch == '.')
     75         {
     76             token += ch;
     77             if (!gofor(ch, pos, prog))
     78             {
     79                 break;
     80             }
     81         }
     82         id = keys.size() - 1;
     83         int dot_num = 0;
     84         for (string::size_type i = 0; i != token.size(); ++i)
     85         {
     86             if (token[i] == '.')
     87             {
     88                 ++dot_num;
     89             }
     90         }
     91         if (dot_num > 1)
     92         {
     93             id = -1;
     94         }
     95     }
     96     else
     97     {
     98         map<string, int>::const_iterator cit;
     99         switch (ch)
    100         {
    101         case '-': // - 操作符
    102             token += ch;
    103             if (gofor(ch, pos, prog))
    104             {
    105                 if (ch == '-' || ch == '=' || ch == '>') // -- 操作符
    106                 {
    107                     token += ch;
    108                     gofor(ch, pos, prog);
    109                 }
    110             }
    111             cit = keys.find(token);
    112             if (cit != keys.end())
    113             {
    114                 id = cit->second;
    115             }
    116             break;
    117         case ':':
    118              token += ch;
    119             if (gofor(ch, pos, prog))
    120             {
    121                 if (ch == '=') // -- 操作符
    122                 {
    123                     token += ch;
    124                     gofor(ch, pos, prog);
    125                 }
    126             }
    127             cit = keys.find(token);
    128             if (cit != keys.end())
    129             {
    130                 id = cit->second;
    131             }
    132             break;
    133 
    134         case '=':
    135             token += ch;
    136             if (gofor(ch, pos, prog))
    137             {
    138                 if (ch == '=') // !% %= 操作符
    139                 {
    140                     token += ch;
    141                     gofor(ch, pos, prog);
    142                 }
    143             }
    144             cit = keys.find(token);
    145             if (cit != keys.end())
    146             {
    147                 id = cit->second;
    148             }
    149             break;
    150 
    151         case '/': // / 操作符
    152             token += ch;
    153             if (gofor(ch, pos, prog))
    154             {
    155                 if (ch == '=') // /= 操作符
    156                 {
    157                     token += ch;
    158                     gofor(ch, pos, prog);
    159                 }
    160                 else if (ch == '/') // 单行注释
    161                 {
    162                     token += ch;
    163                     ++pos;
    164                     while (pos < prog.size())
    165                     {
    166                         ch = prog[pos];
    167                         if (ch == '
    ')
    168                         {
    169                             break;
    170                         }
    171                         token += ch;
    172                         ++pos;
    173                     }
    174                     if (pos >= prog.size())
    175                     {
    176                         ;
    177                     }
    178                     else
    179                     {
    180                         ;
    181                     }
    182                     id = keys.size() - 2;
    183                     break;
    184                 }
    185                 else if (ch == '*') // 注释
    186                 {
    187                     token += ch;
    188                     if (!gofor(ch, pos, prog))
    189                     {
    190                         token += "
    !!!注释错误!!!";
    191                         id = -10;
    192                         break;
    193                     }
    194                     if (pos + 1 >= prog.size())
    195                     {
    196                         token += ch;
    197                         token += "
    !!!注释错误!!!";
    198                         id = -10;
    199                         break;
    200                     }
    201                     char xh = prog[pos + 1];
    202                     while (ch != '*' || xh != '/')
    203                     {
    204                         token += ch;
    205                         if (ch == '
    ')
    206                         {
    207                             ++row;
    208                         }
    209                         //++pos;
    210                         if (!gofor(ch, pos, prog))
    211                         {
    212                             token += "
    !!!注释错误!!!";
    213                             id = -10;
    214                             ret.token = token;
    215                             ret.id    = id;
    216                             return ret;
    217                         }
    218                         //ch = prog[pos];
    219                         if (pos + 1 >= prog.size())
    220                         {
    221                             token += ch;
    222                             token += "
    !!!注释错误!!!";
    223                             id = -10;
    224                             ret.token = token;
    225                             ret.id    = id;
    226                             return ret;
    227                         }
    228                         xh = prog[pos + 1];
    229                     }
    230                     token += ch;
    231                     token += xh;
    232                     pos += 2;
    233                     ch = prog[pos];
    234                     id = keys.size() - 2;
    235                     break;
    236                 }
    237             }
    238             cit = keys.find(token);
    239             if (cit != keys.end())
    240             {
    241                 id = cit->second;
    242             }
    243             break;
    244         case '+':
    245             token += ch;
    246             cit = keys.find(token);
    247             if (cit != keys.end())
    248             {
    249                 id = cit->second;
    250             }
    251             gofor(ch, pos, prog);
    252             break;
    253 
    254         case '<':
    255             token += ch;
    256             if (gofor(ch, pos, prog))
    257             {
    258                 if (ch == '<')
    259                 {
    260                     token += ch;
    261                     if (gofor(ch, pos, prog))
    262                     {
    263                         if (ch == '=')
    264                         {
    265                             token += ch;
    266                             gofor(ch, pos, prog);
    267                         }
    268                     }
    269                 }
    270                 else if (ch == '=')
    271                 {
    272                     token += ch;
    273                     gofor(ch, pos, prog);
    274                 }
    275             }
    276             cit = keys.find(token);
    277             if (cit != keys.end())
    278             {
    279                 id = cit->second;
    280             }
    281             break;
    282 
    283         case '>':
    284             token += ch;
    285             if (gofor(ch, pos, prog))
    286             {
    287                 if (ch == '>')
    288                 {
    289                     token += ch;
    290                     if (gofor(ch, pos, prog))
    291                     {
    292                         if (ch == '=')
    293                         {
    294                             token += ch;
    295                             gofor(ch, pos, prog);
    296                         }
    297                     }
    298                 }
    299                 else if (ch == '=')
    300                 {
    301                     token += ch;
    302                     gofor(ch, pos, prog);
    303                 }
    304             }
    305             cit = keys.find(token);
    306             if (cit != keys.end())
    307             {
    308                 id = cit->second;
    309             }
    310             break;
    311          case '(': // / 操作符
    312             token += ch;
    313             if (gofor(ch, pos, prog))
    314 
    315             {
    316                  if (ch == '*') // 注释
    317                 {
    318                     token += ch;
    319                     if (!gofor(ch, pos, prog))
    320                     {
    321                         token += "
    !!!注释错误!!!";
    322                         id = -10;
    323                         break;
    324                     }
    325                     if (pos + 1 >= prog.size())
    326                     {
    327                         token += ch;
    328                         token += "
    !!!注释错误!!!";
    329                         id = -10;
    330                         break;
    331                     }
    332                     char xh = prog[pos + 1];
    333                     while (ch != '*' || xh != ')')
    334                     {
    335                         token += ch;
    336                         if (ch == '
    ')
    337                         {
    338                             ++row;
    339                         }
    340                         //++pos;
    341                         if (!gofor(ch, pos, prog))
    342                         {
    343                             token += "
    !!!注释错误!!!";
    344                             id = -10;
    345                             ret.token = token;
    346                             ret.id    = id;
    347                             return ret;
    348                         }
    349                         //ch = prog[pos];
    350                         if (pos + 1 >= prog.size())
    351                         {
    352                             token += ch;
    353                             token += "
    !!!注释错误!!!";
    354                             id = -10;
    355                             ret.token = token;
    356                             ret.id    = id;
    357                             return ret;
    358                         }
    359                         xh = prog[pos + 1];
    360                     }
    361                     token += ch;
    362                     token += xh;
    363                     pos += 2;
    364                     ch = prog[pos];
    365                     id = keys.size() - 2;
    366                     break;
    367                 }
    368             }
    369             cit = keys.find(token);
    370             if (cit != keys.end())
    371             {
    372                 id = cit->second;
    373             }
    374             break;
    375 
    376         case '*':
    377             token += ch;
    378             cit = keys.find(token);
    379             if (cit != keys.end())
    380             {
    381                 id = cit->second;
    382             }
    383              gofor(ch, pos, prog);
    384             break;
    385 
    386         case ',':
    387         case '#':
    388         case '.':
    389         case ';':
    390             token += ch;
    391             gofor(ch, pos, prog);
    392             //++pos;
    393             //ch = prog[pos];
    394             cit = keys.find(token);
    395             if (cit != keys.end())
    396             {
    397                 id = cit->second;
    398             }
    399             break;
    400 
    401         case '
    ':
    402             token += "换行";
    403             ++pos;
    404             ch = prog[pos];
    405             id = -2;
    406             break;
    407         default:
    408             token += "错误";
    409             ++pos;
    410             ch = prog[pos];
    411             id = -1;
    412             break;
    413         }
    414     }
    415     ret.token = token;
    416     ret.id    = id;
    417 
    418     return ret;
    419 }
    420 
    421 void init_keys(const string& file, map<string, int>& keys)//读取单词符号和种别码
    422 {
    423     ifstream fin(file.c_str());//.c_str返回的是当前字符串的首地址
    424     if (!fin)
    425     {
    426         cerr << file << " doesn't exist!" << endl;//cerr不经过缓冲而直接输出,一般用于迅速输出出错信息
    427       //  exit(1);
    428     }
    429     keys.clear();//清空map对象里面的内容
    430     string line;
    431     string key;
    432     int id;
    433     while (getline(fin, line))//这个函数接收两个参数:一个输入流对象和一个string对象,getline函数从输入流的下一行读取,并保存读取的内容到string中
    434     {
    435         istringstream sin(line);//istringstream sin(s);定义一个字符串输入流的对象sin,并调用sin的复制构造函数,将line中所包含的字符串放入sin 对象中!
    436         sin >> key >> id;//读取里面的字符串每一行一个key id
    437         keys[key] = id;
    438     }
    439 }
    440 
    441 void read_prog(const string& file, string& prog){//读取代码,并追加到prog上
    442     ifstream fin(file.c_str());
    443     if (!fin)
    444     {
    445         cerr << file << " error!" << endl;
    446       //  exit(2);
    447     }
    448     prog.clear();
    449     string line;
    450     while (getline(fin, line))
    451     {
    452         prog += line + '
    ';
    453     }
    454 }
    455 int main()
    456 {
    457     map<string, int> keys;
    458     init_keys("D:/Test/a.txt", keys);
    459 
    460     string prog;
    461     read_prog("D:/Test/b.txt", prog);
    462 
    463     vector< _2tup > tups;
    464     string token, id;
    465 
    466     string::size_type pos = 0;//size_type属于string标准库,作用可看做相当于unsigned·int
    467     int row  = 1;
    468 
    469     _2tup tu;
    470     cout << "------------------" << "要分析的代码如下"<< "---------------" << endl;
    471     cout << prog << endl << endl;
    472 
    473     // prog += "#"; // 标识终止,其实可以检测 pos 来判别是否终止
    474 
    475     int no = 0;
    476  cout << "------------------" << "分析的结果如下如下"<< "---------------" << endl;
    477     do
    478     {
    479         tu = scanner(prog, pos, keys, row);
    480 
    481         switch (tu.id)
    482         {
    483         case -1://返回的是错误
    484             ++no;
    485             cout << no << ": ";
    486             cout << "Error in row" << row << "!" << '<' << tu.token<< "," << tu.id << '>' << endl;
    487             tups.push_back(tu);
    488             break;
    489         case -2:
    490             ++row;
    491             // cout << '<' << tu.token<< "," << tu.id << '>' << endl;
    492             break;
    493         default:
    494             ++no;
    495             cout << no << ": ";
    496             if(tu.id==28 || tu.id==29){
    497                 cout << '<' << tu.id<< "," << tu.token << '>' << endl;
    498             }
    499             else{
    500                 cout << '<' << tu.id<< "," << "-" << '>' << endl;
    501             }
    502             tups.push_back(tu);
    503             break;
    504         }
    505     } while (pos < prog.size());
    506 
    507     cout << endl << "--------------------------------结果总行数------------"<<tups.size() << endl;
    508     return 0;
    509 }
    View Code

    四:运行截图

    看懂代码之后,便可以很容易扩展写出其他语言的词法分析器。

  • 相关阅读:
    .NET Core 3.0 部署在docker上运行
    Docker 微服务教程
    Docker 入门教程
    快速了解 Linux系统信息
    Navicat 连接本地MS-SQL服务器,只能用localhost无法使用127.0.0.1
    安装Ubuntu Server 18.04 并支持远程方式
    AdventureWorks 安装和配置[转自 微软msdn]
    SQL Server 2014 Agent 无法启动
    微信会死么
    ajax+php数据增加查询获取删除
  • 原文地址:https://www.cnblogs.com/henuliulei/p/10597281.html
Copyright © 2011-2022 走看看