dotnet and php bindings have bitrotted, but packrat is faster now
This commit is contained in:
commit
8a545c4dcf
8 changed files with 94 additions and 37 deletions
35
.travis.yml
35
.travis.yml
|
|
@ -1,3 +1,5 @@
|
||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
language: c
|
language: c
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
|
|
@ -8,35 +10,43 @@ matrix:
|
||||||
include:
|
include:
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-1.9.3-p484
|
rvm: ruby-1.9.3-p551
|
||||||
env: BINDINGS=ruby
|
env: BINDINGS=ruby
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-1.9.3-p484
|
rvm: ruby-1.9.3-p551
|
||||||
env: BINDINGS=ruby CC=clang
|
env: BINDINGS=ruby CC=clang
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-2.0.0-p353
|
rvm: ruby-2.0.0-p647
|
||||||
env: BINDINGS=ruby
|
env: BINDINGS=ruby
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-2.0.0-p353
|
rvm: ruby-2.0.0-p647
|
||||||
env: BINDINGS=ruby CC=clang
|
env: BINDINGS=ruby CC=clang
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-2.1.0
|
rvm: ruby-2.1.7
|
||||||
env: BINDINGS=ruby
|
env: BINDINGS=ruby
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm: ruby-2.1.0
|
rvm: ruby-2.1.7
|
||||||
|
env: BINDINGS=ruby CC=clang
|
||||||
|
- compiler: gcc
|
||||||
|
language: ruby
|
||||||
|
rvm: ruby-2.2.3
|
||||||
|
env: BINDINGS=ruby
|
||||||
|
- compiler: clang
|
||||||
|
language: ruby
|
||||||
|
rvm: ruby-2.2.3
|
||||||
env: BINDINGS=ruby CC=clang
|
env: BINDINGS=ruby CC=clang
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: python
|
language: python
|
||||||
python: "2.7"
|
python: "2.7.10"
|
||||||
env: BINDINGS=python
|
env: BINDINGS=python
|
||||||
- compiler: clang
|
- compiler: clang
|
||||||
language: python
|
language: python
|
||||||
python: "2.7"
|
python: "2.7.10"
|
||||||
env: BINDINGS=python CC=clang
|
env: BINDINGS=python CC=clang
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: perl
|
language: perl
|
||||||
|
|
@ -87,17 +97,16 @@ matrix:
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
language: cpp
|
language: cpp
|
||||||
env: BINDINGS=cpp
|
env: BINDINGS=cpp
|
||||||
- compiler: gcc
|
- compiler: clang
|
||||||
language: cpp
|
language: cpp
|
||||||
env: BINDINGS=cpp CC=clang
|
env: BINDINGS=cpp CC=clang
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -y lcov
|
- sudo apt-get install -y lcov
|
||||||
- gem install coveralls-lcov
|
- gem install coveralls-lcov
|
||||||
- if [ "$BINDINGS" != "none" ]; then sudo apt-get install -qq swig; fi
|
- if [ "$BINDINGS" != "none" ]; then sudo sh -c 'echo "deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse" >> /etc/apt/sources.list'; sudo apt-get update -qq; sudo apt-get install -yqq swig3.0/trusty-backports; fi
|
||||||
- if [ "$BINDINGS" == "perl" ]; then sudo add-apt-repository ppa:dns/irc -y; sudo apt-get update -qq; sudo apt-get install -qq swig=2.0.8-1irc1~12.04; fi
|
- if [ "$BINDINGS" == "python" ]; then sudo apt-get install -yqq python-dev; fi
|
||||||
- if [ "$BINDINGS" == "python" ]; then sudo apt-get install -qq python-dev; fi
|
- if [ "$BINDINGS" == "dotnet" ]; then sudo add-apt-repository ppa:directhex/monoxide -y; sudo apt-get update -qq; sudo apt-get install -yqq mono-devel mono-mcs nunit nunit-console; mozroots --import --sync; fi
|
||||||
- if [ "$BINDINGS" == "dotnet" ]; then sudo add-apt-repository ppa:directhex/monoxide -y; sudo apt-get update -qq; sudo apt-get install -y -qq mono-devel mono-mcs nunit nunit-console; fi
|
|
||||||
install: true
|
install: true
|
||||||
before_script:
|
before_script:
|
||||||
- if [ "$BINDINGS" == "php" ]; then phpenv config-add src/bindings/php/hammer.ini; fi
|
- if [ "$BINDINGS" == "php" ]; then phpenv config-add src/bindings/php/hammer.ini; fi
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ if platform.system() == 'Windows':
|
||||||
default_install_dir = 'build' # no obvious place for installation on Windows
|
default_install_dir = 'build' # no obvious place for installation on Windows
|
||||||
|
|
||||||
vars = Variables(None, ARGUMENTS)
|
vars = Variables(None, ARGUMENTS)
|
||||||
vars.Add(PathVariable('DESTDIR', 'Root directory to install in (useful for packaging scripts)', None, PathVariable.PathIsDirCreate))
|
vars.Add(PathVariable('DESTDIR', "Root directory to install in (useful for packaging scripts)", None, PathVariable.PathIsDirCreate))
|
||||||
vars.Add(PathVariable('prefix', 'Where to install in the FHS', default_install_dir, PathVariable.PathAccept))
|
vars.Add(PathVariable('prefix', "Where to install in the FHS", "/usr/local", PathVariable.PathAccept))
|
||||||
vars.Add(ListVariable('bindings', 'Language bindings to build', 'none', ['cpp', 'dotnet', 'perl', 'php', 'python', 'ruby']))
|
vars.Add(ListVariable('bindings', 'Language bindings to build', 'none', ['cpp', 'dotnet', 'perl', 'php', 'python', 'ruby']))
|
||||||
|
|
||||||
tools = ['default', 'scanreplace']
|
tools = ['default', 'scanreplace']
|
||||||
|
|
|
||||||
|
|
@ -11,31 +11,76 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "../src/hammer.h"
|
#include "../src/hammer.h"
|
||||||
|
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
const HParser* document = NULL;
|
const HParser* document = NULL;
|
||||||
|
|
||||||
void init_parser(void)
|
void init_parser(void)
|
||||||
{
|
{
|
||||||
// CORE
|
// CORE
|
||||||
HParser *digit = h_ch_range(0x30, 0x39);
|
const HParser *digit = h_ch_range(0x30, 0x39);
|
||||||
HParser *alpha = h_choice(h_ch_range(0x41, 0x5a), h_ch_range(0x61, 0x7a), NULL);
|
const HParser *alpha = h_choice(h_ch_range(0x41, 0x5a), h_ch_range(0x61, 0x7a), NULL);
|
||||||
|
|
||||||
// AUX.
|
// AUX.
|
||||||
HParser *plus = h_ch('+');
|
const HParser *plus = h_ch('+');
|
||||||
HParser *slash = h_ch('/');
|
const HParser *slash = h_ch('/');
|
||||||
HParser *equals = h_ch('=');
|
const HParser *equals = h_ch('=');
|
||||||
|
|
||||||
HParser *bsfdig = h_choice(alpha, digit, plus, slash, NULL);
|
const HParser *bsfdig = h_choice(alpha, digit, plus, slash, NULL);
|
||||||
HParser *bsfdig_4bit = h_in((uint8_t *)"AEIMQUYcgkosw048", 16);
|
const HParser *bsfdig_4bit = h_choice(
|
||||||
HParser *bsfdig_2bit = h_in((uint8_t *)"AQgw", 4);
|
h_ch('A'), h_ch('E'), h_ch('I'), h_ch('M'), h_ch('Q'), h_ch('U'),
|
||||||
HParser *base64_3 = h_repeat_n(bsfdig, 4);
|
h_ch('Y'), h_ch('c'), h_ch('g'), h_ch('k'), h_ch('o'), h_ch('s'),
|
||||||
HParser *base64_2 = h_sequence(bsfdig, bsfdig, bsfdig_4bit, equals, NULL);
|
h_ch('w'), h_ch('0'), h_ch('4'), h_ch('8'), NULL);
|
||||||
HParser *base64_1 = h_sequence(bsfdig, bsfdig_2bit, equals, equals, NULL);
|
const HParser *bsfdig_2bit = h_choice(h_ch('A'), h_ch('Q'), h_ch('g'), h_ch('w'), NULL);
|
||||||
HParser *base64 = h_sequence(h_many(base64_3),
|
|
||||||
h_optional(h_choice(base64_2,
|
|
||||||
base64_1, NULL)),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
document = h_sequence(h_whitespace(base64), h_whitespace(h_end_p()), NULL);
|
const HParser *base64_quad = h_sequence(bsfdig, bsfdig, bsfdig, bsfdig, NULL);
|
||||||
|
const HParser *base64_quads = h_many(base64_quad);
|
||||||
|
|
||||||
|
const HParser *base64_2 = h_sequence(bsfdig, bsfdig, bsfdig_4bit, equals, h_end_p(), NULL);
|
||||||
|
const HParser *base64_1 = h_sequence(bsfdig, bsfdig_2bit, equals, equals, h_end_p(), NULL);
|
||||||
|
const HParser *base64_ending = h_choice(h_end_p(), base64_2, base64_1, NULL);
|
||||||
|
const HParser *base64 = h_sequence(base64_quads, base64_ending, NULL);
|
||||||
|
// why does this parse "A=="?!
|
||||||
|
// why does this parse "aaA=" but not "aA=="?!
|
||||||
|
|
||||||
|
document = base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#define TRUE (1)
|
||||||
|
#define FALSE (0)
|
||||||
|
|
||||||
|
void assert_parse(int expected, char *data) {
|
||||||
|
const HParseResult *result;
|
||||||
|
|
||||||
|
size_t datasize = strlen(data);
|
||||||
|
result = h_parse(document, (void*)data, datasize);
|
||||||
|
if((result != NULL) != expected) {
|
||||||
|
fprintf(stderr, "Test failed: %s\n", data);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Test succeeded: %s\n", data);
|
||||||
|
fprintf(stderr, "parsed=%lld bytes\n", result->bit_length/8);
|
||||||
|
h_pprint(stdout, result->ast, 0, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
assert_parse(TRUE, "");
|
||||||
|
assert_parse(TRUE, "YQ==");
|
||||||
|
assert_parse(TRUE, "YXU=");
|
||||||
|
assert_parse(TRUE, "YXVy");
|
||||||
|
assert_parse(TRUE, "QVVSIFNBUkFG");
|
||||||
|
assert_parse(TRUE, "QVVSIEhFUlUgU0FSQUY=");
|
||||||
|
assert_parse(FALSE, "A");
|
||||||
|
assert_parse(FALSE, "A=");
|
||||||
|
assert_parse(FALSE, "A==");
|
||||||
|
assert_parse(FALSE, "AAA==");
|
||||||
|
assert_parse(FALSE, "aa==");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -49,6 +94,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
init_parser();
|
init_parser();
|
||||||
|
|
||||||
|
test();
|
||||||
|
|
||||||
inputsize = fread(input, 1, sizeof(input), stdin);
|
inputsize = fread(input, 1, sizeof(input), stdin);
|
||||||
fprintf(stderr, "inputsize=%zu\ninput=", inputsize);
|
fprintf(stderr, "inputsize=%zu\ninput=", inputsize);
|
||||||
fwrite(input, 1, inputsize, stderr);
|
fwrite(input, 1, inputsize, stderr);
|
||||||
|
|
|
||||||
|
|
@ -188,9 +188,10 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
|
||||||
// check to see if there is already a result for this object...
|
// check to see if there is already a result for this object...
|
||||||
if (!m) {
|
if (!m) {
|
||||||
// It doesn't exist, so create a dummy result to cache
|
// It doesn't exist, so create a dummy result to cache
|
||||||
HLeftRec *base = a_new(HLeftRec, 1);
|
HLeftRec *base = NULL;
|
||||||
// But only cache it now if there's some chance it could grow; primitive parsers can't
|
// But only cache it now if there's some chance it could grow; primitive parsers can't
|
||||||
if (parser->vtable->higher) {
|
if (parser->vtable->higher) {
|
||||||
|
base = a_new(HLeftRec, 1);
|
||||||
base->seed = NULL; base->rule = parser; base->head = NULL;
|
base->seed = NULL; base->rule = parser; base->head = NULL;
|
||||||
h_slist_push(state->lr_stack, base);
|
h_slist_push(state->lr_stack, base);
|
||||||
// cache it
|
// cache it
|
||||||
|
|
@ -207,7 +208,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
|
||||||
cached->input_stream = state->input_stream;
|
cached->input_stream = state->input_stream;
|
||||||
}
|
}
|
||||||
// setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one
|
// setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one
|
||||||
if (NULL == base->head) {
|
if (!base || NULL == base->head) {
|
||||||
h_hashtable_put(state->cache, key, cached_result(state, tmp_res));
|
h_hashtable_put(state->cache, key, cached_result(state, tmp_res));
|
||||||
return tmp_res;
|
return tmp_res;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ csfiles = os.path.join(thisdir, "*.cs")
|
||||||
# target to stand in for.
|
# target to stand in for.
|
||||||
hammer_wrap = AlwaysBuild(dotnetenv.Command(['hammer_wrap.c'], swig,
|
hammer_wrap = AlwaysBuild(dotnetenv.Command(['hammer_wrap.c'], swig,
|
||||||
["rm %s/*.cs || true" % (thisdir,),
|
["rm %s/*.cs || true" % (thisdir,),
|
||||||
"swig $SWIGFLAGS $SOURCE"]))
|
"swig3.0 $SWIGFLAGS $SOURCE"]))
|
||||||
libhammer_dotnet = dotnetenv.SharedLibrary(['hammer_dotnet'], hammer_wrap)
|
libhammer_dotnet = dotnetenv.SharedLibrary(['hammer_dotnet'], hammer_wrap)
|
||||||
hammer_dll = AlwaysBuild(dotnetenv.Command(['hammer.dll'], Glob('ext/*.cs'),
|
hammer_dll = AlwaysBuild(dotnetenv.Command(['hammer.dll'], Glob('ext/*.cs'),
|
||||||
'$CSC -t:library -unsafe -out:$TARGET %s/*.cs $SOURCE' %(thisdir,)))
|
'$CSC -t:library -unsafe -out:$TARGET %s/*.cs $SOURCE' %(thisdir,)))
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ if 'PERL5LIB' in os.environ:
|
||||||
|
|
||||||
swig = ['hammer.i']
|
swig = ['hammer.i']
|
||||||
|
|
||||||
hammer_wrap = perlenv.Command(['hammer_wrap.c', 'hammer.pm'], swig, "swig $SWIGFLAGS $SOURCE")
|
hammer_wrap = perlenv.Command(['hammer_wrap.c', 'hammer.pm'], swig, "swig3.0 $SWIGFLAGS $SOURCE")
|
||||||
makefile = perlenv.Command(['Makefile'], ['Makefile.PL'], "perl $SOURCE CC=" + perlenv['ENV']['CC'])
|
makefile = perlenv.Command(['Makefile'], ['Makefile.PL'], "perl $SOURCE CC=" + perlenv['ENV']['CC'])
|
||||||
|
|
||||||
targetdir = os.path.dirname(str(hammer_wrap[0].path))
|
targetdir = os.path.dirname(str(hammer_wrap[0].path))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ phpenv.Append(LIBS = ['hammer'])
|
||||||
phpenv.Append(LIBPATH = ['../../'])
|
phpenv.Append(LIBPATH = ['../../'])
|
||||||
|
|
||||||
swig = ['hammer.i']
|
swig = ['hammer.i']
|
||||||
bindings_src = phpenv.Command(['hammer.php', 'hammer_wrap.c', 'php_hammer.h'], swig, 'swig -php -DHAMMER_INTERNAL__NO_STDARG_H -Isrc/ $SOURCE')
|
bindings_src = phpenv.Command(['hammer.php', 'hammer_wrap.c', 'php_hammer.h'], swig, 'swig3.0 -php -DHAMMER_INTERNAL__NO_STDARG_H -Isrc/ $SOURCE')
|
||||||
libhammer_php = phpenv.SharedLibrary('hammer', ['hammer_wrap.c'])
|
libhammer_php = phpenv.SharedLibrary('hammer', ['hammer_wrap.c'])
|
||||||
Default(swig, bindings_src, libhammer_php)
|
Default(swig, bindings_src, libhammer_php)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ pythonenv = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0)
|
||||||
swig = pythonenv.Command("hammer.i", "../swig/hammer.i", Copy("$TARGET", "$SOURCE"))
|
swig = pythonenv.Command("hammer.i", "../swig/hammer.i", Copy("$TARGET", "$SOURCE"))
|
||||||
setup = ['setup.py']
|
setup = ['setup.py']
|
||||||
pydir = os.path.join(env['BUILD_BASE'], 'src/bindings/python')
|
pydir = os.path.join(env['BUILD_BASE'], 'src/bindings/python')
|
||||||
libhammer_python = pythonenv.Command(['hammer.py', 'hammer_wrap.c'], [swig, setup], 'python ' + os.path.join(pydir, 'setup.py') + ' build_ext --inplace')
|
libhammer_python = pythonenv.Command(['hammer.py', 'hammer_wrap.c'], [swig, setup], 'python ' + os.path.join(pydir, 'setup.py') + ' build_ext --swig=swig3.0 --inplace')
|
||||||
Default(libhammer_python)
|
Default(libhammer_python)
|
||||||
|
|
||||||
pytestenv = pythonenv.Clone()
|
pytestenv = pythonenv.Clone()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue