程序的语法

『我不生产代码,我只是代码的搬运工。』当然了,这是一个玩笑。说到代码,我们要学习各种编程语言,学习如何让编译器能懂我们编写的代码。但是,编译器是如何做到能听懂我们的话的呢?按照我们既定的语句一行行的去执行,最终达到我们的目的。这篇文章,我会讲一个很简单的四则运算解释器,通过使用 Python 实现它来一步步了解一个解释器是如何工作的,它们又是怎么得到我们想要的结果的。

语法

计算机语言同样也是一种语言,是一种计算机能够理解的语言,我们想要和计算机对话,就要去学习这种语言。和我们人类的语言一样,计算机语言也是有语法的。以汉语为例,我说『我是中国人』,因为汉语的语法,你听到这句话之后会知道『我』是主语,『是』是谓语,『中国人』是宾语,同时你又很清楚每一个成分的含义,最终理解了整句话的意思。

同样,对于计算机语言也是一样,有着程序的语法,一个解释器知道哪个词是操作数,哪个是操作符,哪个是关键字,它们都有着怎样的含义和功能,通过解释器的解释,计算机明白了某行语句的意义,然后进行运算,得到最后的执行结果。

语法图

语法图就是用来表示一种编程语言语法规则设计的示意图,它很直观的显示出了在一种编程语言中,允许使用的语句和不支持的语句。语法图十分易于阅读:只需跟随箭头指示的路径。一些路径表示选择。另一些路径表示循环。

一个简单的语法图

这里我们举一个语法图的例子:

image

这个语法图就是一个描述了简单的加减运算的语法图,term 在其中的意思就是一个操作数,一开始输入一个操作数,有三条路径可以选择『+』,『-』和退出,如果进入了『+』、『-』路径,则需要再输入一个操作数,之后的路径包括『+』、『-』和退出,如此循环,就能解释一个简单的加减法解释器。

根据上边的语法图,下面的表达式都是合法的:

  • 4
  • 1 + 1
  • 1 + 4 - 3

下面的表达式不合法:

  • -
  • + -
  • 2 +
  • + 3 - 3

语法图可以帮助我们:

  • 用图的方式表示出一种计算机语言的设计规范
  • 可以帮助理解解释器,将图表表示成代码

代码实现(Python)

学习一样东西最简单的就是阅读代码(Read the Fucking Code!),因此我们先来看完整代码然后再来分析一下,完整代码在:https://github.com/luoyhang003/Pascal-Interpreter/blob/master/calc3.py

# Token Types:
# EOF: End-Of-File

INTEGER, PLUS, MINUS, EOF = 'INTEGER', 'PLUS', 'MINUS', 'EOF'

class Token(object):
    def __init__(self, type, value):
        # Token types: INTEGER, PLUS, MINUS, EOF
        self.type = type
        # Token value: 0,1,2,3,4,5,6,7,8,9,+,None
        self.value = value

    def __str__(self):
        """
        The format of the print infomation
        For examle:
        Token(INTEGER, 3)
        Token(PLUS, '+')
        Token(MINUS, '-')
        """
        return 'Token({type},{value})'.format(
                type = self.type,
                value = repr(self.value)
                )

    def __repr__(self):
        return self.__str__()

class Interpreter(object):
    def __init__(self, text):
        # Process the whole input
        # e.g. 3+5
        self.text = text
        self.pos = 0
        self.current_token = None
        self.current_char = self.text[self.pos]

    def error(self):
        raise Exception('Error Parsing Error!')

    def advance(self):
        # Advance the pos and set current_char
        self.pos += 1

        if self.pos > len(self.text)-1:
            self.current_char = None
        else:
            self.current_char = self.text[self.pos]

    def skip_whitespace(self):
        # Skip space
        while self.current_char is not None and self.current_char.isspace():
            self.advance()

    def integer(self):
        # Support mutidigit integer
        result = ''

        while self.current_char is not None and self.current_char.isdigit():
            result += self.current_char
            self.advance()

        return int(result)

    def get_next_token(self):
        """
        Lexical Analyzer:
        Parsing the input into tokens.
        Strategy:
        1. is pos past the end of the text?
        2. if so, return EOF
        3. get a character at pos, and decide its type depends on the single char
        4. if it is a space, advance the pos
        5. if it is a digit, then convert it to integer and return INTEGER token
        6. if it is a '+', then return PLUS token
        7. if it is a '-', then return MINUS
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
附录c 编译程序实验 实验目的:用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 语法分析 C2.1 实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. C2.2 实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. C2.2.1待分析的简单语言语法 实验目的 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法. 实验要求 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 实验的输入和输出 输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4;x:=(a+b)/c end# 输出的三地址指令如下: (1) t1=3*4 (2) t2=2+t1 (3) a=t2 (4) t3=a+b (5) t4=t3/c (6) x=t4 算法思想 1设置语义过程 (1) emit(char *result,char *arg1,char *op,char *ag2) 该函数功能是生成一个三地址语句送到四元式表中。 四元式表的结构如下: struct {char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[20]; (2)char *newtemp() 该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,…. Char *newtemp(void) { char *p; char m[8]; p=(char *)malloc(8); k++; itoa(k,m,10); strcpy(p+1,m); p[0]=’t’; return(p); } (2)主程序示意c.10所示。 (2) 函数lrparser在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。 语义分析程序的C语言程序框架 int lrparser() { int schain=0; kk=0; if(syn=1) { 读下一个单词符号; schain=yucu; /调用语句串分析函数进行分析/ if(syn=6) { 读下一个单词符号; if(syn=0 && (kk==0)) 输出(“success”); } else { if(kk!=1 ) 输出 ‘缺end’ 错误;kk=1;} else{输出’begin’错误;kk=1;} } return(schain); int yucu() { int schain=0; schain=statement();/调用语句分析函数进行分析/ while(syn=26) {读下一个单词符号; schain=statement(); /调用语句分析函数进行分析/ } return(schain); } int statement() { char tt[8],eplace[8]; int schain=0; {switch(syn) {case 10: strcpy(tt,token); scanner(); if(syn=18) {读下一个单词符号; strcpy(eplace,expression()); emit(tt,eplace,””,””); schain=0; } else {输出’缺少赋值号’的错误;kk=1; } return(schain); break; } } char *expression(void) {char *tp,*ep2,*eplace,*tt; tp=(char *)malloc(12);/分配空间/ ep2=(char *)malloc(12); eplace=(char *)malloc(12); tt =(char )malloc(12); strcpy(eplace,term ());/调用term分析产生表达式计算的第一项eplace/ while(syn=13 or 14) { 操作符 tt= ‘+’或者‘—’; 读下一个单词符号; strcpy(ep2,term());/调用term分析产生表达式计算的第二项ep2/ strcpy(tp,newtemp());/调用newtemp产生临时变量tp存储计算结果/ emit(tp,eplace,tt,ep2);/生成四元式送入四元式表/ strcpy(eplace,tp); } return(eplace); } char *term(void)/仿照函数expression编写/ char *factor(void) {char *fplace; fplace=(char *)malloc(12); strcpy(fplace, “ ”); if(syn=10) {strcpy(fplace,,token);/将标识符token的值赋给fplace/ 读下一个单词符号; } else if(syn=11) {itoa(sum,fplace,10); 读下一个单词符号; } else if (syn=27) {读下一个单词符号; fplace=expression();/调用expression分析返回表达式的值/ if(syn=28) 读下一个单词符号; else{输出‘}’错误;kk=1; } } else{输出‘(’错误;kk=1; } return(fplace); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值