diff options
-rw-r--r-- | libcrystfel/CMakeLists.txt | 10 | ||||
-rw-r--r-- | libcrystfel/src/symmetry.c | 35 | ||||
-rw-r--r-- | libcrystfel/src/symop.l | 51 | ||||
-rw-r--r-- | libcrystfel/src/symop.y | 106 |
4 files changed, 184 insertions, 18 deletions
diff --git a/libcrystfel/CMakeLists.txt b/libcrystfel/CMakeLists.txt index bd4f44ca..014d2a5a 100644 --- a/libcrystfel/CMakeLists.txt +++ b/libcrystfel/CMakeLists.txt @@ -7,6 +7,8 @@ find_package(PINKINDEXER) find_package(NBP) find_package(FDIP) find_package(ZLIB REQUIRED) +find_package(FLEX REQUIRED) +find_package(BISON REQUIRED) pkg_search_module(FFTW fftw3) set(HAVE_CURSES ${CURSES_FOUND}) @@ -30,6 +32,12 @@ endif() configure_file(config.h.cmake.in config.h) +bison_target(symopp src/symop.y ${CMAKE_CURRENT_BINARY_DIR}/symop-parse.c COMPILE_FLAGS --report=all) +flex_target(symopl src/symop.l ${CMAKE_CURRENT_BINARY_DIR}/symop-lex.c + DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/symop-lex.h) +add_flex_bison_dependency(symopl symopp) +include_directories(${PROJECT_SOURCE_DIR}/src) + set(LIBCRYSTFEL_SOURCES src/reflist.c src/utils.c @@ -63,6 +71,8 @@ set(LIBCRYSTFEL_SOURCES src/taketwo.c src/xgandalf.c src/rational.c + ${BISON_symopp_OUTPUTS} + ${FLEX_symopl_OUTPUTS} ) if (HAVE_FFTW) diff --git a/libcrystfel/src/symmetry.c b/libcrystfel/src/symmetry.c index 06cc368c..19c754ea 100644 --- a/libcrystfel/src/symmetry.c +++ b/libcrystfel/src/symmetry.c @@ -41,6 +41,8 @@ #include "symmetry.h" #include "utils.h" #include "integer_matrix.h" +#include "symop-parse.h" +#include "symop-lex.h" /** @@ -1713,28 +1715,25 @@ static IntegerMatrix *parse_symmetry_operation(const char *s) SymOpList *parse_symmetry_operations(const char *s) { - SymOpList *sol; - char **ops; - int n, i; + YY_BUFFER_STATE b; + RationalMatrix *m; + int r; - sol = new_symoplist(); - if ( sol == NULL ) return NULL; + m = rtnl_mtx_new(3, 3); + b = symop_scan_string(s); + r = symopparse(m); + symop_delete_buffer(b); - n = assplode(s, ";:", &ops, ASSPLODE_NONE); - for ( i=0; i<n; i++ ) { - IntegerMatrix *m; - m = parse_symmetry_operation(ops[i]); - if ( m != NULL ) { - add_symop(sol, m); - } else { - ERROR("Invalid symmetry operation '%s'\n", ops[i]); - /* Try the next one */ - } - free(ops[i]); + if ( r ) { + ERROR("Failed to parse '%s'\n", s); + rtnl_mtx_free(m); + return NULL; } - free(ops); - return sol; + STATUS("Parsed OK\n"); + rtnl_mtx_print(m); + + return NULL; } diff --git a/libcrystfel/src/symop.l b/libcrystfel/src/symop.l new file mode 100644 index 00000000..b00b35b4 --- /dev/null +++ b/libcrystfel/src/symop.l @@ -0,0 +1,51 @@ +/* + * symop.l + * + * Lexical scanner for symmetry operations + * + * Copyright © 2019 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2019 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL 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 3 of the License, or + * (at your option) any later version. + * + * CrystFEL 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 CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + +%{ + #define YYDEBUG 1 + #include "rational.h" + #include "symop-parse.h" +%} + +%option prefix="symop" +%option noyywrap nounput noinput + +%% + +[,] { return COMMA; } +[0-9]+ { symoplval.n = atoi(yytext); return NUMBER; } +[/] { return DIVIDE; } +[+] { return PLUS; } +[-] { return MINUS; } +[ahx] { return H; } +[bky] { return K; } +[clz] { return L; } +[(] { return OPENB; } +[)] { return CLOSEB; } + +%% diff --git a/libcrystfel/src/symop.y b/libcrystfel/src/symop.y new file mode 100644 index 00000000..4aec791a --- /dev/null +++ b/libcrystfel/src/symop.y @@ -0,0 +1,106 @@ +/* + * symop.y + * + * Parser for symmetry operations + * + * Copyright © 2019 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2019 Thomas White <taw@physics.org> + * + * This file is part of CrystFEL. + * + * CrystFEL 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 3 of the License, or + * (at your option) any later version. + * + * CrystFEL 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 CrystFEL. If not, see <http://www.gnu.org/licenses/>. + * + */ + +%{ + #include <stdio.h> + + #include "rational.h" + + extern int symoplex(); + extern int symopparse(RationalMatrix *m); + void symoperror(RationalMatrix *m, const char *s); +%} + +%define api.prefix {symop} + +%parse-param {RationalMatrix *m} + +%union { + RationalMatrix *m; /* Full rational matrix */ + Rational rv[3]; /* Rational vector, e.g. '1/2h+3k' */ + Rational r; /* Rational number */ + int n; /* Just a number */ +} + +%token COMMA +%token NUMBER +%token OPENB CLOSEB +%token H K L + +%left PLUS MINUS +%left DIVIDE +%precedence MUL +%precedence NEG + +%type <m> symop +%type <rv> axexpr +%type <rv> part +%type <n> NUMBER +%type <r> fraction + +%% + +symop: + axexpr COMMA axexpr COMMA axexpr { rtnl_mtx_set(m, 0, 0, $1[0]); + rtnl_mtx_set(m, 0, 1, $1[1]); + rtnl_mtx_set(m, 0, 2, $1[2]); + rtnl_mtx_set(m, 1, 0, $3[0]); + rtnl_mtx_set(m, 1, 1, $3[1]); + rtnl_mtx_set(m, 1, 2, $3[2]); + rtnl_mtx_set(m, 2, 0, $5[0]); + rtnl_mtx_set(m, 2, 1, $5[1]); + rtnl_mtx_set(m, 2, 2, $5[2]); + } +; + +axexpr: + part { int i; for ( i=0; i<3; i++ ) $$[i] = $1[i]; } +| axexpr PLUS axexpr { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_add($1[i], $3[i]); } +| axexpr MINUS axexpr { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_sub($1[i], $3[i]); } +| MINUS axexpr %prec NEG { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_sub(rtnl_zero(), $2[i]); } +| OPENB axexpr CLOSEB { int i; for ( i=0; i<3; i++ ) $$[i] = $2[i]; } +| axexpr DIVIDE NUMBER { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_div($1[i], rtnl($3, 1)); } +| NUMBER axexpr %prec MUL { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_mul($2[i], rtnl($1, 1)); } +| fraction axexpr %prec MUL { int i; for ( i=0; i<3; i++ ) $$[i] = rtnl_mul($2[i], $1); } +; + +part: + H { $$[0] = rtnl(1, 1); $$[1] = rtnl_zero(); $$[2] = rtnl_zero(); } +| K { $$[1] = rtnl(1, 1); $$[0] = rtnl_zero(); $$[2] = rtnl_zero(); } +| L { $$[2] = rtnl(1, 1); $$[0] = rtnl_zero(); $$[1] = rtnl_zero(); } +; + +fraction: + NUMBER DIVIDE NUMBER { $$ = rtnl($1, $3); } +; + +%% + +void symoperror(RationalMatrix *m, const char *s) { + printf("Error\n"); +} |