diff options
Diffstat (limited to 'examples/go/rpn.rl')
-rw-r--r-- | examples/go/rpn.rl | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/examples/go/rpn.rl b/examples/go/rpn.rl deleted file mode 100644 index 2ad0a2db..00000000 --- a/examples/go/rpn.rl +++ /dev/null @@ -1,159 +0,0 @@ -// -*-go-*- -// -// Reverse Polish Notation Calculator -// Copyright (c) 2010 J.A. Roberts Tunney -// MIT License -// -// To compile: -// -// ragel -Z -T0 -o rpn.go rpn.rl -// go build -o rpn rpn.go -// ./rpn -// -// To show a diagram of your state machine: -// -// ragel -V -Z -p -o rpn.dot rpn.rl -// xdot -Tpng -o rpn.png rpn.dot -// - -package main - -import ( - "errors" - "fmt" - "os" - "strconv" -) - -type stack struct { - items []int - count int -} - -func (s *stack) pop() int { - s.count-- - v := s.items[s.count] - return v -} - -func (s *stack) push(v int) { - s.items[s.count] = v - s.count++ -} - -func abs(v int) int { - if v < 0 { - v = -v - } - return v -} - -%% machine rpn; -%% write data; - -func rpn(data string) (res int, err error) { - // p, pe, eof := 0, len(data), len(data) - cs, p, pe := 0, 0, len(data) - mark := 0 - st := &stack{items: make([]int, 128), count: 0} - - %%{ - action mark { mark = p } - action push { x, _ := strconv.Atoi(data[mark:p]); st.push(x) } - action add { y, x := st.pop(), st.pop(); st.push(x + y) } - action sub { y, x := st.pop(), st.pop(); st.push(x - y) } - action mul { y, x := st.pop(), st.pop(); st.push(x * y) } - action div { y, x := st.pop(), st.pop(); st.push(x / y) } - action abs { st.push(abs(st.pop())) } - action abba { st.push(666) } - - stuff = digit+ >mark %push - | '+' @add - | '-' @sub - | '*' @mul - | '/' @div - | 'abs' %abs - | 'add' %add - | 'abba' %abba - ; - - main := ( space | stuff space )* ; - - write init; - write exec; - }%% - - if cs < rpn_first_final { - if p == pe { - return 0, errors.New("unexpected eof") - } else { - return 0, errors.New(fmt.Sprintf("error at position %d", p)) - } - } - - if st.count == 0 { - return 0, errors.New("rpn stack empty on result") - } - - return st.pop(), nil -} - -////////////////////////////////////////////////////////////////////// - -type rpnTest struct { - s string - v int -} - -var rpnTests = []rpnTest{ - rpnTest{"666\n", 666}, - rpnTest{"666 111\n", 111}, - rpnTest{"4 3 add\n", 7}, - rpnTest{"4 3 +\n", 7}, - rpnTest{"4 3 -\n", 1}, - rpnTest{"4 3 *\n", 12}, - rpnTest{"6 2 /\n", 3}, - rpnTest{"0 3 -\n", -3}, - rpnTest{"0 3 - abs\n", 3}, - rpnTest{" 2 2 + 3 - \n", 1}, - rpnTest{"10 7 3 2 * - +\n", 11}, - rpnTest{"abba abba add\n", 1332}, -} - -type rpnFailTest struct { - s string - e string -} - -var rpnFailTests = []rpnFailTest{ - rpnFailTest{"\n", "rpn stack empty on result"}, -} - -func main() { - rc := 0 - - for _, test := range rpnTests { - res, err := rpn(test.s) - if err != nil { - fmt.Fprintf(os.Stderr, "FAIL rpn(%#v) %s\n", test.s, err) - rc = 1 - } else if res != test.v { - fmt.Fprintf(os.Stderr, "FAIL rpn(%#v) -> %#v != %#v\n", - test.s, res, test.v) - rc = 1 - } - } - - for _, test := range rpnFailTests { - res, err := rpn(test.s) - if err == nil { - fmt.Fprintf(os.Stderr, "FAIL rpn(%#v) -> %#v should fail: %#v\n", - test.s, res, test.e) - } else if err.Error() != test.e { - fmt.Fprintf(os.Stderr, "FAIL rpn(%#v) %#v should be %#v\n", - test.s, err.Error(), test.e) - } - } - - os.Exit(rc) -} |