用python编写Sebesda的词法分析器。不适用于输入文件中的最后一个词素

法兹·哈桑123

我必须将词法分析器的Sebesda编程语言概念(第4章,第2节)中的代码转换为python。这是我到目前为止的内容:

# Character classes #
LETTER = 0
DIGIT = 1
UNKNOWN = 99

# Token Codes #
INT_LIT = 10
IDENT = 11
ASSIGN_OP = 20
ADD_OP= 21
SUB_OP = 22
MULT_OP = 23
DIV_OP = 24
LEFT_PAREN = 25
RIGHT_PAREN = 26

charClass = ''
lexeme = ''
lexLen = 0
token = ''
nextToken = ''

### lookup - function to lookup operators and parentheses ###
###          and return the token                         ###
def lookup(ch):
    def left_paren():
        addChar()
        globals()['nextToken'] = LEFT_PAREN

    def right_paren():
        addChar()
        globals()['nextToken'] = RIGHT_PAREN

    def add():
        addChar()
        globals()['nextToken'] = ADD_OP

    def subtract():
        addChar()
        globals()['nextToken'] = SUB_OP

    def multiply():
        addChar()
        globals()['nextToken'] = MULT_OP

    def divide():
        addChar()
        globals()['nextToken'] = DIV_OP
    options = {')': right_paren, '(': left_paren, '+': add,
               '-': subtract, '*': multiply , '/': divide}

    if ch in options.keys():
        options[ch]()
    else:
        addChar()

### addchar- a function to add next char to lexeme ###
def addChar():
    #lexeme = globals()['lexeme']
    if(len(globals()['lexeme']) <=98):
        globals()['lexeme'] += nextChar
    else:
        print("Error. Lexeme is too long")

### getChar- a function to get the next Character of input and determine its character class ###
def getChar():
    globals()['nextChar'] = globals()['contents'][0]
    if nextChar.isalpha():
        globals()['charClass'] = LETTER
    elif nextChar.isdigit():
        globals()['charClass'] = DIGIT
    else:
        globals()['charClass'] = UNKNOWN
    globals()['contents'] = globals()['contents'][1:]


## getNonBlank() - function to call getChar() until it returns a non whitespace character ##
def getNonBlank():
    while nextChar.isspace():
        getChar()

## lex- simple lexical analyzer for arithmetic functions ##
def lex():
    globals()['lexLen'] = 0
    getNonBlank()
    def letterfunc():
        globals()['lexeme'] = ''
        addChar()
        getChar()
        while(globals()['charClass'] == LETTER or globals()['charClass'] == DIGIT):
            addChar()
            getChar()
        globals()['nextToken'] = IDENT

    def digitfunc():
        globals()['lexeme'] = ''
        addChar()
        getChar()
        while(globals()['charClass'] == DIGIT):
            addChar()
            getChar()
        globals()['nextToken'] = INT_LIT

    def unknownfunc():
        globals()['lexeme'] = ''
        lookup(nextChar)
        getChar()

    lexDict = {LETTER: letterfunc, DIGIT: digitfunc, UNKNOWN: unknownfunc}
    if charClass in lexDict.keys():
        lexDict[charClass]()
    print('The next token is: '+ str(globals()['nextToken']) + ' The next lexeme is: ' + globals()['lexeme'])

with open('input.txt') as input:
    contents = input.read()
    getChar()
    lex()
    while contents:
        lex()

我正在使用字符串sum + 1 / 33作为样本输入字符串。据我了解,在顶层对getChar()的第一次调用将characterClass设置为LETTER,并设置contentsum + 1 / 33

然后,程序进入while循环并调用lex()lex()依次将单词sum累积到中lexeme当里面的while循环letterfunc遇到第一个空格字符时,它将中断并退出lex()

由于contents不为空,因此程序将再次在顶级循环通过while循环。这次,getNonBlank()内部调用lex()“将空格填满,contents并且重复与以前相同的过程。

我遇到错误的地方是最后一个词素。有人告诉我,这globals()['contents'][0]超出了范围getChar()我并不期望找到一个困难的错误,但是我尝试手动跟踪它,但似乎无法发现问题。任何帮助将不胜感激。

塞尔吉·巴莱斯塔(Serge Ballesta)

仅仅是因为在成功读取了最后3一个输入字符串后,该digitfunc函数又重复了一次getchar但是在那一刻content已经用光了并且为空,所以contents[0]通过了缓冲区的末尾,因此出现了错误。

解决方法是,如果在表达式的最后一个字符之后添加换行符或空格,则当前代码不会出现此问题。

这样做的原因是,当最后一个字符为char时,UNKNOWN您会立即从lex返回并由于content为空而退出循环,但是如果您正在处理数字或符号,则在getchar不测试输入结束的情况下循环调用顺便说一句,如果您输入的字符串以正确的括号结尾,那么您的词法分析器会吃掉它而忘记显示它找到了它。

因此,您至少应该:

  • 在getchar中测试输入的结束:

    def getchar():
        if len(contents) == 0:
            # print "END OF INPUT DETECTED"
            globals()['charClass'] = UNKNOWN
            globals()['nextChar'] = ''
            return
        ...
    
  • 如果剩下一个,则显示最后一个令牌:

    ...
    while contents:
        lex()
    lex()
    
  • 控制是否存在词素(输入结束时可能会发生奇怪的事情)

    ...
    if charClass in lexDict.keys():
        lexDict[charClass]()
    if lexeme != '':
        print('The next token is: '+ str(globals()['nextToken']) +
              ' The next lexeme is: >' + globals()['lexeme'] + '<')
    

但是您对globals的使用是不好的在函数中使用全局变量的惯用法是在使用之前声明它:

a = 5

def setA(val):
    global a
    a = val   # sets the global variable a

但是Python的全局变量具有代码异味您能做的最好的事情就是将解析器正确封装在一个类中。对象比全局对象好

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

防止词法分析器读取文件中的第一个字符

来自分类Dev

使用输入类型=文件的文件上传不适用于IE中的第一个文件,适用于后续上传

来自分类Dev

indexToScrollTo 不适用于 TableViewCell Swift 中的最后一个 CollectionView

来自分类Dev

词法分析器。计算无法识别的词素总数

来自分类Dev

微调器方法(setSelection)在活动中仅不适用于一个微调器

来自分类Dev

我用Python编写了一个不和谐的机器人。它不适用于小故障

来自分类Dev

编写与CSV文件中的字符串匹配的Haskell词法分析器

来自分类Dev

Roslyn VSIX分析器不适用于VS2013

来自分类Dev

试图在Haskell中建立一个词法分析程序

来自分类Dev

是否已经存在一个将执行Flex生成的词法分析器的Python(2.7)模块?

来自分类Dev

最后一个类型不适用于IE11和Edge中的自定义元素

来自分类Dev

mousemove 和 mouseover 不适用于 d3 图表中的最后一个数据

来自分类Dev

django slug 适用于一个词,但当它超过一个词时它会崩溃

来自分类Dev

Logstash grok过滤器不适用于最后一个字段

来自分类Dev

不适用于:最后一个孩子到文章

来自分类Dev

相同的连接文件适用于 1 个脚本,但不适用于另一个

来自分类Dev

Systemd单元文件仅适用于一个实例名称,不适用于另一实例名称

来自分类Dev

在Python中编写一个可在Windows中同时适用于Python 2.7+和Python 3.3+的.CSV文件

来自分类Dev

将文本设置为居中仅适用于一个微调器,而不适用于其他

来自分类Dev

Fragment 接口/侦听器适用于 Activity,但不适用于另一个 Fragment

来自分类Dev

Elasticsearch 在 must 中适用于一个术语,但不适用于两个

来自分类Dev

适用于Ubuntu的HTTP请求分析器好吗?

来自分类Dev

python中的prolog事实词法分析器

来自分类Dev

ElasticSearch术语聚合不适用于自定义分析器和模式标记器

来自分类Dev

从一个站点获取信息,并在我用PHP编写的分析器/脚本中使用它

来自分类Dev

Elastic Load Balancer侦听器不适用于一个端口

来自分类Dev

HAP不适用于一个特定的URL

来自分类Dev

bash完成不适用于一个用户

来自分类Dev

git add不适用于一个文件夹

Related 相关文章

  1. 1

    防止词法分析器读取文件中的第一个字符

  2. 2

    使用输入类型=文件的文件上传不适用于IE中的第一个文件,适用于后续上传

  3. 3

    indexToScrollTo 不适用于 TableViewCell Swift 中的最后一个 CollectionView

  4. 4

    词法分析器。计算无法识别的词素总数

  5. 5

    微调器方法(setSelection)在活动中仅不适用于一个微调器

  6. 6

    我用Python编写了一个不和谐的机器人。它不适用于小故障

  7. 7

    编写与CSV文件中的字符串匹配的Haskell词法分析器

  8. 8

    Roslyn VSIX分析器不适用于VS2013

  9. 9

    试图在Haskell中建立一个词法分析程序

  10. 10

    是否已经存在一个将执行Flex生成的词法分析器的Python(2.7)模块?

  11. 11

    最后一个类型不适用于IE11和Edge中的自定义元素

  12. 12

    mousemove 和 mouseover 不适用于 d3 图表中的最后一个数据

  13. 13

    django slug 适用于一个词,但当它超过一个词时它会崩溃

  14. 14

    Logstash grok过滤器不适用于最后一个字段

  15. 15

    不适用于:最后一个孩子到文章

  16. 16

    相同的连接文件适用于 1 个脚本,但不适用于另一个

  17. 17

    Systemd单元文件仅适用于一个实例名称,不适用于另一实例名称

  18. 18

    在Python中编写一个可在Windows中同时适用于Python 2.7+和Python 3.3+的.CSV文件

  19. 19

    将文本设置为居中仅适用于一个微调器,而不适用于其他

  20. 20

    Fragment 接口/侦听器适用于 Activity,但不适用于另一个 Fragment

  21. 21

    Elasticsearch 在 must 中适用于一个术语,但不适用于两个

  22. 22

    适用于Ubuntu的HTTP请求分析器好吗?

  23. 23

    python中的prolog事实词法分析器

  24. 24

    ElasticSearch术语聚合不适用于自定义分析器和模式标记器

  25. 25

    从一个站点获取信息,并在我用PHP编写的分析器/脚本中使用它

  26. 26

    Elastic Load Balancer侦听器不适用于一个端口

  27. 27

    HAP不适用于一个特定的URL

  28. 28

    bash完成不适用于一个用户

  29. 29

    git add不适用于一个文件夹

热门标签

归档