Skip to content
Browse files

Use the new grammar.

  • Loading branch information...
1 parent c94fda3 commit 63a13670744650d37de09ac42e884f57018e3880 @kr committed
View
2 TODO
@@ -15,7 +15,7 @@
[+] generate C macros for sodium variable access
[+] simple sh testing
[+] better error reporting in the compiler
-[ ] new grammar
+[+] new grammar
[ ] proper (unicode) string and bytes types
[ ] proper file i/o
[ ] move bytecode loading into sodium code
View
2 ad-hoc-tests/app.lx
@@ -5,7 +5,7 @@ compile "a.lx"
def c (load-module ad-hoc-tests/c)
-c
+c.
pr (load-module sample-module)
View
6 ad-hoc-tests/break.lx
@@ -6,7 +6,7 @@ def (f x) (? x (error "zippo") 7)
def p (f :run 1) # doomed promise -- must be an error
-p .wait (fn (x) (pr "oh noes") (pr x))
+p .wait (fn (x.) (pr "oh noes") (pr x))
p .wait-for-error (fn (name val) (pr "thankfully, got error"))
@@ -14,11 +14,11 @@ def o (p :+ 3) # doomed promise -- must be an error
o .wait-for-error (fn (name val) (pr ("yay! name %s val %s" % name val)))
-o .wait (fn (x) (pr ("boo, answer is %s" % x)))
+o .wait (fn (x.) (pr ("boo, answer is %s" % x)))
def q (f :run '()) # promise for 7
-q .wait (fn (x) (pr "nice yay") (pr x))
+q .wait (fn (x.) (pr "nice yay") (pr x))
q .wait-for-error (fn (name val) (pr "crap! got error"))
View
2 ad-hoc-tests/d.lx
@@ -1,6 +1,6 @@
import (ad-hoc-tests/c -> c)
-def (f):
+def (f.):
c.x
export f
View
12 ad-hoc-tests/ensure.lx
@@ -1,12 +1,12 @@
-def (ok) 5
-def (er) (error "blah")
+def (ok.) 5
+def (er.) (error "blah")
-def ok-promise (ensure (fn () (ok)) (fn () (pr "ok succeded")))
-def er-promise (ensure (fn () (er)) (fn () (pr "er succeded")))
+def ok-promise (ensure (fn () (ok.)) (fn () (pr "ok succeded")))
+def er-promise (ensure (fn () (er.)) (fn () (pr "er succeded")))
-ok-promise .wait (fn (x) (pr x))
-er-promise .wait (fn (x) (pr x))
+ok-promise .wait (fn (x.) (pr x))
+er-promise .wait (fn (x.) (pr x))
ok-promise .wait-for-error (fn (name val) (pr name) (pr val))
er-promise .wait-for-error (fn (name val) (pr name) (pr val))
View
6 ad-hoc-tests/fin.lx
@@ -1,8 +1,8 @@
import fin f
-f
+f.
-def (x) (x)
+def (x.) (x.)
-x
+x.
View
4 ad-hoc-tests/inf.lx
@@ -1,4 +1,4 @@
-def (x) (x)
+def (x.) (x.)
-x
+x.
View
8 ad-hoc-tests/inf2.lx
@@ -1,12 +1,12 @@
def n 0
-def (report):
+def (report.):
pr ("reached depth %d" % n)
-def (count):
+def (count.):
n :: (n + 1)
? ((n % 100000) = 0) (pr n)
- count
+ count.
report :run
-count
+count.
View
2 ad-hoc-tests/mod.lx
@@ -2,4 +2,4 @@ import (ad-hoc-tests/c -> c)
import (ad-hoc-tests/d -> d) f
pr (c.x)
-pr (f)
+pr (f.)
View
6 ad-hoc-tests/promise.lx
@@ -1,5 +1,5 @@
-def pp (make-promise)
+def pp (make-promise.)
def p (pp.car)
def s (pp.cdr)
@@ -7,7 +7,7 @@ def f (p:a)
f.wait [pr x]
-s (obj () ((a) 5))
+s (obj () ((a.) 5))
#def p (load-module pm)
@@ -15,4 +15,4 @@ s (obj () ((a) 5))
#
#def v (p:m)
#
-#v.wait (fn (x) (pr x) (set! v x))
+#v.wait (fn (x.) (pr x) (set! v x))
View
4 ad-hoc-tests/return.na
@@ -1,8 +1,8 @@
-def (f):
+def (f.):
pr "a"
pr "b"
return "c"
pr "d"
pr "e"
-pr (f)
+pr (f.)
View
20 ad-hoc-tests/sample.lx
@@ -3,19 +3,19 @@
# This is a sample LX file
def a: obj ():
- (m) 5
+ (m.) 5
def b: obj ():
- (n) a
+ (n.) a
def x b:n
def y x:m
y.wait:
- fn (x):
+ fn (x.):
pr "should be next-to-last"
- y.wait: fn (x): pr "should be last"
+ y.wait: fn (x.): pr "should be last"
def x 7
@@ -41,19 +41,19 @@ pr x
def (f x): pr x
pr (8 - 3)
pr (8 :- 3)
-fn (x) (* x x)
+fn (x.) (* x x)
def o: obj ():
- (run) "yess"
+ (run.) "yess"
-pr (o)
+pr (o.)
pr ("pi is %f" % π)
-def d (make-dict)
+def d (make-dict.)
d.put! "hi" 42
-pr d.get "hi"
+pr (d.get "hi")
d.delete! "hi"
-pr d.get "hi"
+pr (d.get "hi")
View
10 ad-hoc-tests/send.lx
@@ -3,11 +3,11 @@
# Test eventual sends
def a ():
- (m) (pr "should be fourth") 5
- (q) (pr "should be second")
+ (m.) (pr "should be fourth") 5
+ (q.) (pr "should be second")
def b ():
- (n) (pr "should be third") a
+ (n.) (pr "should be third") a
a:q
@@ -16,8 +16,8 @@ def x (b:n)
def y (x:m)
y.wait:
- fn (x):
- y.wait (fn (x) (pr "should be last"))
+ fn (x.):
+ y.wait (fn (x.) (pr "should be last"))
pr x
pr "should be next-to-last"
View
4 ad-hoc-tests/seq-def.lx
@@ -4,7 +4,7 @@ do :
pr x
-def (f):
+def (f.):
? 4 :
do :
def q 'blah
@@ -12,4 +12,4 @@ def (f):
pr 'ooo
pr 'aaa
-f
+f.
View
4 ad-hoc-tests/unass.lx
@@ -1,5 +1,5 @@
-def (f):
+def (f.):
pr x
def x 3
-f
+f.
View
2 array.na
@@ -66,7 +66,7 @@ def array: sobj:
return ok_sym;
end
- inline C (length) <<end
+ inline C (length.) <<end
return int2datum(datum_size(rcv));
end
View
4 bytes.na
@@ -82,7 +82,7 @@ def bytes: sobj:
return (datum) new_str;
end
- inline C (decode) <<end
+ inline C (decode.) <<end
/* TODO check for valid UTF-8 */
return make_str_init(datum_size(rcv), (char *) rcv);
end
@@ -98,7 +98,7 @@ def bytes: sobj:
return int2datum(bytes_contents(rcv)[i]);
end
- inline C (length) <<end
+ inline C (length.) <<end
return int2datum(datum_size(rcv));
end
View
6 count.lx
@@ -1,8 +1,8 @@
def n 0
-def (count):
+def (count.):
n :: (n + 1)
? ((n % 100000) = 0) (pr n)
- ? (n < 5000000) (count)
+ ? (n < 5000000) (count.)
-count
+count.
View
12 file-io.na
@@ -26,7 +26,7 @@ fsize(int f)
end
def intern-syms ():
- inline C (run) <<end
+ inline C (run.) <<end
read_sym = intern("read");
write_sym = intern("write");
return ok_sym;
@@ -35,7 +35,7 @@ def intern-syms ():
def file ():
(run name flags):
def prepare: obj ():
- inline C (run) <<end
+ inline C (run.) <<end
int f;
int flags = O_RDONLY;
@@ -63,10 +63,10 @@ def file ():
return make_pbox((void *) f, (pbox_fn_free) close);
end
- def pbox (prepare)
+ def pbox (prepare.)
def f ():
- inline C (read) <<end
+ inline C (read.) <<end
int r;
uint len;
datum bytes;
@@ -103,7 +103,7 @@ def file ():
return ok_sym;
end
- inline C (close) <<end
+ inline C (close.) <<end
int r;
int f = (int) rcv[2];
@@ -117,5 +117,5 @@ def file ():
. f
-intern-syms
+intern-syms.
. file
View
8 fin.na
@@ -14,13 +14,13 @@ fin_test_fn(void *i)
end
-def (f):
+def (f.):
def make-box: obj ():
- inline C (run) <<end
+ inline C (run.) <<end
return make_pbox((void *) 3, fin_test_fn);
end
- make-box
- #def pbox (make-box)
+ make-box.
+ #def pbox (make-box.)
#obj ()
export f
View
38 grammar.md
@@ -0,0 +1,38 @@
+# Grammar
+
+ prog: line* EOF
+ line: expr EOL
+ expr: body
+ : body "."
+ : body "." expr
+ : body ":" expr
+ : body ":" EOL block
+ body:
+ : atom mess* binexpr*
+ block: INDENT line* DEDENT
+ mess: BINOP
+ : UNOP
+ binexpr: unexpr
+ : unexpr BINOP binexpr
+ unexpr: atom UNOP*
+ atom: SYMBOL
+ : NUMBER
+ : STRING
+ : "(" expr ")"
+ : "[" expr "]"
+ : "'" atom
+
+## Example 1
+
+ def (f x) (* x x)
+
+ def (g .) (print "hi")
+
+## Example 2
+
+ def a: obj:
+ (foo x y):
+ print x
+ print y
+ (bar .):
+ print "hello"
View
4 int.na
@@ -83,7 +83,7 @@ def int: sobj:
(** x) (error "not implemented")
- (str):
+ (str.):
def upper (self / 10)
def lower (self % 10)
def table "0123456789"
@@ -92,4 +92,4 @@ def int: sobj:
else:
(upper.str) / (table lower)
-. '()
+'()
View
6 lib/foo.lx
@@ -1,9 +1,9 @@
import mod one
-def (a) (pr "this is a")
-def (b) (pr "this is b")
-def (c) (one)
+def (a.) (pr "this is a")
+def (b.) (pr "this is b")
+def (c.) (one.)
export a (b -> y) c
View
2 lib/mod.lx
@@ -1,5 +1,5 @@
-def (one) (pr "this is c")
+def (one.) (pr "this is c")
export one
View
2 lib/pm.lx
@@ -1,2 +1,2 @@
-obj () ((m) 5)
+obj () ((m.) 5)
View
90 lib/unit-test.lx
@@ -5,19 +5,19 @@ def (run-all tester):
((make-runner tester).suite):print-on pr
def (should f):
- #shouldnt [not (f)]
- shouldnt (fn () (not (f)))
+ #shouldnt [not (f.)]
+ shouldnt (fn () (not (f.)))
def (shouldnt f):
- #if (f) (error "Test Failed")
- if (f) (info "Test Failed") (info ".")
+ #if (f.) (error "Test Failed")
+ if (f.) (info "Test Failed") (info ".")
def (info msg):
if *verbose* (pr msg)
def (make-runner tester):
def runner ():
- (suite):
+ (suite.):
runner .named-suite "suite"
(named-suite name):
@@ -25,26 +25,26 @@ def (make-runner tester):
(make-case selector):
def case ():
- (set-up):
+ (set-up.):
if (inspect .has-method? tester 'set-up) (tester .set-up)
#' for vim sake
- (tear-down):
+ (tear-down.):
if (inspect .has-method? tester 'tear-down) (tester .tear-down)
#' for vim sake
- (perform-test):
+ (perform-test.):
call tester selector '()
# Why is this necessary?!
'()
- (all-the-rest):
+ (all-the-rest.):
ensure (fn () (case .perform-test)) (fn () (case .tear-down))
(run-with collector):
case .set-up
def p (case .all-the-rest)
- wait p (fn (x) (collector .pass-in case))
+ wait p (fn (x.) (collector .pass-in case))
p .wait-for-error :
fn (name val):
@@ -58,7 +58,7 @@ def (make-runner tester):
# self.set-up
# do
# self.perform-test
- # collector.pass-in(self) if collector
+ # collector.pass-in(self.) if collector
# ensure
# self.tear-down
# end
@@ -71,42 +71,42 @@ def (make-runner tester):
# raise Stop unless RUT.keep-going
#end
- (count) 1
+ (count.) 1
- (to-s) ('%s:%s' % self.class selector)
+ (to-s.) ('%s:%s' % self.class selector)
. case
- (cases):
+ (cases.):
#(runner .selectors).map [runner .make-case x]
- (runner .selectors).map (fn (x) (runner .make-case x))
+ (runner .selectors).map (fn (x.) (runner .make-case x))
- (selectors):
+ (selectors.):
#(inspect .methods tester) .filter [(x .str) .starts-with? "test-"]
- (inspect .methods tester) .filter (fn (x) ((x .str) .starts-with? "test-"))
+ (inspect .methods tester) .filter (fn (x.) ((x .str) .starts-with? "test-"))
. runner
def (make-suite name tests):
def suite ():
- (name) name
+ (name.) name
- (run):
+ (run.):
def collector (make-collector suite)
collector .start
ensure (fn () (suite .run-with collector)) (fn () (collector .stop))
(run-with collector):
- def p (make-promise)
+ def p (make-promise.)
info ("\n\nRunning suite %s" % name)
#tests [x.run-with collector]
- #tests .schedule (fn (t) (t .run-with collector))
- def promises (tests .map (fn (t) (t .run-with collector)))
- wait-all promises (fn (l) ((p .cdr) collector))
+ #tests .schedule (fn (t.) (t .run-with collector))
+ def promises (tests .map (fn (t.) (t .run-with collector)))
+ wait-all promises (fn (l.) ((p .cdr) collector))
p .car
- (count):
- (tests .map (fn (x) (x .count))) .fold 0 (fn (sum x) (sum + x))
+ (count.):
+ (tests .map (fn (x.) (x .count))) .fold 0 (fn (sum x) (sum + x))
. suite
@@ -114,16 +114,16 @@ def (make-collector suite):
def start-time 0
def stop-time 0
def test-name (suite .name)
- def failures (make-queue)
- def errors (make-queue)
+ def failures (make-queue.)
+ def errors (make-queue.)
def total-count (suite .count)
def total-run 0
def pass-count 0
def collector ():
- (start) (start-time :: (time .now))
+ (start.) (start-time :: (time .now))
- (stop) (stop-time :: (time .now))
+ (stop.) (stop-time :: (time .now))
(error-in ex case):
errors (make-result .error ex case)
@@ -143,15 +143,15 @@ def (make-collector suite):
pr "."
#STDOUT .flush
- (errors) errors
+ (errors.) errors
- (failures) failures
+ (failures.) failures
- (bad-results) (failures + errors)
+ (bad-results.) (failures + errors)
- (duration) (stop-time - start-time)
+ (duration.) (stop-time - start-time)
- (summary):
+ (summary.):
def skipped-count (total-count - total-run)
def skipped-msg (if (skipped-count > 0)
(" (%d skipped)" % skipped-count)
@@ -160,7 +160,7 @@ def (make-collector suite):
fmt % (collector .duration) total-count pass-count (failures .size) (errors .size) skipped-msg
end
- (report):
+ (report.):
puts "\n"
puts (collector .summary)
(collector .bad-results).each-with-index (fn (r i) (r .report (i + 1)))
@@ -180,26 +180,26 @@ class TestResult
self.new(:Error, ex, test)
end
- def report(n)
- return self.report-verbosely(n) if RUT.*verbose* or @kind === :Error
- return self.report-succinctly(n)
+ def report(n.)
+ return self.report-verbosely(n.) if RUT.*verbose* or @kind === :Error
+ return self.report-succinctly(n.)
end
- def report-succinctly(n)
+ def report-succinctly(n.)
puts "\n#{n}) #{@kind} in #{@test}:\n#{@ex.message}"
end
- def report-verbosely(n)
- self.report-succinctly(n)
- puts @ex.backtrace.map { |line| ' ' + self.fix-path(line) }
+ def report-verbosely(n.)
+ self.report-succinctly(n.)
+ puts @ex.backtrace.map { |line| ' ' + self.fix-path(line.) }
end
- def fix-path(line)
+ def fix-path(line.)
path, rest = line.split(':', 2)
- File.make-relative(path) + ':' + fix-rest(rest)
+ File.make-relative(path.) + ':' + fix-rest(rest.)
end
- def fix-rest(rest)
+ def fix-rest(rest.)
return rest if !rest.index(':')
lno, rest = rest.split(':', 2)
lno + ': ' + rest
View
8 module.na
@@ -33,7 +33,7 @@ def loader ():
(run name):
def ent (*modules*.assq name)
if ent: return ent.cdr
- def new-module (make-placeholder)
+ def new-module (make-placeholder.)
*modules* :: (cons (cons name new-module) *modules*)
become new-module (load-module name) 1
. new-module
@@ -50,7 +50,7 @@ def (make-module name):
read-file (find-file name)
def (find-file name):
- name :: ("lib/"./ name.str./ ".lxc")
+ name :: ("lib/"./ (name.str ./ ".lxc"))
name.encode
def find-builtin: obj ():
@@ -65,10 +65,10 @@ def read-file: obj ():
return read_module_file(name);
end
-def (make-placeholder) (obj ())
+def (make-placeholder.) (obj ())
def module: sobj:
- inline C (run) <<end
+ inline C (run.) <<end
start_body(rcv);
return regs[R_VAL];
end
View
2 nil.na
@@ -13,7 +13,7 @@ nil_init()
end
def nil: sobj:
- (str) "()"
+ (str.) "()"
(filter f) '()
(run f) 'ok
(schedule f) 'ok
View
4 pair.na
@@ -30,11 +30,11 @@ def pair: sobj:
return ok_sym;
end
- inline C (car) <<end
+ inline C (car.) <<end
return car(rcv);
end
- inline C (cdr) <<end
+ inline C (cdr.) <<end
return cdr(rcv);
end
View
60 prelude.na
@@ -68,7 +68,7 @@ def inspect ():
if (is? x '()): return false
if (is? m x.car): return true
scan x.cdr
- scan inspect.methods c
+ scan (inspect.methods c)
inline C (same-type? x y) <<end
if (datum_mtab(n_x) == datum_mtab(n_y)) return int2datum(1);
return nil;
@@ -93,8 +93,8 @@ def inspect ():
def (promise? x): inspect.has-method? x 'wait
def (ensure try finally):
- def success [do (finally) x]
- def failure [do (finally) (error x y)]
+ def success [do (finally.) x]
+ def failure [do (finally.) (error x y)]
try:run.wait+ success failure
import array
@@ -131,7 +131,7 @@ def (assq x a):
if (is? x a.car.car): return a.car
assq x a.cdr
-def (make-dict):
+def (make-dict.):
def items '()
def dict: obj ():
(set key value):
@@ -148,12 +148,12 @@ def (make-dict):
import (file-io as open)
-def (make-queue):
+def (make-queue.):
def front '()
def rear '()
def queue ():
- (empty?): is? front '()
- (front):
+ (empty?.): is? front '()
+ (front.):
if (queue.empty?): error "front called on an empty queue"
front.car
(run item):
@@ -165,11 +165,11 @@ def (make-queue):
rear.set-cdr! new
rear :: new
. queue
- (remove!):
+ (remove!.):
def item queue.front
queue.delete!
. item
- (delete!):
+ (delete!.):
if (queue.empty?): error "delete! called on an empty queue"
front :: front.cdr
. queue
@@ -181,7 +181,7 @@ def (make-queue):
queue.consume! f
. queue
-def (make-promise):
+def (make-promise.):
def status 'pending # or resolved or broken
def value '()
@@ -190,23 +190,23 @@ def (make-promise):
# a queue of functions to run upon success
# they must be safe to run directly -- they must do the right thing
- def success-queue (make-queue)
+ def success-queue (make-queue.)
# a queue of functions to run upon success
# they must be safe to run directly -- they must do the right thing
- def err-queue (make-queue)
+ def err-queue (make-queue.)
- def (resolved?) (is? status 'resolved)
- def (pending?) (is? status 'pending)
- def (broken?) (is? status 'broken)
+ def (resolved?.) (is? status 'resolved)
+ def (pending?.) (is? status 'pending)
+ def (broken?.) (is? status 'broken)
def (queue-for-success f):
- if (pending?) (success-queue f)
- if (resolved?) (f value)
+ if (pending?.) (success-queue f)
+ if (resolved?.) (f value)
def (queue-for-err f):
- if (pending?) (err-queue f)
- if (broken?) (f err-name err-val)
+ if (pending?.) (err-queue f)
+ if (broken?.) (f err-name err-val)
def (process state err):
status :: state
@@ -232,7 +232,7 @@ def (make-promise):
# 4. The original promise is broken, the error handler raises an error,
# and this promise is broken.
(wait+ f h):
- def pp (make-promise)
+ def pp (make-promise.)
def p (pp.car)
def s (pp.cdr)
@@ -252,13 +252,13 @@ def (make-promise):
def sink ():
(run val):
- if (resolved?): error "already resolved"
+ if (resolved?.): error "already resolved"
status :: 'resolved
value :: val
success-queue.consume! [x val]
process 'resolved
(break! name val):
- if (broken?): error "already broken"
+ if (broken?.): error "already broken"
status :: 'broken
err-name :: name
err-val :: val
@@ -268,13 +268,13 @@ def (make-promise):
cons promise sink
def (make-broken-promise name val):
- def pp (make-promise)
+ def pp (make-promise.)
(pp.cdr).break! name val
. pp
# expects a thunk, returns a (promise, task) pair
def (make-task f):
- def p (make-promise)
+ def p (make-promise.)
def promise p.car
def sink p.cdr
@@ -284,7 +284,7 @@ def (make-task f):
# expects a thunk and a sink, returns a task
def (make-task+ f sink): obj ():
- (run): sink (f)
+ (run.): sink (f.)
(break! x): sink.break! 'error x
def (schedule-task task):
@@ -301,18 +301,18 @@ def (send rcv msg args):
rcv.send msg args
make-and-schedule-task [call rcv msg args]
-def *tasks* (make-queue)
+def *tasks* (make-queue.)
-def (process-tasks):
+def (process-tasks.):
if (not *tasks*.empty?):
def task (*tasks*.remove!)
- task
+ task.
# if there was an error
# task.break!
- process-tasks
+ process-tasks.
# Load and execute the main program.
module.run-file *args*.car
# Process the work queue.
-process-tasks
+process-tasks.
View
8 re.na
@@ -22,7 +22,7 @@ def re ():
(make pat opts):
def compile: obj ():
- inline C (run) <<end
+ inline C (run.) <<end
pcre *re;
const char *error;
int erroffset, opts;
@@ -34,17 +34,17 @@ def re ():
return make_pbox(re, free);
end
- def compiled (compile)
+ def compiled (compile.)
def r ():
(run subj) (r.match subj (r.runopts))
(find subj) (r.match subj (r.findopts))
- inline C (runopts) <<end
+ inline C (runopts.) <<end
return int2datum(PCRE_ANCHORED);
end
- inline C (findopts) <<end
+ inline C (findopts.) <<end
return int2datum(0);
end
View
206 reader.py
@@ -59,152 +59,150 @@ def parse(self): return self.__program()
@record_pos_info
def __program(self):
'''
-program : stmt* EOF
+ prot: line* EOF
+
'''
- stmts = self.match_loop(self.__stmt, T.EOF)
+
+ lines = self.match_loop(self.__line, T.EOF)
self.match(T.EOF)
- return stmts
+ return lines
+
@record_pos_info
- def __stmt(self):
+ def __line(self):
'''
-stmt : mole
- | mole EOL
+ line: expr EOL
'''
-
- exprs = self.__mole(T.EOL)
- self.try_match(T.EOL)
- return exprs
-
+ expr = self.__expr(T.EOL)
+ self.match(T.EOL)
+ return expr
@record_pos_info
- def __mole(self, *follow):
+ def __expr(self, *follow):
'''
-mole :
- | '.' expr
- | IMESS stuff
- | expr stuff
-
- | expr tail
- | expr SMESS tail
- | expr IMESS tail
- | NAME '::' expr
+ expr: body
+ : body "." expr
+ : body ":" expr
+ : body ":" EOL block
'''
+ singular, body = self.__body(T.DOT, T.DOTS, *follow)
- if self.peek in follow: return nil
if self.peek == T.DOT:
self.match(T.DOT)
- return self.__expr()
- if self.peek in MESSAGE_TOKENS:
- first = lx.S(self.match(*MESSAGE_TOKENS))
- else:
- first = self.__expr()
-
- strip = (self.peek in MESSAGE_TOKENS)
- res = self.__molex(first, *follow)
- if strip: res = res.car()
+ more = self.__expr(*follow)
+ if singular:
+ return cons(body, more)
+ else:
+ return body.append(more)
if self.peek == T.DOTS:
- x = res.append(self.__tail(*follow))
- return x
+ self.match(T.DOTS)
+ if self.try_match(T.EOL):
+ more = self.__block()
+ else:
+ more = list(self.__expr(*follow))
+ if singular: body = list(body)
+ return body.append(more)
- return res
+ return body
@record_pos_info
- def __message(self):
- stype, lexeme, pos = self.xmatch(*MESSAGE_TOKENS)
- if stype == T.ASSIGN: return lx.S(lexeme)
- return lx.Mess(lexeme)
+ def __body(self, *follow):
+ '''
+ body:
+ : atom mess* binexpr*
+ : mess mess* binexpr*
+ '''
+ if self.peek in follow: return False, nil
+
+ if self.peek in (T.IMESS, T.SMESS, T.BINOP):
+ atom = lx.S(self.match(T.IMESS, T.SMESS, T.BINOP))
+ else:
+ atom = self.__atom()
+ if self.peek in follow: return True, atom
- def gobble_messages_reverse(self, l):
- if self.peek not in MESSAGE_TOKENS: return l
- return self.gobble_messages_reverse(cons(self.__message(), l))
+ first, mess = atom, None
+ while self.peek in (T.IMESS, T.SMESS, T.BINOP, T.ASSIGN):
+ type, mess, pos = self.xmatch(T.IMESS, T.SMESS, T.BINOP, T.ASSIGN)
+ if type == T.ASSIGN:
+ first = list(first, lx.S(mess))
+ else:
+ first = list(first, lx.Mess(mess))
- def make_head(self, l):
- a = l.car()
- d = l.cdr()
- if d.nullp(): return a
- return list(self.make_head(d), a)
+ if not mess: first = list(atom)
+
+ args = self.match_loop(self.__binexpr, *follow)
+ return False, first.append(args)
@record_pos_info
- def __molex(self, first, *follow):
- '''
-molex : MESS* tail
- '''
-
- rhead = self.gobble_messages_reverse(list(first))
- tail = cons(rhead.car(), self.__inner_tail(*follow + (T.DOTS,)))
- if rhead.cdr().nullp():
- return tail
- head = self.make_head(rhead.cdr())
- x = list(cons(head, tail))
- return x
+ def __block(self):
+ '''
+ block: INDENT line* DEDENT
+ '''
+ self.match(T.INDENT)
+ lines = self.match_loop(self.__line, T.DEDENT)
+ self.match(T.DEDENT)
+ return lines
@record_pos_info
- def __inner_tail(self, *follow):
+ def __binexpr(self):
'''
-inner_tail :
- | expr inner_tail
+ binexpr: unexpr
+ : unexpr BINOP binexpr
'''
- if self.peek in follow: return nil
- return self.__molex(self.__expr(), *follow)
+ left = self.__unexpr()
+ if self.peek not in (T.BINOP, T.ASSIGN): return left
+ type, lexeme, pos = self.xmatch(T.BINOP, T.ASSIGN)
+ if type == T.ASSIGN:
+ message = lx.S(lexeme)
+ else:
+ message = lx.Mess(lexeme)
+ right = self.__binexpr()
+ return list(left, message, right)
@record_pos_info
- def __tail(self, *follow):
+ def __unexpr(self):
'''
-tail :
- | ':' mole
- | ':' EOL INDENT stmt+ DEDENT EOL
+ unexpr: atom UNOP*
'''
+ atom = self.__atom()
- if self.peek != T.DOTS: return nil
+ first = atom
+ while self.peek in (T.IMESS, T.SMESS):
+ first = list(first, lx.Mess(self.match(T.IMESS, T.SMESS)))
- self.match(T.DOTS)
- if self.peek != T.EOL: return list(self.__mole(*follow))
- self.match(T.EOL)
- self.match(T.INDENT)
- exprs = self.match_loop(self.__stmt, T.DEDENT)
- self.match(T.DEDENT)
- self.match(T.EOL)
- return exprs
+ return first
@record_pos_info
- def __expr(self):
+ def __atom(self):
'''
-expr : atom
- | '(' ')'
- | '(' mole ')'
- | '[' mole ']'
- | "'" expr
+ atom : NAME
+ : INT
+ : DEC
+ : STR
+ : HEREDOC
+ : "(" expr ")"
+ : "[" expr "]"
+ : "'" atom
'''
-
if self.peek == T.LPAR:
self.match(T.LPAR)
- mole = self.__mole(T.RPAR)
+ expr = self.__expr(T.RPAR)
self.match(T.RPAR)
- return mole
- elif self.peek == T.LSQU:
+ return expr
+
+ if self.peek == T.LSQU:
self.match(T.LSQU)
- mole = self.__mole(T.RSQU)
+ expr = self.__expr(T.RSQU)
self.match(T.RSQU)
- return list(lx.S(':shorthand-fn:'), mole)
- elif self.peek == T.QUOTE:
+ return list(lx.S(':shorthand-fn:'), expr)
+
+ if self.peek == T.QUOTE:
self.match(T.QUOTE)
- expr = self.__expr()
- return list(lx.S('quote'), expr)
- else:
- return self.__atom()
+ atom = self.__atom()
+ return list(lx.S('quote'), atom)
- @record_pos_info
- def __atom(self):
- '''
-atom : NAME
- | INT
- | DEC
- | STR
- | HEREDOC
- '''
type, lexeme, pos = self.xmatch(T.INT, T.DEC, T.NAME, T.STR, T.HEREDOC)
if type == T.INT:
return lx.Integer(lexeme)
@@ -251,10 +249,6 @@ def unescape(s):
'"':'"',
}
-def make_invoke(op, first, lexeme, tail):
- return list(lx.S(op), first, (lx.S('quote'), lx.S(lexeme[1:])),
- (lx.S('list'),) + tail)
-
def parse(tokens):
return Parser(tokens).parse()
View
4 sh-tests/assoc.na
@@ -27,8 +27,8 @@ pr x
pr ""
def o ():
- (a): obj ():
- (b) 3
+ (a.): obj ():
+ (b.) 3
pr 5
pr (o.a.b + 2)
View
2 sh-tests/dict.na
@@ -1,5 +1,5 @@
-def x (make-dict)
+def x (make-dict.)
#pr x
View
6 sh-tests/exp-imp.na
@@ -1,8 +1,8 @@
import foo a (y -> b) c
-a
+a.
-b
+b.
-c
+c.
View
8 sh-tests/ind.na
@@ -1,6 +1,6 @@
-def (y) 5
+def (y.) 5
-def x: obj (): (run):
- y
+def x: obj (): (run.):
+ y.
-pr: x
+pr: x.
View
2 sh-tests/insp.na
@@ -1,6 +1,6 @@
def o ():
- (a) 3
+ (a.) 3
pr (inspect .has-method? o 'a)
pr (inspect .has-method? o 'b)
View
8 sh-tests/methods.na
@@ -3,9 +3,9 @@ pr (inspect .methods '())
pr (inspect .methods '(a b))
pr (inspect .methods 'x)
pr (inspect .methods 45)
-pr (inspect .methods (obj () ((hi) 4) ((there) 7)))
+pr (inspect .methods (obj () ((hi.) 4) ((there.) 7)))
-pr ('(a b c) .filter (fn (x) 1))
+pr ('(a b c) .filter (fn (x.) 1))
-pr ('() .run (fn (x) 0))
-pr ('(a b c) .run (fn (x) 0))
+pr ('() .run (fn (x.) 0))
+pr ('(a b c) .run (fn (x.) 0))
View
2 sh-tests/q.na
@@ -1,6 +1,6 @@
#!/home/kr/src/lx/lxi
-def q (make-queue)
+def q (make-queue.)
q 3
q 4
View
8 sh-tests/self.na
@@ -1,17 +1,17 @@
#!/home/kr/src/lx/lxi
def x: sobj:
- (foo):
+ (foo.):
. 7
- (bar):
+ (bar.):
self.foo
- (baz):
+ (baz.):
7 + 3
self.foo
- (bay):
+ (bay.):
def x 1
self.foo
View
4 str.na
@@ -97,11 +97,11 @@ def str: sobj:
return make_str_init(1, s);
end
- inline C (encode) <<end
+ inline C (encode.) <<end
return make_bytes_init_len((char *) rcv, datum_size(rcv));
end
- inline C (length) <<end
+ inline C (length.) <<end
return int2datum(datum_size(rcv));
end
View
16 tests/list.lx
@@ -1,26 +1,26 @@
import (unit-test -> T) run-all should shouldnt
-def (make-tester):
+def (make-tester.):
def empty '()
def single '()
obj ():
- (set-up):
+ (set-up.):
empty :: '()
- single :: '(4)
+ single :: '(4.)
- (test-car):
+ (test-car.):
#should [4 = (single.car)]
should (fn () (4 = (single .car)))
- (test-map-empty):
+ (test-map-empty.):
def (f x) x
#should [is? (empty.map f) '()]
should (fn () (is? (empty .map f) '()))
- (test-equal):
- should (fn () (single = '(4)))
+ (test-equal.):
+ should (fn () (single = '(4.)))
-run-all (make-tester)
+run-all (make-tester.)
pr "done"
View
2 x.lx
@@ -1,4 +1,4 @@
-def (f):
+def (f.):
if 3:
return 5.foo
else:

0 comments on commit 63a1367

Please sign in to comment.
Something went wrong with that request. Please try again.