我是 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。