Initial Commit
[packages] / xemacs-packages / semantic / wisent / wisent-expr.el
1 ;;; wisent-expr.el --- Infix to prefix expression converter
2
3 ;; Copyright (C) 2001 David Ponce
4
5 ;; Author: David Ponce <david@dponce.com>
6 ;; Maintainer: David Ponce <david@dponce.com>
7 ;; Created: 19 June 2001
8 ;; Keywords: syntax
9 ;; X-RCS: $Id: wisent-expr.el,v 1.1 2007-11-26 15:12:31 michaels Exp $
10
11 ;; This file is not part of GNU Emacs.
12
13 ;; This program is free software; you can redistribute it and/or
14 ;; modify it under the terms of the GNU General Public License as
15 ;; published by the Free Software Foundation; either version 2, or (at
16 ;; your option) any later version.
17
18 ;; This program is distributed in the hope that it will be useful, but
19 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 ;; General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with this program; see the file COPYING.  If not, write to
25 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 ;; Boston, MA 02110-1301, USA.
27
28 ;;; Commentary:
29 ;;
30 ;; Sample program using the elisp LALR parser Wisent. It just converts
31 ;; expressions from infix (C like) to prefix notation (Lisp like).
32
33 ;;; History:
34 ;; 
35
36 ;;; Code:
37
38 (require 'wisent)
39
40 (defconst wisent-expr-parser-tables
41   (eval-when-compile
42     (wisent-compile-grammar
43      '(
44        ;; terminals
45        (NUMBER MINUS PLUS DIV MULT LPAREN RPAREN SEMI)
46        ;; no operator precedence
47        nil
48        ;; non terminals
49        (grammar ((grammar expr)
50                  (format "%s %s" $1 $2))
51                 ((expr)
52                  (format "%s" $1))
53                 )
54        (expr    ((add SEMI)
55                  (format "%s%s" $1 $2))
56                 ((SEMI)
57                  ";")
58                 ((error SEMI) ;; on parse error skip tokens until
59                  "\"error\";") ;; next semicolon and return "error";
60                 )
61        (add     ((add MINUS mult)
62                  (list '- $1 $3))
63                 ((add PLUS mult)
64                  (list '+ $1 $3))
65                 ((mult))
66                 )
67        (mult    ((mult DIV final)
68                  (list '/ $1 $3))
69                 ((mult MULT final)
70                  (list '* $1 $3))
71                 ((final))
72                 )
73        (final   ((LPAREN add RPAREN)
74                  $2)
75                 ((NUMBER))
76                 )
77        )))
78   "Expression converter parser tables.")
79
80 (defconst wisent-expr-operators
81   '((?\; . SEMI)
82     (?\( . LPAREN)
83     (?\) . RPAREN)
84     (?\+ . PLUS)
85     (?\- . MINUS)
86     (?\* . MULT)
87     (?\/ . DIV))
88   "Expression converter operator terminals.")
89
90 (defconst wisent-expr-number-regexp
91   (eval-when-compile
92     (concat "^\\("
93             "[0-9]+\\([.][0-9]*\\)?\\([eE][-+]?[0-9]+\\)?"
94             "\\|"
95             "[.][0-9]+\\([eE][-+]?[0-9]+\\)?"
96             "\\)"
97             ))
98   "Regexp to match the expression converter number terminals.")
99
100 (defvar wisent-expr-lexer-input-stream nil
101   "The expression converter lexer input stream.")
102
103 (defun wisent-expr-lexer ()
104   "The expression converter lexer."
105   (let* ((is  (or wisent-expr-lexer-input-stream ""))
106          (k   (string-match "\\S-" is)) ;; skip spaces
107          (lex (list wisent-eoi-term)))
108     (if (not k)
109         nil
110       (setq is (substring is k))
111       (cond
112        ;; Number
113        ((string-match wisent-expr-number-regexp is)
114         (setq lex (list 'NUMBER (read (match-string 0 is)))
115               is  (substring is (match-end 0))))
116        ;; Operator
117        ((setq k (assq (aref is 0) wisent-expr-operators))
118         (setq lex (list (cdr k) (string (aref is 0)))
119               is  (substring is 1)))
120        ;; Invalid input
121        (t
122         (error "Invalid input character '%c'" (aref is 0))))
123       (setq wisent-expr-lexer-input-stream is))
124     lex))
125
126 (defun wisent-expr (input)
127   "Infix to prefix expression converter.
128 Parse INPUT string and output the result of computation."
129   (interactive "sexpr: ")
130   (or (string-match ";\\s-*$" input)
131       (setq input (concat input ";")))
132   (let ((wisent-expr-lexer-input-stream input))
133     (message "%s -> %s"
134              input
135              (wisent-parse wisent-expr-parser-tables
136                            #'wisent-expr-lexer
137                            #'message))))
138
139 (provide 'wisent-expr)
140
141 ;;; wisent-expr.el ends here