Skip to content

Commit

Permalink
Add basic support for Haskell (no documentation).
Browse files Browse the repository at this point in the history
  • Loading branch information
skvadrik committed May 26, 2024
1 parent b527e95 commit 4e78ef8
Show file tree
Hide file tree
Showing 69 changed files with 11,987 additions and 587 deletions.
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ option(RE2C_BUILD_LIBS "Build libraries" OFF)

option(RE2C_BUILD_RE2D "Build re2d executable (an alias for `re2c --lang d`)" ON)
option(RE2C_BUILD_RE2GO "Build re2go executable (an alias for `re2c --lang go`)" ON)
option(RE2C_BUILD_RE2HS "Build re2hs executable (an alias for `re2c --lang haskell`)" ON)
option(RE2C_BUILD_RE2OCAML "Build re2ocaml executable (an alias for `re2c --lang ocaml`)" ON)
option(RE2C_BUILD_RE2PY "Build re2py executable (an alias for `re2c --lang python`)" ON)
option(RE2C_BUILD_RE2RUST "Build re2rust executable (an alias for `re2c --lang rust`)" ON)
Expand Down Expand Up @@ -132,6 +133,7 @@ add_library(re2c_objects_autogen OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_c.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_d.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_go.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_haskell.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_ocaml.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_python.cc"
"${CMAKE_CURRENT_BINARY_DIR}/src/default_syntax_rust.cc"
Expand Down Expand Up @@ -217,6 +219,7 @@ re2c_bootstrap_parser("src/parse/conf_parser.ypp" "src/parse/conf_parser.cc"
re2c_bootstrap_syntax("include/syntax/c" "src/default_syntax_c.cc")
re2c_bootstrap_syntax("include/syntax/d" "src/default_syntax_d.cc")
re2c_bootstrap_syntax("include/syntax/go" "src/default_syntax_go.cc")
re2c_bootstrap_syntax("include/syntax/haskell" "src/default_syntax_haskell.cc")
re2c_bootstrap_syntax("include/syntax/ocaml" "src/default_syntax_ocaml.cc")
re2c_bootstrap_syntax("include/syntax/python" "src/default_syntax_python.cc")
re2c_bootstrap_syntax("include/syntax/rust" "src/default_syntax_rust.cc")
Expand All @@ -237,6 +240,12 @@ if (RE2C_BUILD_RE2GO)
target_compile_definitions(re2go PUBLIC "RE2C_LANG=Lang::GO")
endif()

# re2hs
if (RE2C_BUILD_RE2HS)
add_executable(re2hs ${re2c_sources})
target_compile_definitions(re2hs PUBLIC "RE2C_LANG=Lang::HASKELL")
endif()

# re2ocaml
if (RE2C_BUILD_RE2OCAML)
add_executable(re2ocaml ${re2c_sources})
Expand Down Expand Up @@ -388,6 +397,9 @@ if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
install(TARGETS re2go RUNTIME DESTINATION bin)
install(FILES "${re2c_manpage_go}" DESTINATION "share/man/man1")
endif()
if(RE2C_BUILD_RE2HS)
install(TARGETS re2hs RUNTIME DESTINATION bin)
endif()
if(RE2C_BUILD_RE2OCAML)
install(TARGETS re2ocaml RUNTIME DESTINATION bin)
endif()
Expand All @@ -405,6 +417,7 @@ if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
include/syntax/c
include/syntax/d
include/syntax/go
include/syntax/haskell
include/syntax/ocaml
include/syntax/python
include/syntax/rust
Expand Down
11 changes: 11 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ re2c_GEN_SRC = \
src/default_syntax_c.cc \
src/default_syntax_d.cc \
src/default_syntax_go.cc \
src/default_syntax_haskell.cc \
src/default_syntax_ocaml.cc \
src/default_syntax_python.cc \
src/default_syntax_rust.cc \
Expand Down Expand Up @@ -181,6 +182,7 @@ re2c_BOOT = \
bootstrap/src/default_syntax_c.cc \
bootstrap/src/default_syntax_d.cc \
bootstrap/src/default_syntax_go.cc \
bootstrap/src/default_syntax_haskell.cc \
bootstrap/src/default_syntax_ocaml.cc \
bootstrap/src/default_syntax_python.cc \
bootstrap/src/default_syntax_rust.cc \
Expand Down Expand Up @@ -326,6 +328,7 @@ dist_stdlib_DATA = \
include/syntax/c \
include/syntax/d \
include/syntax/go \
include/syntax/haskell \
include/syntax/ocaml \
include/syntax/python \
include/syntax/rust \
Expand Down Expand Up @@ -546,6 +549,14 @@ re2go_SOURCES = $(re2c_SOURCES)
nodist_re2go_SOURCES = $(nodist_re2c_SOURCES)
endif

# re2hs
if WITH_HASKELL
bin_PROGRAMS += re2hs
re2hs_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=Lang::HASKELL
re2hs_SOURCES = $(re2c_SOURCES)
nodist_re2hs_SOURCES = $(nodist_re2c_SOURCES)
endif

# re2ocaml
if WITH_OCAML
bin_PROGRAMS += re2ocaml
Expand Down
236 changes: 236 additions & 0 deletions bootstrap/src/default_syntax_haskell.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
#include "src/parse/conf_parser.h"
const char* DEFAULT_SYNTAX_HASKELL =
"supported_apis = [\"generic\"];\n"
"supported_api_styles = [\"free-form\"];\n"
"supported_code_models = [\"recursive_functions\"];\n"
"supported_targets = [\"code\", \"dot\"];\n"
"supported_features = [\"nested_ifs\", \"monadic\"];\n"
"\n"
"semicolons = 1;\n"
"//semicolons = 0;\n"
"implicit_bool_conversion = 0;\n"
"backtick_quoted_strings = 0;\n"
"standalone_single_quotes = 1; // TODO: what about identifiers?\n"
"indentation_sensitive = 1;\n"
"wrap_blocks_in_braces = 0;\n"
"\n"
"conf:api = custom;\n"
"conf:api:style = free-form;\n"
"conf:api:sigil = \"@@\";\n"
"conf:header = \"\";\n"
"conf:eof = -1;\n"
"conf:sentinel = -1;\n"
"conf:yyfill:enable = 1;\n"
"conf:yyfill:parameter = 1;\n"
"conf:yyfill:check = 1;\n"
"conf:tags = 0;\n"
"conf:leftmost-captures = 0;\n"
"conf:posix-captures = 0;\n"
"conf:tags:prefix = \"yyt\";\n"
"conf:tags:expression = \"@@\";\n"
"conf:invert-captures = 0;\n"
"conf:define:YYBACKUP = \"YYBACKUP\";\n"
"conf:define:YYBACKUPCTX = \"YYBACKUPCTX\";\n"
"conf:define:YYCONDTYPE = \"YYCONDTYPE\";\n"
"conf:define:YYCOPYMTAG = \"YYCOPYMTAG\";\n"
"conf:define:YYCOPYSTAG = \"YYCOPYSTAG\";\n"
"conf:define:YYCTYPE = \"yyctype\";\n"
"conf:define:YYCTXMARKER = \"YYCTXMARKER\";\n"
"conf:define:YYCURSOR = \"YYCURSOR\";\n"
"conf:define:YYDEBUG = \"YYDEBUG\";\n"
"conf:define:YYFILL = \"YYFILL\";\n"
"conf:define:YYFILL@len = \"@@\";\n"
"conf:define:YYFILL:naked = 0;\n"
"conf:define:YYGETACCEPT = \"GETACCEPT\";\n"
"conf:define:YYGETCOND = \"YYGETCOND\";\n"
"conf:define:YYGETCOND:naked = 0;\n"
"conf:define:YYGETSTATE = \"YYGETSTATE\";\n"
"conf:define:YYGETSTATE:naked = 0;\n"
"conf:define:YYLESSTHAN = \"YYLESSTHAN\";\n"
"conf:define:YYLIMIT = \"YYLIMIT\";\n"
"conf:define:YYMARKER = \"YYMARKER\";\n"
"conf:define:YYMAXFILL = \"yymaxfill\";\n"
"conf:define:YYMAXNMATCH = \"yymaxnmatch\";\n"
"conf:define:YYMTAGN = \"YYMTAGN\";\n"
"conf:define:YYMTAGP = \"YYMTAGP\";\n"
"conf:define:YYPEEK = \"YYPEEK\";\n"
"conf:define:YYRESTORE = \"YYRESTORE\";\n"
"conf:define:YYRESTORECTX = \"YYRESTORECTX\";\n"
"conf:define:YYRESTORETAG = \"YYRESTORETAG\";\n"
"conf:define:YYSETACCEPT = \"SETACCEPT\";\n"
"conf:define:YYSETCOND = \"YYSETCOND\";\n"
"conf:define:YYSETCOND@cond = \"@@\";\n"
"conf:define:YYSETCOND:naked = 0;\n"
"conf:define:YYSETSTATE = \"YYSETSTATE\";\n"
"conf:define:YYSETSTATE:naked = 0;\n"
"conf:define:YYSETSTATE@state = \"@@\";\n"
"conf:define:YYSHIFT = \"YYSHIFT\";\n"
"conf:define:YYSHIFTSTAG = \"YYSHIFTSTAG\";\n"
"conf:define:YYSHIFTMTAG = \"YYSHIFTMTAG\";\n"
"conf:define:YYSKIP = \"YYSKIP\";\n"
"conf:define:YYSTAGN = \"YYSTAGN\";\n"
"conf:define:YYSTAGP = \"YYSTAGP\";\n"
"conf:define:YYFN = [\"<undefined-function-name>;<undefined-function-type>\"];\n"
"conf:yyfn:sep = \";\";\n"
"conf:variable:yyctable = \"yyctable\";\n"
"conf:variable:yyaccept = \"yyaccept\";\n"
"conf:variable:yytarget = \"yytarget\";\n"
"conf:variable:yystate = \"yystate\";\n"
"conf:variable:yynmatch = \"\"; // no array for `yypmatch` in Haskell => no need for `yynmatch`\n"
"conf:variable:yypmatch = \"yypmatch\";\n"
"conf:variable:yych = \"yych\";\n"
"conf:variable:yych:conversion = 0;\n"
"conf:variable:yych:literals = hex;\n"
"conf:variable:yych:emit = (code_model.recursive_functions ? 0 : 1);\n"
"conf:variable:yybm = \"yybm\";\n"
"conf:variable:yybm:hex = 0;\n"
"conf:variable:yyfill = \"yyfill\";\n"
"conf:variable:yystable = \"\"; // deprecated\n"
"conf:cond:abort = 1;\n"
"conf:cond:prefix = \"yyc_\";\n"
"conf:cond:enumprefix = \"YYC_\";\n"
"conf:cond:divider = \"(* *********************************** *)\";\n"
"conf:cond:divider@cond = \"@@\";\n"
"conf:cond:goto = \"\";\n"
"conf:cond:goto@cond = \"@@\";\n"
"conf:state:abort = 1;\n"
"conf:state:nextlabel = 0;\n"
"conf:bit-vectors = 0;\n"
"conf:debug-output = 0;\n"
"conf:computed-gotos = 0;\n"
"conf:computed-gotos:threshold = 9;\n"
"conf:nested-ifs = 0;\n"
"conf:case-insensitive = 0;\n"
"conf:case-inverted = 0;\n"
"conf:case-ranges = 0;\n"
"conf:unsafe = 0;\n"
"conf:monadic = 0;\n"
"conf:encoding:ebcdic = 0;\n"
"conf:encoding:utf32 = 0;\n"
"conf:encoding:ucs2 = 0;\n"
"conf:encoding:utf16 = 0;\n"
"conf:encoding:utf8 = 0;\n"
"conf:encoding-policy = ignore;\n"
"conf:empty-class = match-empty;\n"
"conf:indent:string = \" \";\n"
"conf:indent:top = 0;\n"
"conf:label:prefix = \"yy\";\n"
"conf:label:yyfill = \"yyFillLabel\";\n"
"conf:label:yyloop = \"\";\n"
"conf:label:yyNext = \"yyNext\";\n"
"conf:label:start = 0;\n"
"\n"
"code:var_local = topindent \"let \" name \" = \" init \" in\" nl;\n"
"code:var_global = topindent \"let \" name \" = \" init nl;\n"
"\n"
"code:const_local = topindent \"let \" name \" = \" init \" in\" nl;\n"
"code:const_global = topindent name \" = \" init nl;\n"
"\n"
"// code:array_local\n"
"// code:array_global\n"
"\n"
"// `code:array_elem` is used to generate operations on POSIX `yypmatch` array.\n"
"// Override it to generate an identifier instead, as mutable arrays are non-idiomatic in Haskell.\n"
"code:array_elem = array index;\n"
"\n"
"code:type_int = \"int\";\n"
"code:type_uint = \"uint\";\n"
"code:type_cond_enum = (storable_state? \"int\" : \"uint\");\n"
"// code:type_yybm\n"
"// code:type_yytarget\n"
"\n"
"// code:assign\n"
"\n"
"code:if_then_else =\n"
" [branch{0}: topindent (multival ? \"if \" cond \" then\" : \"when (\" cond \") $\") (monadic ? \" do\") nl\n"
" indent [stmt: stmt] dedent]\n"
" [branch{1:-1}: topindent \"else\" (have_cond? \" if \" cond \" then\") (monadic ? \" do\") nl\n"
" indent [stmt: stmt] dedent];\n"
"\n"
"code:if_then_else_oneline =\n"
" [branch{0}: topindent (multival ? \"if \" cond \" then \" : \"when (\" cond \") $ \") [stmt: stmt] nl]\n"
" [branch{1:-1}: topindent \"else \" (have_cond? \"if \" cond \" then \") [stmt: stmt] nl];\n"
"\n"
"code:switch =\n"
" topindent \"case \" expr \" of\" nl\n"
" indent [case: case] dedent;\n"
"\n"
"code:switch_cases = topindent \"_c | \"\n"
" [case{0:-2}: case \" || \"]\n"
" [case{-1}: case \" ->\" (monadic ? \" do\") nl\n"
" indent [stmt: stmt] dedent\n"
" ];\n"
"\n"
"code:switch_case_range = (multival\n"
" ? [val{0}: val] \" <= _c && _c <= \" [val{-1}: val]\n"
" : [val{0}: val] \" == _c\");\n"
"\n"
"code:switch_case_default = \"True\";\n"
"\n"
"code:enum =\n"
" \"data \" name \" = \"\n"
" [elem{0:-2}: elem \" | \"]\n"
" [elem{-1}: elem] \" deriving (Eq, Show)\"\n"
" nl;\n"
"\n"
"code:enum_elem = name;\n"
"\n"
"code:fndef =\n"
" name \" :: \" [arg: argtype \" -> \"] type nl\n"
" name [arg: \" \" (have_argmods? argmods) argname] \" =\" (monadic ? \" do\") nl\n"
" indent [stmt: stmt] dedent;\n"
"\n"
"code:fncall =\n"
" topindent (have_retval ? \"let \" retval \" = \")\n"
" name (have_args ? [arg: \" \" arg] : \" ()\") nl;\n"
"\n"
"code:tailcall = topindent name (have_args ? [arg: \" \" arg] : \" ()\") nl;\n"
"\n"
"code:recursive_functions = [fn: fndef nl];\n"
"\n"
"code:fingerprint = \"-- Generated by re2c\" (version? \" \" version) (date? \" on \" date) nl;\n"
"\n"
"code:line_info = \"#\" line \" \\\"\" file \"\\\"\" nl;\n"
"\n"
"code:abort = topindent \"error \\\"internal lexer error\\\"\" nl;\n"
"\n"
"code:yydebug = topindent debug \" \" state \" \" char nl;\n"
"\n"
"code:yypeek = (monadic\n"
" ? topindent char \" <- \" peek nl\n"
" : topindent \"let \" char \" = \" peek \" in\" nl);\n"
"\n"
"code:yyskip = topindent skip nl;\n"
"\n"
"code:yybackup = topindent backup nl;\n"
"\n"
"code:yybackupctx = topindent backupctx nl;\n"
"\n"
"code:yyrestore = topindent restore nl;\n"
"\n"
"code:yyrestorectx = topindent restorectx nl;\n"
"\n"
"code:yyrestoretag = topindent restoretag nl;\n"
"\n"
"code:yyshift = topindent shift nl;\n"
"\n"
"code:yyshiftstag = topindent shiftstag nl;\n"
"\n"
"code:yyshiftmtag = topindent shiftmtag nl;\n"
"\n"
"code:yystagp = topindent stagp nl;\n"
"\n"
"code:yymtagp = topindent mtagp nl;\n"
"\n"
"code:yystagn = topindent stagn nl;\n"
"\n"
"code:yymtagn = topindent mtagn nl;\n"
"\n"
"code:yycopystag = topindent copystag nl;\n"
"\n"
"code:yycopymtag = topindent copymtag nl;\n"
"\n"
"code:yygetaccept = getaccept;\n"
"\n"
"code:yysetaccept = topindent setaccept nl;\n"
;
Loading

0 comments on commit 4e78ef8

Please sign in to comment.