Plai 2: Everything about parser

plai-type 的parser, 不得不说lisp语言还是擅长处理括号表达式,而且其list 的member允许类型不同,但是说真的,还是不怎么喜欢lisp。

#lang plai-typed
(define-type ArithC
  [numC (n : number)]
  [plusC (l : ArithC) (r : ArithC)]
  [multC (l : ArithC) (r : ArithC)])
(define (parse [s : s-expression]) : ArithC
  (cond
    [(s-exp-number? s) (numC (s-exp->number s))]
    [(s-exp-list? s)
     (let ([sl (s-exp->list s)])
       (case (s-exp->symbol (first sl))
         [(+) (plusC (parse (second sl)) (parse (third sl)))]
         [(*) (multC (parse (second sl)) (parse (third sl)))]
         [else (error 'parse "invalid list input")]))]
    [else (error 'parse "invalid input")]))

(parse '(+ (* 1 2) (+ 2 3)))

  因为刚开始学OCaml, 所以也用OCaml写了一个parser,但是我是用状态机实现的,很ugly, verbose,而且感觉代码风格还是imperative的,离functional 还是有很大的距离。

let s = "(+ (* 1 2) (+ 2 3))" in
let l = String.length s in
let state : int ref = ref 0 in
let rec parse (i : int) =
    if i >= l then ()
    else (
        match s.[i] with
        | '(' ->
                print_char '(';
                if !state = 0 then (
                    state := 1;
                    parse (i+1);
                )
                else if !state = 3 || !state = 5  then (
                    state := 1;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
        | '+' ->
                if !state = 1 then (
                    print_string "plusC";
                    state := 2;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
    | '*' ->
                if !state = 1 then (
                    print_string "multC";
                    state := 2;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
        | ' ' ->
                print_char ' ';
                if !state = 2 then (
                    state := 3;
                    parse (i+1);
                )
                else if !state = 4 || !state = 7 then (
                    state := 5;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
        | ')' ->
                print_char ')';
                if !state = 7 then (
                    state := 7;
                    parse (i+1);
                )
                else if !state = 6 then (
                    state := 7;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
    | c ->
                Printf.printf "(numC %c)" c;
                if !state = 3 then (
                    state := 4;
                    parse (i+1);
                )
                else if !state = 1 then (
                    state := 8;
                    parse (i+1);
                )
                else if !state = 5 then (
                    state := 6;
                    parse (i+1);
                )
                else (
                    print_string "error";
                    parse (i+1);
                )
         )
in parse 0

  

 

posted @ 2016-10-22 13:41  goingstudy  阅读(271)  评论(0编辑  收藏  举报