aboutsummaryrefslogtreecommitdiff
path: root/nomnom/parser.nom
blob: 13d6112b1b4a61aad5e90b37261c1f8da51f273e (plain)
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env nomsu -V4.8.10
# This file contains the parser, which converts text into abstract syntax trees
#use "nomonom/ast.nom"
%lpeg = (=lua "require('lpeg')")
%re = (=lua "require('re')")
call %lpeg.setmaxstack with [20000]
set {..}
    ((P 1)'s meaning):%lpeg.P, ((R 1)'s meaning):%lpeg.R
    ((Carg 1)'s meaning):%lpeg.Carg, ((S 1)'s meaning):%lpeg.S
    ((Cc 1)'s meaning):%lpeg.Cc, ((lpeg re pattern 1)'s meaning):%re.compile
    ((lpeg re pattern 1 using 2)'s meaning):%re.compile
    ((lpeg pattern 1's match of 2)'s meaning):%lpeg.match
    ((lpeg pattern 1's match of 2 with 3)'s meaning): (..)
        [%1, %2, %3] -> (call %lpeg.match with [%1, %2, nil, %3])

%source_code_for_tree = {}
%defs = (..)
    {..}
        nl: (P "\r")^(-1) * (P "\n")
        tab: P "\t"
        tonumber: %tonumber
        tochar: %string.char
        unpack: %unpack
        nil: Cc (nil)
        userdata: Carg 1
        utf8_char: (..)
            (R "\194\223")*(R "\128\191") +
            ..(R "\224\239")*(R "\128\191")*(R "\128\191") +
            ..(R "\240\244")*(R "\128\191")*(R "\128\191")*(R "\128\191")

        Tree: [%t, %userdata] ->:
            %source = (..)
                Source {filename:%userdata.filename, start:%t.start, stop:%t.stop}
            set {%t.start: nil, %t.stop: nil, %t.source: %source}
            %t = (Syntax Tree %t)
            (Syntax Tree).source_code_for_tree.%t = %userdata.source
            return %t
    ..with fallback %key ->:
        if:
            (%key::matches "^ascii_(%d+)$"):
                %i = (%key::matching "^ascii_(%d+)$")
                return (call %string.char with [%i as a number])
            
            (%key::matches "^number_(%d+)$"):
                %i = (%key::matching "^number_(%d+)$")
                return (Cc (%i as a number))

%id_patt = (..)
    ((P "") - (R "09")) * (..)
        (%defs.utf8_char + (R "az") + (R "AZ") + (P "_") + (R "09")) ^ 1 * -1

%operator_patt = ((S "'`~!@$^&*+=|<>?/-") ^ 1 * -1)
externally [%text is a nomsu id, %text is a nomsu identifier] all mean (..)
    lpeg pattern %id_patt's match of %text

externally (%text is a nomsu operator) means (..)
    lpeg pattern %operator_patt's match of %text

%peg_tidier = (..)
    lpeg re pattern "\
        ..file <- %nl* {~ (def/comment) (%nl+ (def/comment))* %nl* ~}
        def <- anon_def / captured_def
        anon_def <-
            ({ident} (" "*) ":" {[^%nl]* (%nl+ " "+ [^%nl]*)*}) 
            -> "%1 <- %2"
        captured_def <-
            ({ident} (" "*) "(" {ident} ")" (" "*) ":" {[^%nl]* (%nl+ " "+ [^%nl]*)*})
            -> "%1 <- ({| {:start:{}:} %3 {:stop:{}:} {:type: (''->'%2') :} |} %%userdata) -> Tree"
        ident <- [a-zA-Z_][a-zA-Z0-9_]*
        comment <- "--" [^%nl]*
        "

externally (make parser from %peg) means (make parser from %peg using (nil))
externally (make parser from %peg using %make_tree) means:
    %peg = (lpeg pattern %peg_tidier's match of %peg)
    %peg = (lpeg re pattern %peg using %defs)
    (%input from %filename parsed) means:
        %input = "\%input"
        %tree_mt = {__index:{source:%input, filename:%filename}}
        %userdata = {..}
            make_tree:%make_tree or ([%] -> (: set %'s metatable to %tree_mt; return %))
            filename:%filename, source:%input
        
        %tree = (lpeg pattern %peg's match of %input with %userdata)
        assume %tree or barf "\
            ..File \%filename failed to parse:
            \%input"
        
        return %tree
    
    return ((1 from 2 parsed)'s meaning)