aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2021-10-28 15:00:56 +0200
committerThomas White <taw@physics.org>2021-10-28 15:00:56 +0200
commit3dfb24e9cacf8bc62f39b0de37c5b0ddceba9e71 (patch)
treeef709dab75a8527675751424d8e55b06070aa098
parent86633959138c6ec528c8cf635c6f0d39d79b61cc (diff)
Make symmetry operation parser re-entrant
Fixes: https://gitlab.desy.de/thomas.white/crystfel/-/issues/1
-rw-r--r--libcrystfel/src/symmetry.c19
-rw-r--r--libcrystfel/src/symop.l7
-rw-r--r--libcrystfel/src/symop.y24
-rw-r--r--tests/meson.build3
-rw-r--r--tests/symop_parse.c68
5 files changed, 99 insertions, 22 deletions
diff --git a/libcrystfel/src/symmetry.c b/libcrystfel/src/symmetry.c
index 312470c7..6cda54a2 100644
--- a/libcrystfel/src/symmetry.c
+++ b/libcrystfel/src/symmetry.c
@@ -40,6 +40,7 @@
#include "utils.h"
#include "integer_matrix.h"
#include "symop-parse.h"
+#define YYSTYPE SYMOPSTYPE
#include "symop-lex.h"
@@ -1623,11 +1624,14 @@ RationalMatrix *parse_symmetry_operation(const char *s)
YY_BUFFER_STATE b;
RationalMatrix *m;
int r;
+ void *scanner;
m = rtnl_mtx_new(3, 3);
- b = symop_scan_string(s);
- r = symopparse(m, NULL);
- symop_delete_buffer(b);
+ symoplex_init(&scanner);
+ b = symop_scan_string(s, scanner);
+ r = symopparse(scanner, m, NULL);
+ symop_delete_buffer(b, scanner);
+ symoplex_destroy(scanner);
if ( r ) {
ERROR("Failed to parse '%s'\n", s);
@@ -1669,13 +1673,16 @@ SymOpList *parse_symmetry_operations(const char *s)
RationalMatrix *m;
SymOpList *list;
int r;
+ void *scanner;
m = rtnl_mtx_new(3, 3); /* Scratch space for parser */
list = new_symoplist(); /* The result we want */
- b = symop_scan_string(s);
- r = symopparse(m, list);
- symop_delete_buffer(b);
+ symoplex_init(&scanner);
+ b = symop_scan_string(s, scanner);
+ r = symopparse(scanner, m, list);
+ symop_delete_buffer(b, scanner);
+ symoplex_destroy(scanner);
rtnl_mtx_free(m);
if ( r ) {
diff --git a/libcrystfel/src/symop.l b/libcrystfel/src/symop.l
index f4b2a79e..a755707b 100644
--- a/libcrystfel/src/symop.l
+++ b/libcrystfel/src/symop.l
@@ -27,18 +27,17 @@
*/
%{
- #define YYDEBUG 1
- #include "rational.h"
#include "symop-parse.h"
+ #define YYSTYPE SYMOPSTYPE
%}
%option prefix="symop"
-%option noyywrap nounput noinput
+%option noyywrap nounput noinput reentrant bison-bridge
%%
[,] { return COMMA; }
-[0-9]+ { symoplval.n = atoi(yytext); return NUMBER; }
+[0-9]+ { yylval->n = atoi(yytext); return NUMBER; }
[/] { return DIVIDE; }
[+] { return PLUS; }
[-] { return MINUS; }
diff --git a/libcrystfel/src/symop.y b/libcrystfel/src/symop.y
index 08584594..80712359 100644
--- a/libcrystfel/src/symop.y
+++ b/libcrystfel/src/symop.y
@@ -32,14 +32,16 @@
#include "rational.h"
#include "symmetry.h"
- extern int symoplex();
- extern int symopparse(RationalMatrix *m, SymOpList *list);
- void symoperror(RationalMatrix *m, SymOpList *list, const char *s);
+ #include "symop-parse.h"
+ #include "symop-lex.h"
+
+ void symoperror(void *scanner, RationalMatrix *m, SymOpList *list, const char *s);
%}
%define api.prefix {symop}
-
-%parse-param {RationalMatrix *m} {SymOpList *list}
+%define api.pure full
+%parse-param {void *scanner} {RationalMatrix *m} {SymOpList *list}
+%lex-param {void *scanner}
%code requires {
#include "symmetry.h"
@@ -70,19 +72,19 @@
%type <r> fraction
%{
-static int try_add_symop(SymOpList *list, RationalMatrix *m, int complain)
+static int try_add_symop(void *scanner, SymOpList *list, RationalMatrix *m, int complain)
{
if ( list == NULL ) {
/* Only complain if this isn't the only operation provided */
if ( complain ) {
- yyerror(m, list, "Must be a single symmetry operation");
+ yyerror(scanner, m, list, "Must be a single symmetry operation");
}
return 1;
} else {
IntegerMatrix *im;
im = intmat_from_rtnl_mtx(m);
if ( im == NULL ) {
- yyerror(m, list, "Symmetry operations must all be integer");
+ yyerror(scanner, m, list, "Symmetry operations must all be integer");
return 1;
} else {
add_symop(list, im);
@@ -95,8 +97,8 @@ static int try_add_symop(SymOpList *list, RationalMatrix *m, int complain)
%%
symoplist:
- symop { try_add_symop(list, m, 0); }
-| symoplist SEMICOLON symop { if ( try_add_symop(list, m, 1) ) YYERROR; }
+ symop { try_add_symop(scanner, list, m, 0); }
+| symoplist SEMICOLON symop { if ( try_add_symop(scanner, list, m, 1) ) YYERROR; }
;
symop:
@@ -135,6 +137,6 @@ fraction:
%%
-void symoperror(RationalMatrix *m, SymOpList *list, const char *s) {
+void symoperror(void *scanner, RationalMatrix *m, SymOpList *list, const char *s) {
printf("Error: %s\n", s);
}
diff --git a/tests/meson.build b/tests/meson.build
index 5ad19672..6f2822b7 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -41,7 +41,8 @@ simple_tests = ['ambi_check',
'evparse4',
'evparse5',
'evparse6',
- 'evparse7']
+ 'evparse7',
+ 'symop_parse']
foreach name : simple_tests
exe = executable(name, ''.join([name, '.c']),
diff --git a/tests/symop_parse.c b/tests/symop_parse.c
new file mode 100644
index 00000000..0865ff9b
--- /dev/null
+++ b/tests/symop_parse.c
@@ -0,0 +1,68 @@
+/*
+ * symop_parse.c
+ *
+ * Check that symmetry operation parsing works
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 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 <string.h>
+#include <stdarg.h>
+
+#include <symmetry.h>
+#include <rational.h>
+
+int main(int argc, char *argv[])
+{
+ int r = 0;
+ RationalMatrix *mtx;
+ SymOpList *sym;
+
+ mtx = parse_symmetry_operation("h,k,l");
+ if ( !rtnl_mtx_is_identity(mtx) ) {
+ printf("h,k,l not an identity:\n");
+ rtnl_mtx_print(mtx);
+ r = 1;
+ }
+
+ mtx = parse_symmetry_operation("k,h,-l");
+
+ mtx = parse_symmetry_operation("h,k,l");
+ if ( !rtnl_mtx_is_identity(mtx) ) {
+ printf("h,k,l not an identity on second attempt:\n");
+ rtnl_mtx_print(mtx);
+ r = 1;
+ }
+
+ sym = parse_symmetry_operations("h,k,l;k,h,-l;-h,-k,l");
+ if ( sym == NULL ) r = 1;
+
+ mtx = parse_symmetry_operation("h,k,fail");
+ if ( mtx != NULL ) r = 1;
+
+ sym = parse_symmetry_operations("k,h,-l;h,k,fail;h,k,l");
+ if ( sym != NULL ) r = 1;
+
+ return r;
+}