aboutsummaryrefslogtreecommitdiff
path: root/tools/find.nom
blob: aeb535dfb3a3b079bb409969f2675bd13d6c6c70 (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
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env nomsu -V5.12.12.8
#
    This is a tool to find syntax trees matching a pattern. "*" is a wildcard
    that will match any subtree, and "**" is a wildcard that will match any
    0 or more subtrees. "**" is greedy, so extra arguments after it will
    not match.

        nomsu -t find [flags] "* squared" file1 file2...

    Flags:
        -l  List only the names of the files with matches
        --wildcard=<wildcard>  Specify a custom wildcard (in case you need to
            match an action with a "*" in the name)

    Output:
        <filename>:<line number>:
            <matching lines>
    
use "lib/os.nom"
use "lib/consolecolor.nom"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$wildcard = ($(COMMAND LINE ARGS)."--wildcard" or "%*")
$pattern = $(COMMAND LINE ARGS).extras.1
if (any of [not $pattern, $pattern == "*", $pattern == "**"]):
    barf "Usage: nomsu -t find [-l] [--wildcard=<wildcard>] <pattern>, where <pattern> is valid Nomsu code"

$pattern = ($pattern|with "\$wildcard\$wildcard" -> "$multi_wildcard")
$pattern = ($pattern|with $wildcard -> "$wildcard")
$pattern_tree = ($pattern parsed)
say $pattern_tree

($tree matches $patt) means:
    when:
        (not ($tree is syntax tree)):
            return (no)

        (($patt.type == "Var") and ($patt.1 == "wildcard")):
            return (yes)

        ($tree.type != $patt.type):
            return (no)

        ($tree.type == "Action"):
            if (($tree|get stub) != ($patt|get stub)):
                return (no)

    for $ in 1 to (#$patt):
        if ($patt.$ is syntax tree):
            if ($patt.$ == \$multi_wildcard):
                return (yes)

            unless ($tree.$ matches $patt.$):
                return (no)
        ..else:
            unless ($tree.$ == $patt.$):
                return (no)

    if ((#$tree) != (#$patt)):
        return (no)

    return (yes)

$filenames = ($(COMMAND LINE ARGS).extras|from 2 to -1)
if ((#$filenames) == 0):
    say "Warning: searching stdin (ctrl-d to abort). To avoid this message, use nomsu -t find -"
    $filenames = ["stdin"]

for $filename in ($filenames):
    $file = (read file $filename)
    unless $file:
        barf "File does not exist: \$filename"
    $code = (NomsuCode from ($Source $filename 1 (size of $file)) $file)
    try:
        $tree = ($code parsed)
    ..and if it barfs $msg:
        say (red "\$filename failed to parse:\n\$msg")
        $tree = (nil)
    
    unless $tree:
        do next $filename
    
    $results = []
    for $t in recursive $tree:
        if ($t matches $pattern_tree):
            $line_num = ($file|line number at $t.source.start)
            $results|
                add {line: $line_num, text: "\(blue "\$filename:\$line_num:")\n\(source lines of $t)"}
        
        for $sub in $t:
            if ($sub is syntax tree):
                recurse $t on $sub

    if ($(COMMAND LINE ARGS)."-l"):
        if ((#$results) > 0):
            say $filename
    ..else:
        sort $results by $ -> $.line
        for $ in $results:
            say $.text