在 Racket 中构建解析器

问题描述 投票:0回答:0

我是 Racket 的新手,我正在尝试使用 Beautiful Racket 库解析语法。我在一个单独的文件中定义了语法,它似乎完全没问题。我的标记化也在工作,我打印了输出以确认一切都被标记化了。我正在创建一个解析器,它使用 Beautiful Racket 中的“parse-to-datum”过程。但是,我遇到了解析器错误。当解析器遇到诸如“A”之类的 ID 时,它会产生一条错误消息:

Encountered unexpected token of type 'ID (value "A") while parsing 'unknown [line=1, column=#f, offset=9]

这是我的输入:

10 read A 
20 read B 
30 gosub 400 
40 if C = 400 then write C 
50 if C = 0 then goto 1000 
400 C = A + B : return 
$$

这是我在 Racket 中定义的语法:

#lang brag

program : linelist DOLLAR DOLLAR
linelist : line linelist | "epsilon"
line : idx stmt linetail* EOL
idx : digit | nonzero_digit digit*
linetail : COLON stmt | "epsilon"
stmt : id ASSIGN-OP expr DELIMIT 
     | IF expr THEN stmt 
     | READ id DELIMIT 
     | WRITE expr DELIMIT 
     | GOTO idx 
     | GOSUB idx 
     | RETURN
expr : id etail | num etail | LPAREN expr RPAREN
etail : ADD-OP expr | SUB-OP expr | EQ-OP expr | "epsilon"
id : LETTER+
num : numsign digit digit*
numsign : ADD-OP | SUB-OP | "epsilon"
nonzero_digit : DIGIT - "0"
digit : "0" | nonzero_digit

这是我的解析函数:

#lang br
(require "grammar.rkt" "tokenizer.rkt" brag/support)

(define (parse file-name)
  (define file-content (port->string (open-input-file file-name) #:close? #t))
  (with-handlers ([exn:fail? (lambda (exn)
                               (displayln (exn-message exn)))])
    (let ((tokens (apply-tokenizer-maker make-tokenizer file-content)))
      (for-each (lambda (token)
                  (displayln token))
                tokens)
      (parse-to-datum tokens)
      (displayln "Accept"))))

(parse "file03.txt")

我已经尝试调整我在语法中定义 ID 的方式,但这没有帮助,因为我认为这是一个解析器问题。它在第一行中很好地解析了“10”和“read”,但无法解析 A。我希望它根据语法规则解析 A。

parsing racket tokenize lexer beautiful-racket
© www.soinside.com 2019 - 2024. All rights reserved.