我在ocaml中编写了一个程序,给出了一个像1 + 2这样的中缀表达式,输出前缀表示法:+ 1 2
我的问题是我找不到制定规则的方法:所有值,运算符和括号应始终至少由一个空格分隔:1+ 1将错误1 + 1 ok。我想不使用ocamlp4语法。
这是代码:
open Genlex
type tree =
| Leaf of string
| Node of tree * string * tree
let my_lexer str =
let kwds = ["("; ")"; "+"; "-"; "*"; "/"] in
make_lexer kwds (Stream.of_string str)
let make_tree_from_stream stream =
let op_parser operator_l higher_perm =
let rec aux left higher_perm = parser
[<'Kwd op when List.mem op operator_l; right = higher_perm; s >]
-> aux (Node (left, op, right)) higher_perm s
| [< >]
-> left
in
parser [< left = higher_perm; s >] -> aux left higher_perm s
in
let rec high_perm l = op_parser ["*"; "/"] brackets l
and low_perm l = op_parser ["+"; "-"] high_perm l
and brackets = parser
| [< 'Kwd "("; e = low_perm; 'Kwd ")" >] -> e
| [< 'Ident n >] -> Leaf n
| [< 'Int n >] -> Leaf (string_of_int n)
in
low_perm stream
let rec draw_tree = function
| Leaf n -> Printf.printf "%s" n
| Node(fg, r, fd) -> Printf.printf "(%s " (r);
draw_tree fg;
Printf.printf " ";
draw_tree fd;
Printf.printf ")"
let () =
let line = read_line() in
draw_tree (make_tree_from_stream (my_lexer line)); Printf.printf "\n"
另外如果您有关于代码的一些提示或者如果您注意到prog风格的一些错误,那么我将非常感谢您让我知道。谢谢!
答案 0 :(得分:1)
Genlex
提供了一个现成的词法分析器,它尊重OCaml的词汇约定,特别是忽略了你提到的位置中的空格。我不认为你可以在它上面实现你想要的东西(它不是一个灵活的解决方案,而是一个快速的方法来使原型工作)。
如果你想继续编写流解析器,你可以为它编写自己的词法分析器:定义token
类型,并将char Stream.t
lex到token Stream.t
,然后你就可以了你想要解析。否则,如果您不想使用Camlp4,您可能需要尝试LR解析器生成器,例如menhir(更好的ocamlyacc)。