Move lemon parser generation into build directory

This moves the generated files out of the source tree and into
the build directory. They are now regenerated each time they are
needed, based on the timestamp of the generated file compared to
the timestamp of the lemon file.

To do this, we also bundle lemon into the thirdparty directory
and build it for ourselves since it is a very tiny program and
not all platforms seem to distribute it in a consistent manner.

Fixes https://gitlab.com/kicad/code/kicad/issues/5013
This commit is contained in:
Ian McInerney 2020-07-30 20:33:41 +01:00
parent 34705fd8b2
commit 0a1d8c1aaa
17 changed files with 6036 additions and 1776 deletions

View File

@ -615,6 +615,7 @@ include_directories( SYSTEM ${PIXMAN_INCLUDE_DIR} )
find_package( Boost 1.59.0 REQUIRED ) find_package( Boost 1.59.0 REQUIRED )
include_directories( SYSTEM ${Boost_INCLUDE_DIR} ) include_directories( SYSTEM ${Boost_INCLUDE_DIR} )
# Include MinGW resource compiler. # Include MinGW resource compiler.
include( MinGWResourceCompiler ) include( MinGWResourceCompiler )

View File

@ -1,7 +1,7 @@
# This program source code file is part of KICAD, a free EDA CAD application. # This program source code file is part of KICAD, a free EDA CAD application.
# #
# Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> # Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
# Copyright (C) 2010 Kicad Developers, see AUTHORS.txt for contributors. # Copyright (C) 2010-2020 Kicad Developers, see AUTHORS.txt for contributors.
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@ -54,6 +54,55 @@ function( make_lexer outputTarget inputFile outHeaderFile outCppFile enum )
endfunction() endfunction()
# Function generate_lemon_grammar
#
# This is a function to create a custom command to generate a parser grammar using lemon.
#
# Arguments:
# - TGT is the target to add the consuming file to
# - GRAMMAR_DIR is the path relative to CMAKE_CURRENT_BINARY_DIR for the directory where the files will be generated into
# - CONSUMING_FILE is the file relative to CMAKE_CURRENT_SOURCE_DIR that will include the grammar.c/h file
# - GRAMMAR_FILE is the file relative to CMAKE_CURRENT_SOURCE_DIR of the grammar file to use.
function( generate_lemon_grammar TGT GRAMMAR_DIR CONSUMING_FILE GRAMMAR_FILE )
# Get the name without extension
get_filename_component( GRAMMAR_BASE ${GRAMMAR_FILE} NAME_WE )
file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR} )
set( LEMON_EXE $<TARGET_FILE:lemon>)
get_property( LEMON_TEMPLATE
TARGET lemon
PROPERTY lemon_template
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR}/${GRAMMAR_BASE}.c
${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR}/${GRAMMAR_BASE}.h
COMMAND ${CMAKE_COMMAND}
-DLEMON_EXE=${LEMON_EXE}
-DLEMON_TEMPLATE=${LEMON_TEMPLATE}
-DGRAMMAR_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${GRAMMAR_FILE}
-DGRAMMAR_DIR=${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR}
-P ${CMAKE_MODULE_PATH}/LemonParserGenerator.cmake
COMMENT "Running Lemon on ${GRAMMAR_FILE} to generate ${GRAMMAR_DIR}/${GRAMMAR_BASE}.c"
DEPENDS lemon
${CMAKE_CURRENT_SOURCE_DIR}/${GRAMMAR_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR}
)
# Mark the consuming file with a direct dependency on the generated grammar so that
# it isn't compiled until the grammar is generated
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/${CONSUMING_FILE}
PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_DIR}/${GRAMMAR_BASE}.c
)
target_sources( ${TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${CONSUMING_FILE} )
target_include_directories( ${TGT} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} )
endfunction()
# Is a macro instead of function so there's a higher probability that the # Is a macro instead of function so there's a higher probability that the
# scope of CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA is global # scope of CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA is global
macro( add_conffiles ) macro( add_conffiles )

View File

@ -0,0 +1,50 @@
# This program source code file is part of KICAD, a free EDA CAD application.
#
# Copyright (C) 2020 Kicad Developers, see AUTHORS.txt for contributors.
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, you may find one here:
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# or you may search the http://www.gnu.org website for the version 2 license,
# or you may write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
# This file takes the following variables as arguments:
# * LEMON_EXE - The absolute path to the lemon executable
# * LEMON_TEMPLATE - The absolute path to the lemon template file
# * GRAMMAR_FILE - The file of the grammar to use
# * GRAMMAR_DIR - An absolute path to where the grammar should be generated
# Get the name without extension
get_filename_component( GRAMMAR_BASE ${GRAMMAR_FILE} NAME_WE )
# Only regenerate the lemon code if the grammar is newer than the current code
if( ${GRAMMAR_FILE} IS_NEWER_THAN ${GRAMMAR_DIR}/${GRAMMAR_BASE}.c )
execute_process(
COMMAND ${LEMON_EXE} -T${LEMON_TEMPLATE} -d${GRAMMAR_DIR} -q ${GRAMMAR_FILE}
WORKING_DIRECTORY ${GRAMMAR_DIR}
OUTPUT_VARIABLE _lemon_output
ERROR_VARIABLE _lemon_error
RESULT_VARIABLE _lemon_result
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if( NOT ${_lemon_result} EQUAL 0)
message( FATAL_ERROR "Lemon generator for ${GRAMMAR_FILE} has failed\n"
"Error: ${_lemon_error}" )
endif()
endif()

View File

@ -25,6 +25,8 @@ Licensed under GPLv2 (or later):
- SutherlandHodgmanClipPoly in thirdparty/other_math - SutherlandHodgmanClipPoly in thirdparty/other_math
Licensed under ZLib: Licensed under ZLib:
- nanosvg in thirdparty/nanosvg - nanosvg in thirdparty/nanosvg
Licensed in the public domain:
- lemon in thirdparty/lemon
Licensed under CC-BY-SA-4.0: Licensed under CC-BY-SA-4.0:
- All the demo files provided in demos/* - All the demo files provided in demos/*
Licensed under GPLv3 (or later): Licensed under GPLv3 (or later):

View File

@ -4,9 +4,6 @@ if( COMPILER_SUPPORTS_WARNINGS )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}")
endif() endif()
add_subdirectory( libeval )
add_subdirectory( libeval_compiler )
if( KICAD_SPICE ) if( KICAD_SPICE )
set( INC_AFTER ${INC_AFTER} ${NGSPICE_INCLUDE_DIR} ) set( INC_AFTER ${INC_AFTER} ${NGSPICE_INCLUDE_DIR} )
endif() endif()
@ -421,9 +418,6 @@ set( COMMON_SRCS
project/project_archiver.cpp project/project_archiver.cpp
project/project_file.cpp project/project_file.cpp
project/project_local_settings.cpp project/project_local_settings.cpp
libeval/numeric_evaluator.cpp
libeval_compiler/libeval_compiler.cpp
) )
add_library( common STATIC add_library( common STATIC
@ -438,13 +432,6 @@ target_include_directories( common PRIVATE
add_dependencies( common libcontext ) add_dependencies( common libcontext )
add_dependencies( common version_header ) add_dependencies( common version_header )
find_program(LEMON lemon)
if( LEMON )
add_dependencies( common libeval_grammar )
add_dependencies( common libeval_grammar2 )
endif()
target_link_libraries( common target_link_libraries( common
kimath kimath
kiplatform kiplatform
@ -551,6 +538,23 @@ target_link_libraries( pcbcommon PUBLIC
add_dependencies( pcbcommon delaunator ) add_dependencies( pcbcommon delaunator )
# The lemon grammar for the numeric evaluator
generate_lemon_grammar(
common
libeval
libeval/numeric_evaluator.cpp
libeval/grammar.lemon
)
# The lemon grammar for the expression compiler
generate_lemon_grammar(
common
libeval_compiler
libeval_compiler/libeval_compiler.cpp
libeval_compiler/grammar.lemon
)
# auto-generate netlist_lexer.h and netlist_keywords.cpp # auto-generate netlist_lexer.h and netlist_keywords.cpp
make_lexer( make_lexer(
common common

View File

@ -1,38 +0,0 @@
#
# This program source code file is part of KICAD, a free EDA CAD application.
#
# Copyright (C) 2018 Kicad Developers, see AUTHORS.txt for contributors.
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, you may find one here:
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# or you may search the http://www.gnu.org website for the version 2 license,
# or you may write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
find_program(LEMON lemon)
if( LEMON )
macro( generate_lemon_grammar TGT_NAME GRAMMAR_LEMON GRAMMAR_C )
add_custom_target( ${TGT_NAME}
DEPENDS ${GRAMMAR_LEMON}
COMMAND ${LEMON} -q ${GRAMMAR_LEMON}
COMMENT "Running Lemon on ${GRAMMAR_LEMON} -> ${GRAMMAR_C}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endmacro()
generate_lemon_grammar( libeval_grammar grammar.lemon grammar.c )
endif()

View File

@ -1,12 +0,0 @@
#define VAR 1
#define ASSIGN 2
#define SEMCOL 3
#define PLUS 4
#define MINUS 5
#define UNIT 6
#define DIVIDE 7
#define MULT 8
#define ENDS 9
#define VALUE 10
#define PARENL 11
#define PARENR 12

View File

@ -33,8 +33,8 @@ namespace numEval
#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wsign-compare"
#endif #endif
#include "grammar.c" #include <libeval/grammar.c>
#include "grammar.h" #include <libeval/grammar.h>
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -1,38 +0,0 @@
#
# This program source code file is part of KICAD, a free EDA CAD application.
#
# Copyright (C) 2018 Kicad Developers, see AUTHORS.txt for contributors.
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, you may find one here:
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# or you may search the http://www.gnu.org website for the version 2 license,
# or you may write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
find_program(LEMON lemon)
if( LEMON )
macro( generate_lemon_grammar TGT_NAME GRAMMAR_LEMON GRAMMAR_C )
add_custom_target( ${TGT_NAME}
DEPENDS ${GRAMMAR_LEMON}
COMMAND ${LEMON} -q ${GRAMMAR_LEMON}
COMMENT "Running Lemon on ${GRAMMAR_LEMON} -> ${GRAMMAR_C}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endmacro()
generate_lemon_grammar( libeval_grammar2 grammar.lemon grammar.c )
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
#define G_IDENTIFIER 1
#define G_ASSIGN 2
#define G_SEMCOL 3
#define G_BOOL_AND 4
#define G_BOOL_OR 5
#define G_BOOL_XOR 6
#define G_LESS_THAN 7
#define G_GREATER_THAN 8
#define G_LESS_EQUAL_THAN 9
#define G_GREATER_EQUAL_THAN 10
#define G_EQUAL 11
#define G_NOT_EQUAL 12
#define G_BOOL_NOT 13
#define G_PLUS 14
#define G_MINUS 15
#define G_DIVIDE 16
#define G_MULT 17
#define G_STRUCT_REF 18
#define G_UNIT 19
#define G_ENDS 20
#define G_VALUE 21
#define G_STRING 22
#define G_PARENL 23
#define G_PARENR 24

View File

@ -23,7 +23,7 @@
#include <vector> #include <vector>
#ifdef DEBUG #ifdef DEBUG
#include <stdarg.h> #include <cstdarg>
#endif #endif
#include <reporter.h> #include <reporter.h>
@ -42,8 +42,8 @@ namespace LIBEVAL
#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wsign-compare"
#endif #endif
#include "grammar.c" #include <libeval_compiler/grammar.c>
#include "grammar.h" #include <libeval_compiler/grammar.h>
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -25,6 +25,7 @@ add_subdirectory( clipper )
add_subdirectory( compoundfilereader ) add_subdirectory( compoundfilereader )
add_subdirectory( delaunator ) add_subdirectory( delaunator )
add_subdirectory( dxflib_qcad ) add_subdirectory( dxflib_qcad )
add_subdirectory( lemon )
add_subdirectory( libcontext ) add_subdirectory( libcontext )
add_subdirectory( markdown2html ) add_subdirectory( markdown2html )
add_subdirectory( nanosvg ) add_subdirectory( nanosvg )

14
thirdparty/lemon/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,14 @@
add_executable( lemon
lemon.c
)
# The location of the template file for lemon is passed as a property on the lemon target
define_property( TARGET
PROPERTY lemon_template
BRIEF_DOCS "Location of the template file for the lemon parser"
FULL_DOCS "Location of the template file for the lemon parser"
)
set_property( TARGET lemon
PROPERTY lemon_template ${CMAKE_CURRENT_SOURCE_DIR}/lempar.c
)

10
thirdparty/lemon/README.md vendored Normal file
View File

@ -0,0 +1,10 @@
This directory contains the lemon parser main program file and template file.
It is used for building several parsers in common, and is provided because not
all distributions package it in a nice way. Note, this program is not installed
with KiCad and is only used as a build-time utility.
The files come from:
* lempar.c - https://www.sqlite.org/src/file/tool/lempar.c
* lemon.c - https://www.sqlite.org/src/file/tool/lemon.c
It has been released into the public domain with the sqlite project.

5851
thirdparty/lemon/lemon.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,16 +25,13 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
/************ Begin %include sections from the grammar ************************/ /************ Begin %include sections from the grammar ************************/
#line 28 "grammar.lemon" %%
#include <assert.h>
#include <libeval/numeric_evaluator.h>
#line 33 "grammar.c"
/**************** End of %include directives **********************************/ /**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols /* These constants specify the various numeric values for terminal symbols
** in a format understandable to "makeheaders". This section is blank unless ** in a format understandable to "makeheaders". This section is blank unless
** "lemon" is run with the "-m" command-line option. ** "lemon" is run with the "-m" command-line option.
***************** Begin makeheaders token definitions *************************/ ***************** Begin makeheaders token definitions *************************/
%%
/**************** End makeheaders token definitions ***************************/ /**************** End makeheaders token definitions ***************************/
/* The next sections is a series of control #defines. /* The next sections is a series of control #defines.
@ -92,38 +89,7 @@
# define INTERFACE 1 # define INTERFACE 1
#endif #endif
/************* Begin control #defines *****************************************/ /************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned char %%
#define YYNOCODE 17
#define YYACTIONTYPE unsigned char
#define ParseTOKENTYPE numEval::TokenType
typedef union {
int yyinit;
ParseTOKENTYPE yy0;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define ParseARG_SDECL NUMERIC_EVALUATOR* pEval ;
#define ParseARG_PDECL , NUMERIC_EVALUATOR* pEval
#define ParseARG_PARAM ,pEval
#define ParseARG_FETCH NUMERIC_EVALUATOR* pEval =yypParser->pEval ;
#define ParseARG_STORE yypParser->pEval =pEval ;
#define ParseCTX_SDECL
#define ParseCTX_PDECL
#define ParseCTX_PARAM
#define ParseCTX_FETCH
#define ParseCTX_STORE
#define YYNSTATE 18
#define YYNRULE 17
#define YYNTOKEN 13
#define YY_MAX_SHIFT 17
#define YY_MIN_SHIFTREDUCE 28
#define YY_MAX_SHIFTREDUCE 44
#define YY_ERROR_ACTION 45
#define YY_ACCEPT_ACTION 46
#define YY_NO_ACTION 47
#define YY_MIN_REDUCE 48
#define YY_MAX_REDUCE 64
/************* End control #defines *******************************************/ /************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@ -190,41 +156,7 @@ typedef union {
** yy_default[] Default action for each state. ** yy_default[] Default action for each state.
** **
*********** Begin parsing tables **********************************************/ *********** Begin parsing tables **********************************************/
#define YY_ACTTAB_COUNT (54) %%
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 61, 17, 63, 10, 4, 5, 11, 12, 13, 44,
/* 10 */ 30, 2, 14, 29, 9, 8, 31, 6, 7, 28,
/* 20 */ 17, 59, 17, 4, 5, 4, 5, 58, 44, 30,
/* 30 */ 2, 30, 2, 9, 8, 31, 6, 7, 31, 6,
/* 40 */ 7, 40, 9, 8, 31, 6, 7, 46, 1, 1,
/* 50 */ 10, 15, 16, 3,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 0, 1, 15, 16, 4, 5, 16, 16, 16, 9,
/* 10 */ 10, 11, 16, 3, 4, 5, 6, 7, 8, 9,
/* 20 */ 1, 16, 1, 4, 5, 4, 5, 16, 9, 10,
/* 30 */ 11, 10, 11, 4, 5, 6, 7, 8, 6, 7,
/* 40 */ 8, 12, 4, 5, 6, 7, 8, 13, 14, 15,
/* 50 */ 16, 16, 16, 2, 17, 17, 17, 17, 17, 17,
/* 60 */ 17, 17, 17, 17, 17, 17, 17,
};
#define YY_SHIFT_COUNT (17)
#define YY_SHIFT_MIN (0)
#define YY_SHIFT_MAX (51)
static const unsigned char yy_shift_ofst[] = {
/* 0 */ 19, 0, 21, 21, 21, 21, 21, 21, 21, 21,
/* 10 */ 10, 29, 38, 32, 32, 32, 32, 51,
};
#define YY_REDUCE_COUNT (9)
#define YY_REDUCE_MIN (-13)
#define YY_REDUCE_MAX (36)
static const signed char yy_reduce_ofst[] = {
/* 0 */ 34, -13, -10, -9, -8, -4, 5, 11, 35, 36,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
/* 10 */ 45, 45, 55, 53, 52, 57, 56, 54,
};
/********** End of lemon-generated parsing tables *****************************/ /********** End of lemon-generated parsing tables *****************************/
/* The next table maps tokens (terminal symbols) into fallback tokens. /* The next table maps tokens (terminal symbols) into fallback tokens.
@ -243,6 +175,7 @@ static const YYACTIONTYPE yy_default[] = {
*/ */
#ifdef YYFALLBACK #ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = { static const YYCODETYPE yyFallback[] = {
%%
}; };
#endif /* YYFALLBACK */ #endif /* YYFALLBACK */
@ -330,23 +263,7 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
/* For tracing shifts, the names of all terminals and nonterminals /* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */ ** are required. The following table supplies these names */
static const char *const yyTokenName[] = { static const char *const yyTokenName[] = {
/* 0 */ "$", %%
/* 1 */ "VAR",
/* 2 */ "ASSIGN",
/* 3 */ "SEMCOL",
/* 4 */ "PLUS",
/* 5 */ "MINUS",
/* 6 */ "UNIT",
/* 7 */ "DIVIDE",
/* 8 */ "MULT",
/* 9 */ "ENDS",
/* 10 */ "VALUE",
/* 11 */ "PARENL",
/* 12 */ "PARENR",
/* 13 */ "main",
/* 14 */ "in",
/* 15 */ "stmt",
/* 16 */ "expr",
}; };
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@ -354,23 +271,7 @@ static const char *const yyTokenName[] = {
/* For tracing reduce actions, the names of all rules are required. /* For tracing reduce actions, the names of all rules are required.
*/ */
static const char *const yyRuleName[] = { static const char *const yyRuleName[] = {
/* 0 */ "stmt ::= expr ENDS", %%
/* 1 */ "stmt ::= expr SEMCOL",
/* 2 */ "expr ::= VALUE",
/* 3 */ "expr ::= expr UNIT",
/* 4 */ "expr ::= MINUS expr",
/* 5 */ "expr ::= PLUS expr",
/* 6 */ "expr ::= VAR",
/* 7 */ "expr ::= VAR ASSIGN expr",
/* 8 */ "expr ::= expr PLUS expr",
/* 9 */ "expr ::= expr MINUS expr",
/* 10 */ "expr ::= expr MULT expr",
/* 11 */ "expr ::= expr DIVIDE expr",
/* 12 */ "expr ::= PARENL expr PARENR",
/* 13 */ "main ::= in",
/* 14 */ "in ::= stmt",
/* 15 */ "in ::= in stmt",
/* 16 */ "stmt ::= ENDS",
}; };
#endif /* NDEBUG */ #endif /* NDEBUG */
@ -496,6 +397,7 @@ static void yy_destructor(
** inside the C code. ** inside the C code.
*/ */
/********* Begin destructor definitions ***************************************/ /********* Begin destructor definitions ***************************************/
%%
/********* End destructor definitions *****************************************/ /********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */ default: break; /* If no destructor action specified: do nothing */
} }
@ -619,15 +521,18 @@ static YYACTIONTYPE yy_find_shift_action(
do{ do{
i = yy_shift_ofst[stateno]; i = yy_shift_ofst[stateno];
assert( i>=0 ); assert( i>=0 );
/* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ assert( i<=YY_ACTTAB_COUNT );
assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
assert( iLookAhead!=YYNOCODE ); assert( iLookAhead!=YYNOCODE );
assert( iLookAhead < YYNTOKEN ); assert( iLookAhead < YYNTOKEN );
i += iLookAhead; i += iLookAhead;
if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ assert( i<(int)YY_NLOOKAHEAD );
if( yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK #ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */ YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
&& (iFallback = yyFallback[iLookAhead])!=0 ){ iFallback = yyFallback[iLookAhead];
if( iFallback!=0 ){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
@ -642,16 +547,8 @@ static YYACTIONTYPE yy_find_shift_action(
#ifdef YYWILDCARD #ifdef YYWILDCARD
{ {
int j = i - iLookAhead + YYWILDCARD; int j = i - iLookAhead + YYWILDCARD;
if( assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
#if YY_SHIFT_MIN+YYWILDCARD<0 if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){
#ifndef NDEBUG #ifndef NDEBUG
if( yyTraceFILE ){ if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
@ -665,6 +562,7 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */ #endif /* YYWILDCARD */
return yy_default[stateno]; return yy_default[stateno];
}else{ }else{
assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
return yy_action[i]; return yy_action[i];
} }
}while(1); }while(1);
@ -715,6 +613,7 @@ static void yyStackOverflow(yyParser *yypParser){
/* Here code is inserted which will execute if the parser /* Here code is inserted which will execute if the parser
** stack every overflows */ ** stack every overflows */
/******** Begin %stack_overflow code ******************************************/ /******** Begin %stack_overflow code ******************************************/
%%
/******** End %stack_overflow code ********************************************/ /******** End %stack_overflow code ********************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument var */ ParseARG_STORE /* Suppress warning about unused %extra_argument var */
ParseCTX_STORE ParseCTX_STORE
@ -786,45 +685,13 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */ ** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = { static const YYCODETYPE yyRuleInfoLhs[] = {
15, /* (0) stmt ::= expr ENDS */ %%
15, /* (1) stmt ::= expr SEMCOL */
16, /* (2) expr ::= VALUE */
16, /* (3) expr ::= expr UNIT */
16, /* (4) expr ::= MINUS expr */
16, /* (5) expr ::= PLUS expr */
16, /* (6) expr ::= VAR */
16, /* (7) expr ::= VAR ASSIGN expr */
16, /* (8) expr ::= expr PLUS expr */
16, /* (9) expr ::= expr MINUS expr */
16, /* (10) expr ::= expr MULT expr */
16, /* (11) expr ::= expr DIVIDE expr */
16, /* (12) expr ::= PARENL expr PARENR */
13, /* (13) main ::= in */
14, /* (14) in ::= stmt */
14, /* (15) in ::= in stmt */
15, /* (16) stmt ::= ENDS */
}; };
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */ ** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = { static const signed char yyRuleInfoNRhs[] = {
-2, /* (0) stmt ::= expr ENDS */ %%
-2, /* (1) stmt ::= expr SEMCOL */
-1, /* (2) expr ::= VALUE */
-2, /* (3) expr ::= expr UNIT */
-2, /* (4) expr ::= MINUS expr */
-2, /* (5) expr ::= PLUS expr */
-1, /* (6) expr ::= VAR */
-3, /* (7) expr ::= VAR ASSIGN expr */
-3, /* (8) expr ::= expr PLUS expr */
-3, /* (9) expr ::= expr MINUS expr */
-3, /* (10) expr ::= expr MULT expr */
-3, /* (11) expr ::= expr DIVIDE expr */
-3, /* (12) expr ::= PARENL expr PARENR */
-1, /* (13) main ::= in */
-1, /* (14) in ::= stmt */
-2, /* (15) in ::= in stmt */
-1, /* (16) stmt ::= ENDS */
}; };
static void yy_accept(yyParser*); /* Forward Declaration */ static void yy_accept(yyParser*); /* Forward Declaration */
@ -858,12 +725,15 @@ static YYACTIONTYPE yy_reduce(
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfoNRhs[yyruleno]; yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){ if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt, yyTracePrompt,
yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yymsp[yysize].stateno);
}else{ }else{
fprintf(yyTraceFILE, "%sReduce %d [%s].\n", fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno]); yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
} }
} }
#endif /* NDEBUG */ #endif /* NDEBUG */
@ -910,92 +780,7 @@ static YYACTIONTYPE yy_reduce(
** break; ** break;
*/ */
/********** Begin reduce actions **********************************************/ /********** Begin reduce actions **********************************************/
YYMINORTYPE yylhsminor; %%
case 0: /* stmt ::= expr ENDS */
#line 49 "grammar.lemon"
{ pEval->parseSetResult(yymsp[-1].minor.yy0.valid ? yymsp[-1].minor.yy0.dValue : NAN); }
#line 918 "grammar.c"
break;
case 1: /* stmt ::= expr SEMCOL */
#line 50 "grammar.lemon"
{ pEval->parseSetResult(NAN); }
#line 923 "grammar.c"
break;
case 2: /* expr ::= VALUE */
#line 52 "grammar.lemon"
{ yylhsminor.yy0.dValue = yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=true; }
#line 928 "grammar.c"
yymsp[0].minor.yy0 = yylhsminor.yy0;
break;
case 3: /* expr ::= expr UNIT */
#line 53 "grammar.lemon"
{ yylhsminor.yy0.dValue = yymsp[-1].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=yymsp[-1].minor.yy0.valid; }
#line 934 "grammar.c"
yymsp[-1].minor.yy0 = yylhsminor.yy0;
break;
case 4: /* expr ::= MINUS expr */
#line 54 "grammar.lemon"
{ yymsp[-1].minor.yy0.dValue = -yymsp[0].minor.yy0.dValue; yymsp[-1].minor.yy0.valid=yymsp[0].minor.yy0.valid; }
#line 940 "grammar.c"
break;
case 5: /* expr ::= PLUS expr */
#line 55 "grammar.lemon"
{ yymsp[-1].minor.yy0.dValue = yymsp[0].minor.yy0.dValue; yymsp[-1].minor.yy0.valid=yymsp[0].minor.yy0.valid; }
#line 945 "grammar.c"
break;
case 6: /* expr ::= VAR */
#line 56 "grammar.lemon"
{ yylhsminor.yy0.dValue = pEval->GetVar(yymsp[0].minor.yy0.text); yylhsminor.yy0.valid=true; }
#line 950 "grammar.c"
yymsp[0].minor.yy0 = yylhsminor.yy0;
break;
case 7: /* expr ::= VAR ASSIGN expr */
#line 57 "grammar.lemon"
{ pEval->SetVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yylhsminor.yy0.dValue = yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=false; }
#line 956 "grammar.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 8: /* expr ::= expr PLUS expr */
#line 58 "grammar.lemon"
{ yylhsminor.yy0.dValue = yymsp[-2].minor.yy0.dValue + yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=yymsp[0].minor.yy0.valid; }
#line 962 "grammar.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 9: /* expr ::= expr MINUS expr */
#line 59 "grammar.lemon"
{ yylhsminor.yy0.dValue = yymsp[-2].minor.yy0.dValue - yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=yymsp[0].minor.yy0.valid; }
#line 968 "grammar.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 10: /* expr ::= expr MULT expr */
#line 60 "grammar.lemon"
{ yylhsminor.yy0.dValue = yymsp[-2].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yylhsminor.yy0.valid=yymsp[0].minor.yy0.valid; }
#line 974 "grammar.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 11: /* expr ::= expr DIVIDE expr */
#line 61 "grammar.lemon"
{
if (yymsp[0].minor.yy0.dValue != 0.0) {
yylhsminor.yy0.dValue = yymsp[-2].minor.yy0.dValue / yymsp[0].minor.yy0.dValue;
}
else pEval->parseError("Div by zero");
yylhsminor.yy0.valid=yymsp[0].minor.yy0.valid;
}
#line 986 "grammar.c"
yymsp[-2].minor.yy0 = yylhsminor.yy0;
break;
case 12: /* expr ::= PARENL expr PARENR */
#line 68 "grammar.lemon"
{ yymsp[-2].minor.yy0.dValue = yymsp[-1].minor.yy0.dValue; yymsp[-2].minor.yy0.valid=yymsp[-1].minor.yy0.valid; }
#line 992 "grammar.c"
break;
default:
/* (13) main ::= in */ yytestcase(yyruleno==13);
/* (14) in ::= stmt (OPTIMIZED OUT) */ assert(yyruleno!=14);
/* (15) in ::= in stmt */ yytestcase(yyruleno==15);
/* (16) stmt ::= ENDS */ yytestcase(yyruleno==16);
break;
/********** End reduce actions ************************************************/ /********** End reduce actions ************************************************/
}; };
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) ); assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
@ -1036,6 +821,7 @@ static void yy_parse_failed(
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser fails */ ** parser fails */
/************ Begin %parse_failure code ***************************************/ /************ Begin %parse_failure code ***************************************/
%%
/************ End %parse_failure code *****************************************/ /************ End %parse_failure code *****************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -1054,10 +840,7 @@ static void yy_syntax_error(
ParseCTX_FETCH ParseCTX_FETCH
#define TOKEN yyminor #define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/ /************ Begin %syntax_error code ****************************************/
#line 33 "grammar.lemon" %%
pEval->parseError("Syntax error");
#line 1061 "grammar.c"
/************ End %syntax_error code ******************************************/ /************ End %syntax_error code ******************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -1083,10 +866,7 @@ static void yy_accept(
/* Here code is inserted which will be executed whenever the /* Here code is inserted which will be executed whenever the
** parser accepts */ ** parser accepts */
/*********** Begin %parse_accept code *****************************************/ /*********** Begin %parse_accept code *****************************************/
#line 37 "grammar.lemon" %%
pEval->parseOk();
#line 1090 "grammar.c"
/*********** End %parse_accept code *******************************************/ /*********** End %parse_accept code *******************************************/
ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */
ParseCTX_STORE ParseCTX_STORE
@ -1287,11 +1067,10 @@ void Parse(
*/ */
int ParseFallback(int iToken){ int ParseFallback(int iToken){
#ifdef YYFALLBACK #ifdef YYFALLBACK
if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
return yyFallback[iToken]; return yyFallback[iToken];
}
#else #else
(void)iToken; (void)iToken;
#endif
return 0; return 0;
#endif
} }