; Python-ish grammar ; (derived from a previous experiment, 08/py3/p3meta.py) ; ; Deliberate differences from Python 3.0: ; - Anonymous fn defs like JavaScript, instead of single-expr lambdas ; - It's really a Python syntax for Scheme. I'm not implementing all ; of Python for a parser experiment :-) ; ; This is the first pass, which generates an AST. Further transformation ; is required to generate valid Scheme code -- we have to identify local ; variables and add LETs to declare them, for example. ; top = stmt+ if_ = 'if' expr ':' suite [else_] else_ = 'else' ':' suite while_ = 'while' expr ':' suite [else_] ; Incomplete for_ = 'for' expr ':' suite [else_] with_ = 'with' expr ':' suite ; Unlike standard Python, my 'def' can define anonymous functions def_ = 'def' [name:n] '(' argument+:a ')' ':' suite:s -> (if n `(define (,n ,@a) ,s) `(lambda ,a ,s) ) class_ = 'class' name ['(' name ')'] ':' suite try_ = 'try' ':' suite ['except' ':' suite]+ [else_] ['finally' ':' suite] ; XXX: 'suite' loops forever (but 'expr' works in its place) suite = ws nl indent stmt+:s dedent | stmtlist:s ws nl -> s stmt = compound:s | simple:s ws nl -> s stmtlist = simple:s [';' simple]*:ss [';'] -> (if (empty? ss) s (cons s ss)) simple = pass | return | scope | break | continue | expr compound = def_ | class_ | if_ | while_ | for_ | try_ | with_ scope = {'global' | 'nonlocal'}:kw name+:ns -> `(kw ,ns) return = 'return' pass = 'pass' break = 'break' continue = 'continue' ;expr = SCHEME ;p = SCHEME ;operator = SCHEME parens = '(' { expr ',' }+:es ')' -> `(begin ,es) value = scalar | varref ; variable or function call varref = name:n ['(' parameter+:a ')'] -> (if a `(n ,a) n) parameter = ['*':r] ['*':k] name:n [default:d] -> (cond (k (kwarg n)) ; '**' = keyword args (r (restarg n)) ; '*' = rest args (d (optarg n)) ; optional argument (else n)) argument = ['*':r] ['*':k] name:n [typetag:t] [default:d] -> ; TODO: don't throw away type annotations (cond (k (kwarg n)) ; '**' = keyword args (r (restarg n)) ; '*' = rest args (d (optarg n)) ; optional argument (else n)) typetag = ':' name default = '=' expr ;dent = SCHEME ;indent = SCHEME ;samedent = SCHEME scalar = number | string | bool | List ;number = SCHEME ;string = SCHEME bool = True | False | None True = {'True'} -> #t False = {'False'} -> '#f None = {'None'} -> null ;list = '[' [expr:e [',' expr]*]:es [','] ']' List = '[' [expr [',' expr]*]:es [','] ']' ; Sketchy... probably need to define in Scheme: ;escape = '\\' any_char:c -> c ;string = str_s | str_d | str_3s | str_3d ;str_s = '\'' (escape | <^'>)* '\'' ;str_d = '"' (escape | <^">)* '"' ; These won't close right: ;str_3s = '\'\'\'' (escape | <^">)* '\'\'\'' ;str_3d = '"""' (escape | <^">)* '"""' ;Number = ['+'|'-']:s (char-in #\0 #\9) Number = ['+'|'-':s] Number:n -> (if s (- n) n)