aboutsummaryrefslogtreecommitdiff
path: root/tools/find.nom
blob: f9a63b97c94620f8d78dd7e58be9058d946feda5 (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
#!/usr/bin/env nomsu -V6.14
#
    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"
use "lib/consolecolor"

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

$wildcard = ($(COMMAND LINE ARGS).wildcard or "%*")
$pattern = $(COMMAND LINE ARGS).extras.1
if (any of [not $pattern, $pattern == "*", $pattern == "**"]):
    fail ("
        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)
($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:
        fail "File does not exist: \$filename"
    $code = (NomsuCode from ($Source $filename 1 (size of $file)) $file)
    try:
        $tree = ($code parsed)
    ..if it fails $msg:
        say
            red ("
                \$filename failed to parse:
                \$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