Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unidirectional Compilation #155

Merged
merged 7 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
/lttoolbox/lt-append
/lttoolbox/lsx-comp
/lttoolbox/lt-paradigm
/lttoolbox/lt-invert
/lttoolbox/lt-restrict
/lttoolbox/lt-apply-acx
/python/Makefile
/python/Makefile.in
/python/lttoolbox.i
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ AC_PREREQ(2.52)

m4_define([PKG_VERSION_MAJOR], [3])
m4_define([PKG_VERSION_MINOR], [6])
m4_define([PKG_VERSION_PATCH], [9])
xavivars marked this conversation as resolved.
Show resolved Hide resolved
m4_define([PKG_VERSION_PATCH], [10])

AC_INIT([lttoolbox], [PKG_VERSION_MAJOR.PKG_VERSION_MINOR.PKG_VERSION_PATCH], [apertium-stuff@lists.sourceforge.net], [lttoolbox], [https://wiki.apertium.org/wiki/Lttoolbox])

Expand Down
9 changes: 6 additions & 3 deletions lttoolbox/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

h_sources = alphabet.h att_compiler.h buffer.h compiler.h compression.h \
h_sources = acx.h alphabet.h att_compiler.h buffer.h cli.h compiler.h compression.h \
deserialiser.h entry_token.h expander.h file_utils.h fst_processor.h input_file.h lt_locale.h \
match_exe.h match_node.h match_state.h my_stdio.h node.h \
pattern_list.h regexp_compiler.h serialiser.h sorted_vector.h state.h string_utils.h \
transducer.h trans_exe.h xml_parse_util.h xml_walk_util.h exception.h tmx_compiler.h \
ustring.h sorted_vector.hpp
cc_sources = alphabet.cc att_compiler.cc compiler.cc compression.cc entry_token.cc \
cc_sources = acx.cc alphabet.cc att_compiler.cc cli.cc compiler.cc compression.cc entry_token.cc \
expander.cc file_utils.cc fst_processor.cc input_file.cc lt_locale.cc match_exe.cc \
match_node.cc match_state.cc node.cc pattern_list.cc \
regexp_compiler.cc sorted_vector.cc state.cc string_utils.cc transducer.cc \
Expand All @@ -14,7 +14,7 @@ cc_sources = alphabet.cc att_compiler.cc compiler.cc compression.cc entry_token.
library_includedir = $(includedir)/$(PACKAGE_NAME)-$(VERSION_API)/$(PACKAGE_NAME)
library_include_HEADERS = $(h_sources)

bin_PROGRAMS = lt-comp lt-proc lt-expand lt-paradigm lt-tmxcomp lt-tmxproc lt-print lt-trim lt-append lsx-comp
bin_PROGRAMS = lt-comp lt-proc lt-expand lt-paradigm lt-tmxcomp lt-tmxproc lt-print lt-trim lt-append lsx-comp lt-invert lt-restrict lt-apply-acx
instdir = lttoolbox

lib_LTLIBRARIES= liblttoolbox3.la
Expand All @@ -41,6 +41,9 @@ lt_paradigm_SOURCES = lt_paradigm.cc
lt_tmxcomp_SOURCES = lt_tmxcomp.cc
lt_tmxproc_SOURCES = lt_tmxproc.cc
lsx_comp_SOURCES = lt_comp.cc
lt_invert_SOURCES = lt_invert.cc
lt_restrict_SOURCES = lt_restrict.cc
lt_apply_acx_SOURCES = lt_apply_acx.cc

#lt-validate-dictionary: Makefile.am validate-header.sh
# @echo "Creating lt-validate-dictionary script"
Expand Down
61 changes: 61 additions & 0 deletions lttoolbox/acx.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2022 Apertium
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <lttoolbox/acx.h>
#include <lttoolbox/xml_walk_util.h>

const xmlChar* CHAR_NODE = (const xmlChar*)"char";
const xmlChar* EQUIV_NODE = (const xmlChar*)"equiv-char";
const char* VALUE_ATTR = "value";

int32_t get_val(xmlNode* node)
{
UString s = getattr(node, VALUE_ATTR);
if (s.empty()) {
error_and_die(node, "Missing value attribute.");
}
std::vector<int32_t> v;
ustring_to_vec32(s, v);
if (v.size() > 1) {
error_and_die(node, "Expected a single character in value attribute, but found %d.", v.size());
}
return v[0];
}

std::map<int32_t, sorted_vector<int32_t>> readACX(const char* file)
{
std::map<int32_t, sorted_vector<int32_t>> acx;
xmlNode* top_node = load_xml(file);
for (auto char_node : children(top_node)) {
if (!xmlStrEqual(char_node->name, CHAR_NODE)) {
error_and_die(char_node, "Expected <char> but found <%s>.",
(const char*)char_node->name);
}
int32_t key = get_val(char_node);
sorted_vector<int32_t> vec;
for (auto equiv_node : children(char_node)) {
if (!xmlStrEqual(equiv_node->name, EQUIV_NODE)) {
error_and_die(char_node, "Expected <equiv-char> but found <%s>.",
(const char*)equiv_node->name);
}
vec.insert(get_val(equiv_node));
}
if (!vec.empty()) {
acx.insert(std::make_pair(key, vec));
}
}
return acx;
}
25 changes: 25 additions & 0 deletions lttoolbox/acx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 Apertium
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ACXPARSEUTIL_
#define _ACXPARSEUTIL_

#include <lttoolbox/sorted_vector.hpp>
#include <map>

std::map<int32_t, sorted_vector<int32_t>> readACX(const char* file);

#endif
193 changes: 193 additions & 0 deletions lttoolbox/cli.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* Copyright (C) 2022 Apertium
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#include <lttoolbox/cli.h>

#include <cstdlib>
#include <iostream>
#include <libgen.h>
#include <string>
#include <getopt.h>

CLI::CLI(std::string desc, std::string ver)
{
description = desc;
version = ver;
}

CLI::CLI(std::string desc)
{
description = desc;
}

CLI::~CLI()
{
}

void CLI::add_str_arg(char short_flag, std::string long_flag,
std::string desc, std::string arg)
{
options.push_back({.short_opt=short_flag, .long_opt=long_flag,
.desc=desc, .is_bool=false, .var=arg});
}

void CLI::add_bool_arg(char short_flag, std::string long_flag,
std::string desc)
{
options.push_back({.short_opt=short_flag, .long_opt=long_flag,
.desc=desc, .is_bool=true, .var=""});
}

void CLI::add_file_arg(std::string name, bool optional)
{
file_args.push_back(std::make_pair(name, optional));
if (!optional) min_file_args++;
}

void CLI::set_epilog(std::string e)
{
epilog = e;
}

void CLI::print_usage()
{
if (!prog_name.empty()) {
std::cout << prog_name;
if (!version.empty()) {
std::cout << " v" << version;
}
std::cout << ": " << description << std::endl;
std::cout << "USAGE: " << prog_name;
std::string bargs;
std::string sargs;
for (auto& it : options) {
if (it.is_bool) {
bargs += it.short_opt;
} else {
sargs += " [-";
sargs += it.short_opt;
sargs += ' ';
sargs += it.var;
sargs += ']';
}
}
if (!bargs.empty()) {
std::cout << " [-" << bargs << "]";
}
std::cout << sargs;
int depth = 0;
for (auto& it : file_args) {
std::cout << ' ';
if (it.second) {
std::cout << '[';
depth += 1;
}
std::cout << it.first;
}
while (depth-- > 0) std::cout << "]";
std::cout << std::endl;
for (auto& it : options) {
std::cout << " -" << it.short_opt;
#if HAVE_GETOPT_LONG
std::cout << ", --" << it.long_opt << ':';
for (size_t i = it.long_opt.size(); i < 20; i++) {
std::cout << ' ';
}
#else
std::cout << ": ";
#endif
std::cout << it.desc << std::endl;
}
if (!epilog.empty()) {
std::cout << epilog << std::endl;
}
}
exit(EXIT_FAILURE);
}

void CLI::parse_args(int argc, char* argv[])
{
prog_name = basename(argv[0]);
std::string arg_str;
#if HAVE_GETOPT_LONG
struct option long_options[options.size()];
int option_index = 0;
#endif
for (size_t i = 0; i < options.size(); i++) {
arg_str += options[i].short_opt;
if (!options[i].is_bool) arg_str += ':';
#if HAVE_GETOPT_LONG
long_options[i].name = options[i].long_opt.c_str();
long_options[i].has_arg = (options[i].is_bool ? no_argument : required_argument);
long_options[i].flag = 0;
long_options[i].val = options[i].short_opt;
#endif
}

while (true) {
#if HAVE_GETOPT_LONG
int cnt = getopt_long(argc, argv, arg_str.c_str(), long_options, &option_index);
#else
int cnt = getopt(argc, argv, arg_str.c_str());
#endif
if (cnt == -1) break;

bool found = false;
for (auto& it : options) {
if (it.short_opt == cnt) {
found = true;
if (it.short_opt == 'v' && it.long_opt == "version") {
std::cout << prog_name << " version " << version << std::endl;
exit(EXIT_SUCCESS);
}
if (it.is_bool) {
bools[it.long_opt] = true;
} else {
strs[it.long_opt].push_back(optarg);
}
break;
}
}
if (!found || cnt == 'h') {
print_usage();
}
}
while (optind < argc) {
files.push_back(argv[optind++]);
}
if (files.size() < min_file_args || files.size() > file_args.size()) {
print_usage();
}
while (files.size() < file_args.size()) {
files.push_back("");
}
}

std::map<std::string, std::vector<std::string>>& CLI::get_strs()
{
return strs;
}

std::map<std::string, bool>& CLI::get_bools()
{
return bools;
}

std::vector<std::string>& CLI::get_files()
{
return files;
}
60 changes: 60 additions & 0 deletions lttoolbox/cli.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 Apertium
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/

#include <string>
#include <vector>
#include <map>

class CLI {
private:
struct CLIOption {
char short_opt;
std::string long_opt;
std::string desc;
bool is_bool;
std::string var;
};

std::string description;
std::string version;
std::string epilog;

std::vector<CLIOption> options;
std::vector<std::pair<std::string, bool>> file_args;
size_t min_file_args = 0;

std::map<std::string, std::vector<std::string>> strs;
std::map<std::string, bool> bools;
std::vector<std::string> files;

std::string prog_name;

public:
CLI(std::string desc, std::string version);
CLI(std::string desc);
~CLI();
void add_str_arg(char short_flag, std::string long_flag, std::string desc,
std::string arg);
void add_bool_arg(char short_flag, std::string long_flag, std::string desc);
void add_file_arg(std::string name, bool optional = true);
void set_epilog(std::string e);
void print_usage();
void parse_args(int argc, char* argv[]);
std::map<std::string, std::vector<std::string>>& get_strs();
std::map<std::string, bool>& get_bools();
std::vector<std::string>& get_files();
};
Loading