# This defines macros and rules for Bison and Flex source processing
#
# This specilizes _SRC() macro, so should be imported after generic version definition
# Thus uses _ADD_HIDDEN_INPUTS() macro from ymake.core.conf

M4_PATH=contrib/tools/m4

LEX_FLAGS=
BISON_FLAGS=-v

_BISON_DATA_DIR=contrib/tools/bison/data
_CPP_BISON_SKELS=\
  ${_BISON_DATA_DIR}/m4sugar/foreach.m4 \
  ${_BISON_DATA_DIR}/m4sugar/m4sugar.m4 \
  ${_BISON_DATA_DIR}/skeletons/bison.m4 \
  ${_BISON_DATA_DIR}/skeletons/c++-skel.m4 \
  ${_BISON_DATA_DIR}/skeletons/c++.m4 \
  ${_BISON_DATA_DIR}/skeletons/c-like.m4 \
  ${_BISON_DATA_DIR}/skeletons/c-skel.m4 \
  ${_BISON_DATA_DIR}/skeletons/c.m4 \
  ${_BISON_DATA_DIR}/skeletons/glr.cc \
  ${_BISON_DATA_DIR}/skeletons/lalr1.cc \
  ${_BISON_DATA_DIR}/skeletons/location.cc \
  ${_BISON_DATA_DIR}/skeletons/stack.hh \
  ${_BISON_DATA_DIR}/skeletons/variant.hh \
  ${_BISON_DATA_DIR}/skeletons/yacc.c \

_BISON_GEN_EXT=.cpp
_FLEX_GEN_EXT=.cpp

_BISON_HEADER_SUFFIX=.h
_BISON_HEADER=
_BISON_PP=
_FLEX_TOOL=
_FLEX_TOOL_DIR=
_FLEX_HEADER=

when ($_BISON_FLEX_SET_DEFAULTS == "yes") {
    _BISON_HEADER=--defines=${nopath;noext;output;main;addincl;norel;suf=$_BISON_HEADER_SUFFIX:SRC}
    _BISON_PP=$YMAKE_PYTHON ${input:"build/scripts/preprocess.py"} $_ADD_HIDDEN_INPUTS($_CPP_BISON_SKELS) ${nopath;noext;tmp;suf=$_BISON_HEADER_SUFFIX:SRC}
    _FLEX_TOOL=${tool:"contrib/tools/flex-old"}
    _FLEX_TOOL_DIR=contrib/tools/flex-old
    _FLEX_HEADER=
}

### @usage: FLEX_FLAGS(<flags>)
###
### Set flags for Lex tool (flex) invocations.
macro FLEX_FLAGS(Flags...) {
    SET_APPEND(LEX_FLAGS $Flags)
}

### @usage: BISON_FLAGS(<flags>)
###
### Set flags for Bison tool invocations.
macro BISON_FLAGS(Flags...) {
    SET_APPEND(BISON_FLAGS $Flags)
}

### @usage: BISON_GEN_C()
###
### Generate C from Bison grammar. The C++ is generated by default.
macro BISON_GEN_C() {
    SET(_BISON_GEN_EXT .c)
    SET(_BISON_PP)
}

### @usage: BISON_GEN_CPP()
###
### Generate C++ from Bison grammar. This is current default.
macro BISON_GEN_CPP() {
    SET(_BISON_GEN_EXT .cpp)
}


### @usage: FLEX_GEN_C()
###
### Generate C from Lex grammar. The C++ is generated by default.
macro FLEX_GEN_C() {
    SET(_FLEX_GEN_EXT .c)
}

### @usage: FLEX_GEN_CPP()
###
### Generate C++ from Lex grammar. This is current default.
macro FLEX_GEN_CPP() {
    SET(_FLEX_GEN_EXT .cpp)
}

### @usage: BISON_HEADER(<header_suffix>)
###
### Use SUFF (including extension) to name Bison defines header file. The default is just `.h`.
macro BISON_HEADER(Suffix) {
    SET(_BISON_HEADER_SUFFIX $Suffix)
    SET(_BISON_HEADER --defines=\${nopath;noext;output;main;addincl;norel;suf=$_BISON_HEADER_SUFFIX:SRC})
    SET(_BISON_PP $YMAKE_PYTHON \${input:"build/scripts/preprocess.py"} $_ADD_HIDDEN_INPUTS($_CPP_BISON_SKELS) \${nopath;noext;tmp;suf=$_BISON_HEADER_SUFFIX:SRC})

}

### @usage: BISON_NO_HEADER()
###
### Don't emit Bison defines header file.
macro BISON_NO_HEADER() {
    SET(_BISON_HEADER)
}

### @usage: USE_MODERN_FLEX()
###
### Use `contrib/tools/flex` as flex tool. Default is `contrib/tools/flex-old`.
### @note: by default no header is emitted. Use `USE_MODERN_FLEX_WITH_HEADER` to add header emission.
macro USE_MODERN_FLEX() {
    SET(_FLEX_TOOL \${tool:"contrib/tools/flex"} --m4=\${tool:"contrib/tools/m4"})
    SET(_FLEX_TOOL_DIR contrib/tools/flex)
}

### @usage: USE_MODERN_FLEX_WITH_HEADER(<header_suffix>)
###
### Use `contrib/tools/flex` as flex tool. Default is `contrib/tools/flex-old`.
### Additionally emit headers with suffix provided. Header suffix should include extension `.h`.
###
### @example: USE_MODERN_FLEX_WITH_HEADER(_lexer.h)
macro USE_MODERN_FLEX_WITH_HEADER(Suffix) {
    SET(_FLEX_TOOL \${tool:"contrib/tools/flex"} --m4=\${tool:"contrib/tools/m4"})
    SET(_FLEX_TOOL_DIR contrib/tools/flex)
    SET(_FLEX_HEADER --header-file=\${nopath;noext;output;main;addincl;norel;suf=$Suffix:SRC})
}

### @usage: USE_OLD_FLEX()
###
### Use `contrib/tools/flex-old` as flex tool. This is current default.
macro USE_OLD_FLEX() {
    SET(_FLEX_TOOL \${tool:"contrib/tools/flex-old"})
    SET(_FLEX_TOOL_DIR contrib/tools/flex-old)
}

macro _SRC("y", SRC, SRCFLAGS...) {
    .PEERDIR=build/induced/by_bison
    .CMD=${tool:"contrib/tools/bison"} $BISON_FLAGS ${env:"M4=${tool:M4_PATH}"} ${env:"BISON_PKGDATADIR=${ARCADIA_ROOT}/${_BISON_DATA_DIR}"} $_BISON_HEADER ${hide:_BISON_GEN_EXT} -o ${nopath;output;suf=$_BISON_GEN_EXT:SRC} ${input:SRC} ${SRCFLAGS} ${hide;kv:"p YC"} ${hide;kv:"pc light-green"} && $_BISON_PP
    .SEM=target_macroses-ITEM && target_macroses-macro target_bison_parser && target_macroses-args PRIVATE ${input:SRC} ${output;nopath;noext;hide;suf=${OBJ_SUF}.o:SRC} ${nopath;noext;hide;output:SRC.h} ${nopath;noext;output;addincl;hide:SRC.h} && platform_vars-BISON_FLAGS ${quo:BISON_FLAGS} && conan-tool_requires m4/1.4.19 && conan-imports 'bin, m4* -> ./bin/m4/bin' && conan-tool_requires bison/3.8.2 && conan-imports 'bin, bison* -> ./bin/bison/bin' && conan-imports 'res, * -> ./bin/bison/res'
}

macro _SRC("ypp", SRC, SRCFLAGS...) {
    .PEERDIR=build/induced/by_bison
    .CMD=$_SRC(y $SRC $SRCFLAGS)
    .SEM=$_SRC(y $SRC $SRCFLAGS)
}

macro _SRC("l", SRC, SRCFLAGS...) {
    .CMD=$_FLEX_TOOL $LEX_FLAGS ${SRCFLAGS} $_FLEX_HEADER ${hide:_FLEX_GEN_EXT} -o${output;suf=$_FLEX_GEN_EXT:SRC} ${hide;output_include:"util/system/compiler.h"} ${input:SRC} ${hide;kv:"p LX"} ${hide;kv:"pc yellow"}
    .ADDINCL=$_FLEX_TOOL_DIR
    .SEM=target_macroses-ITEM && target_macroses-macro target_flex_lexers && target_macroses-args ${hide;tool:_FLEX_TOOL} ${hide;output;suf=${OBJ_SUF}.o:SRC} ${input:SRC} && platform_vars-LEX_FLAGS ${quo:LEX_FLAGS}
}

# tag:src-processing
macro _SRC("lex", SRC, SRCFLAGS...) {
    .CMD=$_SRC(l $SRC $SRCFLAGS)
}

# tag:src-processing
macro _SRC("lpp", SRC, SRCFLAGS...) {
    .CMD=$_SRC(l $SRC $SRCFLAGS)
}