File: syntax.cpp

package info (click to toggle)
antimony 0.9.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,476 kB
  • sloc: cpp: 42,596; ansic: 28,661; python: 1,093; yacc: 128; lex: 114; sh: 90; makefile: 10
file content (114 lines) | stat: -rw-r--r-- 3,682 bytes parent folder | download | duplicates (3)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <Python.h>

#include "script/syntax.h"
#include "app/colors.h"

ScriptHighlighter::ScriptHighlighter(QTextDocument* doc)
    : QSyntaxHighlighter(doc)
{
    PyObject* kwmod = PyImport_ImportModule("keyword");
    PyObject* kwlist = PyObject_GetAttrString(kwmod, "kwlist");

    QList<QString> keywords = {"input", "output", "title", "meta"};

    // Get all of Python's keywords and add them to a list.
    for (int i=0; i < PyList_Size(kwlist); ++i)
    {
        PyObject* kw = PyList_GetItem(kwlist, i);

        wchar_t* w = PyUnicode_AsWideCharString(kw, NULL);
        keywords << QString::fromWCharArray(w);
        PyMem_Free(w);
    }

    Py_DECREF(kwlist);
    Py_DECREF(kwmod);

    // Make rules for all the Python keywords.
    QTextCharFormat kw_format;
    kw_format.setForeground(Colors::green);
    for (auto k : keywords)
        rules << Rule("\\b" + k + "\\b", kw_format);

    QTextCharFormat quote_format;
    quote_format.setForeground(Colors::brown);
    // Triple-quoted (multiline) strings
    // Single-line triple-quoted string
    rules << Rule("'''.*?'''", quote_format);
    rules << Rule("\"\"\".*?\"\"\"", quote_format);
    // Beginning of multiline string
    rules << Rule("'''.*$", quote_format, BASE, MULTILINE_SINGLE);
    rules << Rule("\"\"\".*$", quote_format, BASE, MULTILINE_DOUBLE);
    // End of multiline string
    rules << Rule("^.*'''", quote_format, MULTILINE_SINGLE, BASE);
    rules << Rule("^.*\"\"\"", quote_format, MULTILINE_DOUBLE, BASE);
    // Inside of multiline string
    rules << Rule("^.+$", quote_format, MULTILINE_SINGLE, MULTILINE_SINGLE);
    rules << Rule("^.+$", quote_format, MULTILINE_DOUBLE, MULTILINE_DOUBLE);

    // Regular strings
    rules << Rule("\".*?\"", quote_format);
    rules << Rule("'.*?'", quote_format);

    // String that can be prepended to a regex to make it detect negative
    // numbers (but not subtraction).  Note that a closing parenthesis is
    // needed and the desired number is the last match group.
    QString neg = "(^|\\*\\*|[(+\\-=*\\/,\\[])([+\\-\\s]*";

    QTextCharFormat float_format;
    float_format.setForeground(Colors::yellow);
    rules << Rule(neg + "\\b\\d+\\.\\d*)", float_format);
    rules << Rule(neg + "\\b\\d+\\.\\d*e\\d+)", float_format);
    rules << Rule(neg + "\\b\\d+e\\d+)", float_format);

    QTextCharFormat int_format;
    int_format.setForeground(Colors::orange);
    rules << Rule(neg + "\\b\\d+\\b)", int_format);

    QTextCharFormat comment_format;
    comment_format.setForeground(Colors::base03);

    rules << Rule("#.*", comment_format);
}

////////////////////////////////////////////////////////////////////////////////

void ScriptHighlighter::highlightBlock(const QString& text)
{
    int offset = 0;
    int state = previousBlockState();

    while (offset <= text.length())
    {
        int match_start = -1;
        int match_length;
        Rule rule;

        for (auto r : rules)
        {
            if (r.state_in != state)
                continue;

            auto match = r.regex.match(text, offset);
            if (!match.hasMatch())
                continue;
            auto index = match.lastCapturedIndex();

            if (match_start == -1 || match.capturedStart(index) < match_start)
            {
                match_start = match.capturedStart(index);
                match_length = match.capturedLength(index);
                rule = r;
            }
        }

        if (match_start == -1)
            break;

        setFormat(match_start, match_length, rule.format);
        offset = match_start + match_length;
        state = rule.state_out;
    }

    setCurrentBlockState(state);
}