File: calc.g

package info (click to toggle)
yapps2 2.2.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 408 kB
  • sloc: python: 1,016; sh: 24; makefile: 13
file content (64 lines) | stat: -rw-r--r-- 2,636 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
globalvars = {}       # We will store the calculator's variables here

def lookup(map, name):
    for x,v in map:  
        if x == name: return v
    if name not in globalvars: print('Undefined (defaulting to 0):', name)
    return globalvars.get(name, 0)

def stack_input(scanner,ign):
    """Grab more input"""
    scanner.stack_input(input(">?> "))

%%
parser Calculator:
    ignore:    "[ \r\t\n]+"
    ignore:    "[?]"         {{ stack_input }}

    token END: "$"
    token NUM: "[0-9]+"
    token VAR: "[a-zA-Z_]+"

    # Each line can either be an expression or an assignment statement
    rule goal:   expr<<[]>> END            {{ print('=', expr) }}
                                           {{ return expr }}
               | "set" VAR expr<<[]>> END  {{ globalvars[VAR] = expr }}
                                           {{ print(VAR, '=', expr) }}
                                           {{ return expr }}

    # An expression is the sum and difference of factors
    rule expr<<V>>:   factor<<V>>         {{ n = factor }}
                     ( "[+]" factor<<V>>  {{ n = n+factor }}
                     |  "-"  factor<<V>>  {{ n = n-factor }}
                     )*                   {{ return n }}

    # A factor is the product and division of terms
    rule factor<<V>>: term<<V>>           {{ v = term }}
                     ( "[*]" term<<V>>    {{ v = v*term }}
                     |  "/"  term<<V>>    {{ v = v/term }}
                     )*                   {{ return v }}

    # A term is a number, variable, or an expression surrounded by parentheses
    rule term<<V>>:   
                 NUM                      {{ return int(NUM) }}
               | VAR                      {{ return lookup(V, VAR) }}
               | "\\(" expr "\\)"         {{ return expr }}
               | "let" VAR "=" expr<<V>>  {{ V = [(VAR, expr)] + V }}
                 "in" expr<<V>>           {{ return expr }}
%%
if __name__=='__main__':
    print('Welcome to the calculator sample for Yapps 2.')
    print('  Enter either "<expression>" or "set <var> <expression>",')
    print('  or just press return to exit.  An expression can have')
    print('  local variables:  let x = expr in expr')
    # We could have put this loop into the parser, by making the
    # `goal' rule use (expr | set var expr)*, but by putting the
    # loop into Python code, we can make it interactive (i.e., enter
    # one expression, get the result, enter another expression, etc.)
    while 1:
        try: s = input('>>> ')
        except EOFError: break
        if not s.strip(): break
        parse('goal', s)
    print('Bye.')