aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2019-02-11 18:15:32 +0100
committerThomas White <taw@physics.org>2019-03-11 16:49:36 +0100
commit24ce9e4ac098d7744fb23f535eb97f3375425fd8 (patch)
tree5f8d9a85dd1761e51e0905cbaea0e20a5e299d43 /libcrystfel
parent9a3ef1de0b661085a26d9be60bcff9e261783acd (diff)
Symmetry operation parser using Flex/Bison
Diffstat (limited to 'libcrystfel')
-rw-r--r--libcrystfel/CMakeLists.txt10
-rw-r--r--libcrystfel/src/symmetry.c35
-rw-r--r--libcrystfel/src/symop.l51
-rw-r--r--libcrystfel/src/symop.y106
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");
+}