Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/skia/skia/src/sksl/lex/   (Fast Lexical Analyzer Version 2.6©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  Main.cpp   Sprache: C

 
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "src/sksl/lex/DFA.h"
#include "src/sksl/lex/LexUtil.h"
#include "src/sksl/lex/NFA.h"
#include "src/sksl/lex/NFAtoDFA.h"
#include "src/sksl/lex/RegexNode.h"
#include "src/sksl/lex/RegexParser.h"
#include "src/sksl/lex/TransitionTable.h"

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

/**
 * Processes a .lex file and produces .h and .cpp files which implement a lexical analyzer. The .lex
 * file is a text file with one token definition per line. Each line is of the form:
 * <TOKEN_NAME> = <pattern>
 * where <pattern> is either a regular expression (e.g [0-9]) or a double-quoted literal string.
 */


static constexpr const char HEADER[] =
    "/*\n"
    " * Copyright 2017 Google Inc.\n"
    " *\n"
    " * Use of this source code is governed by a BSD-style license that can be\n"
    " * found in the LICENSE file.\n"
    " */\n"
    "/*****************************************************************************************\n"
    " ******************** This file was generated by sksllex. Do not edit. *******************\n"
    " *****************************************************************************************/\n";

static void writeH(const DFA& dfa, const char* lexer, const char* token,
                   const std::vector<std::string>& tokens, const char* hPath) {
    std::ofstream out(hPath);
    SkASSERT(out.good());
    out << HEADER;
    out << "#ifndef SKSL_" << lexer << "\n";
    out << "#define SKSL_" << lexer << "\n";
    out << "#include \n";
    out << "#include \n";
    out << "namespace SkSL {\n";
    out << "\n";
    out << "struct " << token << " {\n";
    out << " enum class Kind {\n";
    for (const std::string& t : tokens) {
        out << " TK_" << t << ",\n";
    }
    out << " TK_NONE,";
    out << R"(
    };

    )" << token << "() {}";

    out << token << R"((Kind kind, int32_t offset, int32_t length)
    : fKind(kind)
    , fOffset(offset)
    , fLength(length) {}

    Kind fKind      = Kind::TK_NONE;
    int32_t fOffset = -1;
    int32_t fLength = -1;
};

class )" << lexer << R"( {
public:
    void start(std::string_view text) {
        fText = text;
        fOffset = 0;
    }

    )" << token << R"( next();

    struct Checkpoint {
        int32_t fOffset;
    };

    Checkpoint getCheckpoint() const {
        return {fOffset};
    }

    void rewindToCheckpoint(Checkpoint checkpoint) {
        fOffset = checkpoint.fOffset;
    }

private:
    std::string_view fText;
    int32_t fOffset;
};

// namespace
#endif
)";
}

static void writeCPP(const DFA& dfa, const char* lexer, const char* token, const char* include,
                     const char* cppPath) {
    std::ofstream out(cppPath);
    SkASSERT(out.good());
    out << HEADER;
    out << "#include \"" << include << "\"\n";
    out << "\n";
    out << "namespace SkSL {\n";
    out << "\n";

    size_t states = 0;
    for (const auto& row : dfa.fTransitions) {
        states = std::max(states, row.size());
    }
    out << "using State = " << (states <= 256 ? "uint8_t" : "uint16_t") << ";\n";

    // Find the first character mapped in our DFA.
    size_t startChar = 0;
    for (; startChar < dfa.fCharMappings.size(); ++startChar) {
        if (dfa.fCharMappings[startChar] != 0) {
            break;
        }
    }

    // Arbitrarily-chosen character which is greater than startChar, and should not appear in actual
    // input.
    SkASSERT(startChar < 18);
    out << "static constexpr uint8_t kInvalidChar = 18;";
    out << "static constexpr uint8_t kMappings[" << dfa.fCharMappings.size() - startChar << "] = {";
    for (size_t index = startChar; index < dfa.fCharMappings.size(); ++index) {
        out << std::to_string(dfa.fCharMappings[index]) << ", ";
    }
    out << "};\n";

    WriteTransitionTable(out, dfa, states);

    out << "static const uint8_t kAccepts[" << states << "] = {";
    for (size_t i = 0; i < states; ++i) {
        if (i < dfa.fAccepts.size() && dfa.fAccepts[i] != INVALID) {
            out << " " << dfa.fAccepts[i] << ",";
        } else {
            out << " 255,";
        }
    }
    out << "};\n";
    out << "\n";

    out << token << " " << lexer << "::next() {";
    out << R"(
    // Note that we cheat here: normally a lexer needs to worry about the case
    // where a token has a prefix which is not itself a valid token - for instance,
    // maybe we have a valid token 'while', but 'w', 'wh', etc. are not valid
    // tokens. Our grammar doesn't have this property, so we can simplify the logic
    // a bit.
    int32_t startOffset = fOffset;
    State   state = 1;
    for (;;) {
        if (fOffset >= (int32_t)fText.length()) {
            if (startOffset == (int32_t)fText.length() || kAccepts[state] == 255) {
                return )" << token << "(" << token << R"(::Kind::TK_END_OF_FILE, startOffset, 0);
            }
            break;
        }
        uint8_t c = (uint8_t)(fText[fOffset] - )" << startChar << R"();
        if (c >= )" << dfa.fCharMappings.size() - startChar << R"() {
            c = kInvalidChar;
        }
        State newState = get_transition(kMappings[c], state);
        if (!newState) {
            break;
        }
        state = newState;
        ++fOffset;
    }
    Token::Kind kind = ()" << token << R"(::Kind) kAccepts[state];
    return )" << token << R"((kind, startOffset, fOffset - startOffset);
}

// namespace
)";
}

static void process(const char* inPath, const char* lexer, const char* token, const char* hPath,
                    const char* cppPath) {
    NFA nfa;
    std::vector<std::string> tokens;
    tokens.push_back("END_OF_FILE");
    std::string line;
    std::ifstream in(inPath);
    while (std::getline(in, line)) {
        if (line.length() == 0) {
            continue;
        }
        if (line.length() >= 2 && line[0] == '/' && line[1] == '/') {
            continue;
        }
        std::istringstream split(line);
        std::string name, delimiter, pattern;
        if (split >> name >> delimiter >> pattern) {
            SkASSERT(split.eof());
            SkASSERT(name != "");
            SkASSERT(delimiter == "=");
            SkASSERT(pattern != "");
            tokens.push_back(name);
            if (pattern[0] == '"') {
                SkASSERT(pattern.size() > 2 && pattern[pattern.size() - 1] == '"');
                RegexNode node = RegexNode(RegexNode::kChar_Kind, pattern[1]);
                for (size_t i = 2; i < pattern.size() - 1; ++i) {
                    node = RegexNode(RegexNode::kConcat_Kind, node,
                                     RegexNode(RegexNode::kChar_Kind, pattern[i]));
                }
                nfa.addRegex(node);
            }
            else {
                nfa.addRegex(RegexParser().parse(pattern));
            }
        }
    }
    NFAtoDFA converter(&nfa);
    DFA dfa = converter.convert();
    writeH(dfa, lexer, token, tokens, hPath);
    writeCPP(dfa, lexer, token, (std::string("src/sksl/SkSL") + lexer + ".h").c_str(), cppPath);
}

int main(int argc, const char** argv) {
    if (argc != 6) {
        printf("usage: sksllex \n");
        exit(1);
    }
    process(argv[1], argv[2], argv[3], argv[4], argv[5]);
    return 0;
}

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.