1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 6*a970610aSStefan Eßer * Copyright (c) 2018-2024 Gavin D. Howard and contributors. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12252884aeSStefan Eßer * list of conditions and the following disclaimer. 13252884aeSStefan Eßer * 14252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16252884aeSStefan Eßer * and/or other materials provided with the distribution. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29252884aeSStefan Eßer * 30252884aeSStefan Eßer * ***************************************************************************** 31252884aeSStefan Eßer * 32252884aeSStefan Eßer * Definitions for bc's lexer. 33252884aeSStefan Eßer * 34252884aeSStefan Eßer */ 35252884aeSStefan Eßer 36252884aeSStefan Eßer #ifndef BC_LEX_H 37252884aeSStefan Eßer #define BC_LEX_H 38252884aeSStefan Eßer 39252884aeSStefan Eßer #include <stdbool.h> 40252884aeSStefan Eßer #include <stddef.h> 41252884aeSStefan Eßer 42252884aeSStefan Eßer #include <status.h> 43252884aeSStefan Eßer #include <vector.h> 44252884aeSStefan Eßer #include <lang.h> 45252884aeSStefan Eßer 46d101cdd6SStefan Eßer /** 47d101cdd6SStefan Eßer * A convenience macro for throwing errors in lex code. This takes care of 48d101cdd6SStefan Eßer * plumbing like passing in the current line the lexer is on. 49d101cdd6SStefan Eßer * @param l The lexer. 50d101cdd6SStefan Eßer * @param e The error. 51d101cdd6SStefan Eßer */ 52103d7cdfSStefan Eßer #if BC_DEBUG 53d101cdd6SStefan Eßer #define bc_lex_err(l, e) (bc_vm_handleError((e), __FILE__, __LINE__, (l)->line)) 54103d7cdfSStefan Eßer #else // BC_DEBUG 5550696a6eSStefan Eßer #define bc_lex_err(l, e) (bc_vm_handleError((e), (l)->line)) 56103d7cdfSStefan Eßer #endif // BC_DEBUG 57d101cdd6SStefan Eßer 58d101cdd6SStefan Eßer /** 59d101cdd6SStefan Eßer * A convenience macro for throwing errors in lex code. This takes care of 60d101cdd6SStefan Eßer * plumbing like passing in the current line the lexer is on. 61d101cdd6SStefan Eßer * @param l The lexer. 62d101cdd6SStefan Eßer * @param e The error. 63d101cdd6SStefan Eßer */ 64103d7cdfSStefan Eßer #if BC_DEBUG 65d101cdd6SStefan Eßer #define bc_lex_verr(l, e, ...) \ 66d101cdd6SStefan Eßer (bc_vm_handleError((e), __FILE__, __LINE__, (l)->line, __VA_ARGS__)) 67103d7cdfSStefan Eßer #else // BC_DEBUG 6850696a6eSStefan Eßer #define bc_lex_verr(l, e, ...) (bc_vm_handleError((e), (l)->line, __VA_ARGS__)) 69103d7cdfSStefan Eßer #endif // BC_DEBUG 70252884aeSStefan Eßer 7144d4804dSStefan Eßer // BC_LEX_NEG_CHAR returns the char that corresponds to negative for the 7244d4804dSStefan Eßer // current calculator. 7344d4804dSStefan Eßer // 7444d4804dSStefan Eßer // BC_LEX_LAST_NUM_CHAR returns the char that corresponds to the last valid 7544d4804dSStefan Eßer // char for numbers. In bc and dc, capital letters are part of numbers, to a 7644d4804dSStefan Eßer // point. (dc only goes up to hex, so its last valid char is 'F'.) 773aa99676SStefan Eßer #if BC_ENABLED 783aa99676SStefan Eßer 793aa99676SStefan Eßer #if DC_ENABLED 80252884aeSStefan Eßer #define BC_LEX_NEG_CHAR (BC_IS_BC ? '-' : '_') 81252884aeSStefan Eßer #define BC_LEX_LAST_NUM_CHAR (BC_IS_BC ? 'Z' : 'F') 823aa99676SStefan Eßer #else // DC_ENABLED 833aa99676SStefan Eßer #define BC_LEX_NEG_CHAR ('-') 843aa99676SStefan Eßer #define BC_LEX_LAST_NUM_CHAR ('Z') 853aa99676SStefan Eßer #endif // DC_ENABLED 863aa99676SStefan Eßer 873aa99676SStefan Eßer #else // BC_ENABLED 883aa99676SStefan Eßer 893aa99676SStefan Eßer #define BC_LEX_NEG_CHAR ('_') 903aa99676SStefan Eßer #define BC_LEX_LAST_NUM_CHAR ('F') 913aa99676SStefan Eßer 923aa99676SStefan Eßer #endif // BC_ENABLED 933aa99676SStefan Eßer 9444d4804dSStefan Eßer /** 9544d4804dSStefan Eßer * Returns true if c is a valid number character. 9644d4804dSStefan Eßer * @param c The char to check. 9744d4804dSStefan Eßer * @param pt If a decimal point has already been seen. 9844d4804dSStefan Eßer * @param int_only True if the number is expected to be an int only, false if 9944d4804dSStefan Eßer * non-integers are allowed. 10044d4804dSStefan Eßer * @return True if @a c is a valid number character. 10144d4804dSStefan Eßer */ 102252884aeSStefan Eßer #define BC_LEX_NUM_CHAR(c, pt, int_only) \ 10344d4804dSStefan Eßer (isdigit(c) != 0 || ((c) >= 'A' && (c) <= BC_LEX_LAST_NUM_CHAR) || \ 104252884aeSStefan Eßer ((c) == '.' && !(pt) && !(int_only))) 105252884aeSStefan Eßer 10644d4804dSStefan Eßer /// An enum of lex token types. 10778bc019dSStefan Eßer typedef enum BcLexType 10878bc019dSStefan Eßer { 10944d4804dSStefan Eßer /// End of file. 110252884aeSStefan Eßer BC_LEX_EOF, 11144d4804dSStefan Eßer 11244d4804dSStefan Eßer /// Marker for invalid tokens, used by bc and dc for const data. 113252884aeSStefan Eßer BC_LEX_INVALID, 114252884aeSStefan Eßer 115252884aeSStefan Eßer #if BC_ENABLED 11644d4804dSStefan Eßer 11744d4804dSStefan Eßer /// Increment operator. 118252884aeSStefan Eßer BC_LEX_OP_INC, 11944d4804dSStefan Eßer 12044d4804dSStefan Eßer /// Decrement operator. 121252884aeSStefan Eßer BC_LEX_OP_DEC, 12244d4804dSStefan Eßer 123252884aeSStefan Eßer #endif // BC_ENABLED 124252884aeSStefan Eßer 12544d4804dSStefan Eßer /// BC_LEX_NEG is not used in lexing; it is only for parsing. The lexer 12644d4804dSStefan Eßer /// marks all '-' characters as BC_LEX_OP_MINUS, but the parser needs to be 12744d4804dSStefan Eßer /// able to distinguish them. 128252884aeSStefan Eßer BC_LEX_NEG, 12944d4804dSStefan Eßer 13044d4804dSStefan Eßer /// Boolean not. 131252884aeSStefan Eßer BC_LEX_OP_BOOL_NOT, 13244d4804dSStefan Eßer 133252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 13444d4804dSStefan Eßer 13544d4804dSStefan Eßer /// Truncation operator. 136252884aeSStefan Eßer BC_LEX_OP_TRUNC, 13744d4804dSStefan Eßer 138252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 139252884aeSStefan Eßer 14044d4804dSStefan Eßer /// Power operator. 141252884aeSStefan Eßer BC_LEX_OP_POWER, 14244d4804dSStefan Eßer 14344d4804dSStefan Eßer /// Multiplication operator. 144252884aeSStefan Eßer BC_LEX_OP_MULTIPLY, 14544d4804dSStefan Eßer 14644d4804dSStefan Eßer /// Division operator. 147252884aeSStefan Eßer BC_LEX_OP_DIVIDE, 14844d4804dSStefan Eßer 14944d4804dSStefan Eßer /// Modulus operator. 150252884aeSStefan Eßer BC_LEX_OP_MODULUS, 15144d4804dSStefan Eßer 15244d4804dSStefan Eßer /// Addition operator. 153252884aeSStefan Eßer BC_LEX_OP_PLUS, 15444d4804dSStefan Eßer 15544d4804dSStefan Eßer /// Subtraction operator. 156252884aeSStefan Eßer BC_LEX_OP_MINUS, 157252884aeSStefan Eßer 158252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 159d101cdd6SStefan Eßer 16044d4804dSStefan Eßer /// Places (truncate or extend) operator. 161252884aeSStefan Eßer BC_LEX_OP_PLACES, 162252884aeSStefan Eßer 16344d4804dSStefan Eßer /// Left (decimal) shift operator. 164252884aeSStefan Eßer BC_LEX_OP_LSHIFT, 16544d4804dSStefan Eßer 16644d4804dSStefan Eßer /// Right (decimal) shift operator. 167252884aeSStefan Eßer BC_LEX_OP_RSHIFT, 168d101cdd6SStefan Eßer 169252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 170252884aeSStefan Eßer 17144d4804dSStefan Eßer /// Equal operator. 172252884aeSStefan Eßer BC_LEX_OP_REL_EQ, 17344d4804dSStefan Eßer 17444d4804dSStefan Eßer /// Less than or equal operator. 175252884aeSStefan Eßer BC_LEX_OP_REL_LE, 17644d4804dSStefan Eßer 17744d4804dSStefan Eßer /// Greater than or equal operator. 178252884aeSStefan Eßer BC_LEX_OP_REL_GE, 17944d4804dSStefan Eßer 18044d4804dSStefan Eßer /// Not equal operator. 181252884aeSStefan Eßer BC_LEX_OP_REL_NE, 18244d4804dSStefan Eßer 18344d4804dSStefan Eßer /// Less than operator. 184252884aeSStefan Eßer BC_LEX_OP_REL_LT, 18544d4804dSStefan Eßer 18644d4804dSStefan Eßer /// Greater than operator. 187252884aeSStefan Eßer BC_LEX_OP_REL_GT, 188252884aeSStefan Eßer 18944d4804dSStefan Eßer /// Boolean or operator. 190252884aeSStefan Eßer BC_LEX_OP_BOOL_OR, 19144d4804dSStefan Eßer 19244d4804dSStefan Eßer /// Boolean and operator. 193252884aeSStefan Eßer BC_LEX_OP_BOOL_AND, 194252884aeSStefan Eßer 195252884aeSStefan Eßer #if BC_ENABLED 196d101cdd6SStefan Eßer 19744d4804dSStefan Eßer /// Power assignment operator. 198252884aeSStefan Eßer BC_LEX_OP_ASSIGN_POWER, 19944d4804dSStefan Eßer 20044d4804dSStefan Eßer /// Multiplication assignment operator. 201252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MULTIPLY, 20244d4804dSStefan Eßer 20344d4804dSStefan Eßer /// Division assignment operator. 204252884aeSStefan Eßer BC_LEX_OP_ASSIGN_DIVIDE, 20544d4804dSStefan Eßer 20644d4804dSStefan Eßer /// Modulus assignment operator. 207252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MODULUS, 20844d4804dSStefan Eßer 20944d4804dSStefan Eßer /// Addition assignment operator. 210252884aeSStefan Eßer BC_LEX_OP_ASSIGN_PLUS, 21144d4804dSStefan Eßer 21244d4804dSStefan Eßer /// Subtraction assignment operator. 213252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MINUS, 21444d4804dSStefan Eßer 215252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 21644d4804dSStefan Eßer 21744d4804dSStefan Eßer /// Places (truncate or extend) assignment operator. 218252884aeSStefan Eßer BC_LEX_OP_ASSIGN_PLACES, 21944d4804dSStefan Eßer 22044d4804dSStefan Eßer /// Left (decimal) shift assignment operator. 221252884aeSStefan Eßer BC_LEX_OP_ASSIGN_LSHIFT, 22244d4804dSStefan Eßer 22344d4804dSStefan Eßer /// Right (decimal) shift assignment operator. 224252884aeSStefan Eßer BC_LEX_OP_ASSIGN_RSHIFT, 22544d4804dSStefan Eßer 226252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 227252884aeSStefan Eßer #endif // BC_ENABLED 22844d4804dSStefan Eßer 22944d4804dSStefan Eßer /// Assignment operator. 230252884aeSStefan Eßer BC_LEX_OP_ASSIGN, 231252884aeSStefan Eßer 23244d4804dSStefan Eßer /// Newline. 233252884aeSStefan Eßer BC_LEX_NLINE, 23444d4804dSStefan Eßer 23544d4804dSStefan Eßer /// Whitespace. 236252884aeSStefan Eßer BC_LEX_WHITESPACE, 237252884aeSStefan Eßer 23844d4804dSStefan Eßer /// Left parenthesis. 239252884aeSStefan Eßer BC_LEX_LPAREN, 24044d4804dSStefan Eßer 24144d4804dSStefan Eßer /// Right parenthesis. 242252884aeSStefan Eßer BC_LEX_RPAREN, 243252884aeSStefan Eßer 24444d4804dSStefan Eßer /// Left bracket. 245252884aeSStefan Eßer BC_LEX_LBRACKET, 24644d4804dSStefan Eßer 24744d4804dSStefan Eßer /// Comma. 248252884aeSStefan Eßer BC_LEX_COMMA, 24944d4804dSStefan Eßer 25044d4804dSStefan Eßer /// Right bracket. 251252884aeSStefan Eßer BC_LEX_RBRACKET, 252252884aeSStefan Eßer 25344d4804dSStefan Eßer /// Left brace. 254252884aeSStefan Eßer BC_LEX_LBRACE, 25544d4804dSStefan Eßer 25644d4804dSStefan Eßer /// Semicolon. 257252884aeSStefan Eßer BC_LEX_SCOLON, 25844d4804dSStefan Eßer 25944d4804dSStefan Eßer /// Right brace. 260252884aeSStefan Eßer BC_LEX_RBRACE, 261252884aeSStefan Eßer 26244d4804dSStefan Eßer /// String. 263252884aeSStefan Eßer BC_LEX_STR, 26444d4804dSStefan Eßer 26544d4804dSStefan Eßer /// Identifier/name. 266252884aeSStefan Eßer BC_LEX_NAME, 26744d4804dSStefan Eßer 26844d4804dSStefan Eßer /// Constant number. 269252884aeSStefan Eßer BC_LEX_NUMBER, 270252884aeSStefan Eßer 27144d4804dSStefan Eßer // These keywords are in the order they are in for a reason. Don't change 27244d4804dSStefan Eßer // the order unless you want a bunch of weird failures in the test suite. 27344d4804dSStefan Eßer // In fact, almost all of these tokens are in a specific order for a reason. 27444d4804dSStefan Eßer 275252884aeSStefan Eßer #if BC_ENABLED 27644d4804dSStefan Eßer 27744d4804dSStefan Eßer /// bc auto keyword. 278252884aeSStefan Eßer BC_LEX_KW_AUTO, 27944d4804dSStefan Eßer 28044d4804dSStefan Eßer /// bc break keyword. 281252884aeSStefan Eßer BC_LEX_KW_BREAK, 28244d4804dSStefan Eßer 28344d4804dSStefan Eßer /// bc continue keyword. 284252884aeSStefan Eßer BC_LEX_KW_CONTINUE, 28544d4804dSStefan Eßer 28644d4804dSStefan Eßer /// bc define keyword. 287252884aeSStefan Eßer BC_LEX_KW_DEFINE, 28844d4804dSStefan Eßer 28944d4804dSStefan Eßer /// bc for keyword. 290252884aeSStefan Eßer BC_LEX_KW_FOR, 29144d4804dSStefan Eßer 29244d4804dSStefan Eßer /// bc if keyword. 293252884aeSStefan Eßer BC_LEX_KW_IF, 29444d4804dSStefan Eßer 29544d4804dSStefan Eßer /// bc limits keyword. 296252884aeSStefan Eßer BC_LEX_KW_LIMITS, 29744d4804dSStefan Eßer 29844d4804dSStefan Eßer /// bc return keyword. 299252884aeSStefan Eßer BC_LEX_KW_RETURN, 30044d4804dSStefan Eßer 30144d4804dSStefan Eßer /// bc while keyword. 302252884aeSStefan Eßer BC_LEX_KW_WHILE, 30344d4804dSStefan Eßer 30444d4804dSStefan Eßer /// bc halt keyword. 305252884aeSStefan Eßer BC_LEX_KW_HALT, 30644d4804dSStefan Eßer 30744d4804dSStefan Eßer /// bc last keyword. 308252884aeSStefan Eßer BC_LEX_KW_LAST, 30944d4804dSStefan Eßer 310252884aeSStefan Eßer #endif // BC_ENABLED 31144d4804dSStefan Eßer 31244d4804dSStefan Eßer /// bc ibase keyword. 313252884aeSStefan Eßer BC_LEX_KW_IBASE, 31444d4804dSStefan Eßer 31544d4804dSStefan Eßer /// bc obase keyword. 316252884aeSStefan Eßer BC_LEX_KW_OBASE, 31744d4804dSStefan Eßer 31844d4804dSStefan Eßer /// bc scale keyword. 319252884aeSStefan Eßer BC_LEX_KW_SCALE, 32044d4804dSStefan Eßer 32144d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 32244d4804dSStefan Eßer 32344d4804dSStefan Eßer /// bc seed keyword. 324252884aeSStefan Eßer BC_LEX_KW_SEED, 32544d4804dSStefan Eßer 32644d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 32744d4804dSStefan Eßer 32844d4804dSStefan Eßer /// bc length keyword. 329252884aeSStefan Eßer BC_LEX_KW_LENGTH, 33044d4804dSStefan Eßer 33144d4804dSStefan Eßer /// bc print keyword. 332252884aeSStefan Eßer BC_LEX_KW_PRINT, 33344d4804dSStefan Eßer 33444d4804dSStefan Eßer /// bc sqrt keyword. 335252884aeSStefan Eßer BC_LEX_KW_SQRT, 33644d4804dSStefan Eßer 33744d4804dSStefan Eßer /// bc abs keyword. 338252884aeSStefan Eßer BC_LEX_KW_ABS, 33944d4804dSStefan Eßer 340d101cdd6SStefan Eßer /// bc is_number keyword. 341d101cdd6SStefan Eßer BC_LEX_KW_IS_NUMBER, 342d101cdd6SStefan Eßer 343d101cdd6SStefan Eßer /// bc is_string keyword. 344d101cdd6SStefan Eßer BC_LEX_KW_IS_STRING, 345d101cdd6SStefan Eßer 34644d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 34744d4804dSStefan Eßer 34844d4804dSStefan Eßer /// bc irand keyword. 349252884aeSStefan Eßer BC_LEX_KW_IRAND, 35044d4804dSStefan Eßer 35144d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 35244d4804dSStefan Eßer 35344d4804dSStefan Eßer /// bc asciffy keyword. 35444d4804dSStefan Eßer BC_LEX_KW_ASCIIFY, 35544d4804dSStefan Eßer 35644d4804dSStefan Eßer /// bc modexp keyword. 35744d4804dSStefan Eßer BC_LEX_KW_MODEXP, 35844d4804dSStefan Eßer 35944d4804dSStefan Eßer /// bc divmod keyword. 36044d4804dSStefan Eßer BC_LEX_KW_DIVMOD, 36144d4804dSStefan Eßer 36244d4804dSStefan Eßer /// bc quit keyword. 363252884aeSStefan Eßer BC_LEX_KW_QUIT, 36444d4804dSStefan Eßer 36544d4804dSStefan Eßer /// bc read keyword. 366252884aeSStefan Eßer BC_LEX_KW_READ, 36744d4804dSStefan Eßer 36844d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 36944d4804dSStefan Eßer 37044d4804dSStefan Eßer /// bc rand keyword. 371252884aeSStefan Eßer BC_LEX_KW_RAND, 37244d4804dSStefan Eßer 37344d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 37444d4804dSStefan Eßer 37544d4804dSStefan Eßer /// bc maxibase keyword. 376252884aeSStefan Eßer BC_LEX_KW_MAXIBASE, 37744d4804dSStefan Eßer 37844d4804dSStefan Eßer /// bc maxobase keyword. 379252884aeSStefan Eßer BC_LEX_KW_MAXOBASE, 38044d4804dSStefan Eßer 38144d4804dSStefan Eßer /// bc maxscale keyword. 382252884aeSStefan Eßer BC_LEX_KW_MAXSCALE, 38344d4804dSStefan Eßer 38444d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 385d101cdd6SStefan Eßer 38644d4804dSStefan Eßer /// bc maxrand keyword. 387252884aeSStefan Eßer BC_LEX_KW_MAXRAND, 388d101cdd6SStefan Eßer 38944d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 39044d4804dSStefan Eßer 391d43fa8efSStefan Eßer /// bc line_length keyword. 392d43fa8efSStefan Eßer BC_LEX_KW_LINE_LENGTH, 393d43fa8efSStefan Eßer 394d43fa8efSStefan Eßer #if BC_ENABLED 395d43fa8efSStefan Eßer 396d43fa8efSStefan Eßer /// bc global_stacks keyword. 397d43fa8efSStefan Eßer BC_LEX_KW_GLOBAL_STACKS, 398d43fa8efSStefan Eßer 399d43fa8efSStefan Eßer #endif // BC_ENABLED 400d43fa8efSStefan Eßer 401d43fa8efSStefan Eßer /// bc leading_zero keyword. 402d43fa8efSStefan Eßer BC_LEX_KW_LEADING_ZERO, 403d43fa8efSStefan Eßer 40444d4804dSStefan Eßer /// bc stream keyword. 40544d4804dSStefan Eßer BC_LEX_KW_STREAM, 40644d4804dSStefan Eßer 40744d4804dSStefan Eßer /// bc else keyword. 408252884aeSStefan Eßer BC_LEX_KW_ELSE, 409252884aeSStefan Eßer 410252884aeSStefan Eßer #if DC_ENABLED 411252884aeSStefan Eßer 412103d7cdfSStefan Eßer /// dc extended registers keyword. 413103d7cdfSStefan Eßer BC_LEX_EXTENDED_REGISTERS, 414103d7cdfSStefan Eßer 41544d4804dSStefan Eßer /// A special token for dc to calculate equal without a register. 41644d4804dSStefan Eßer BC_LEX_EQ_NO_REG, 41744d4804dSStefan Eßer 41844d4804dSStefan Eßer /// Colon (array) operator. 419252884aeSStefan Eßer BC_LEX_COLON, 42044d4804dSStefan Eßer 42144d4804dSStefan Eßer /// Execute command. 422252884aeSStefan Eßer BC_LEX_EXECUTE, 42344d4804dSStefan Eßer 42444d4804dSStefan Eßer /// Print stack command. 425252884aeSStefan Eßer BC_LEX_PRINT_STACK, 42644d4804dSStefan Eßer 42744d4804dSStefan Eßer /// Clear stack command. 428252884aeSStefan Eßer BC_LEX_CLEAR_STACK, 42944d4804dSStefan Eßer 43044d4804dSStefan Eßer /// Register stack level command. 43144d4804dSStefan Eßer BC_LEX_REG_STACK_LEVEL, 43244d4804dSStefan Eßer 43344d4804dSStefan Eßer /// Main stack level command. 434252884aeSStefan Eßer BC_LEX_STACK_LEVEL, 43544d4804dSStefan Eßer 43644d4804dSStefan Eßer /// Duplicate command. 437252884aeSStefan Eßer BC_LEX_DUPLICATE, 43844d4804dSStefan Eßer 43944d4804dSStefan Eßer /// Swap (reverse) command. 440252884aeSStefan Eßer BC_LEX_SWAP, 44144d4804dSStefan Eßer 44244d4804dSStefan Eßer /// Pop (remove) command. 443252884aeSStefan Eßer BC_LEX_POP, 444252884aeSStefan Eßer 44544d4804dSStefan Eßer /// Store ibase command. 446252884aeSStefan Eßer BC_LEX_STORE_IBASE, 44744d4804dSStefan Eßer 44844d4804dSStefan Eßer /// Store obase command. 449252884aeSStefan Eßer BC_LEX_STORE_OBASE, 45044d4804dSStefan Eßer 45144d4804dSStefan Eßer /// Store scale command. 452252884aeSStefan Eßer BC_LEX_STORE_SCALE, 45344d4804dSStefan Eßer 454252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 455d101cdd6SStefan Eßer 45644d4804dSStefan Eßer /// Store seed command. 457252884aeSStefan Eßer BC_LEX_STORE_SEED, 458d101cdd6SStefan Eßer 459252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 46044d4804dSStefan Eßer 46144d4804dSStefan Eßer /// Load variable onto stack command. 462252884aeSStefan Eßer BC_LEX_LOAD, 46344d4804dSStefan Eßer 46444d4804dSStefan Eßer /// Pop off of variable stack onto results stack command. 465252884aeSStefan Eßer BC_LEX_LOAD_POP, 46644d4804dSStefan Eßer 46744d4804dSStefan Eßer /// Push onto variable stack command. 468252884aeSStefan Eßer BC_LEX_STORE_PUSH, 46944d4804dSStefan Eßer 47044d4804dSStefan Eßer /// Print with pop command. 471252884aeSStefan Eßer BC_LEX_PRINT_POP, 47244d4804dSStefan Eßer 47344d4804dSStefan Eßer /// Parameterized quit command. 474252884aeSStefan Eßer BC_LEX_NQUIT, 47544d4804dSStefan Eßer 47644d4804dSStefan Eßer /// Execution stack depth command. 47744d4804dSStefan Eßer BC_LEX_EXEC_STACK_LENGTH, 47844d4804dSStefan Eßer 47944d4804dSStefan Eßer /// Scale of number command. This is needed specifically for dc because bc 48044d4804dSStefan Eßer /// parses the scale function in parts. 481252884aeSStefan Eßer BC_LEX_SCALE_FACTOR, 48244d4804dSStefan Eßer 48344d4804dSStefan Eßer /// Array length command. This is needed specifically for dc because bc 48444d4804dSStefan Eßer /// just reuses its length keyword. 48544d4804dSStefan Eßer BC_LEX_ARRAY_LENGTH, 48644d4804dSStefan Eßer 487252884aeSStefan Eßer #endif // DC_ENABLED 488252884aeSStefan Eßer 489252884aeSStefan Eßer } BcLexType; 490252884aeSStefan Eßer 491252884aeSStefan Eßer struct BcLex; 492252884aeSStefan Eßer 49344d4804dSStefan Eßer /** 49444d4804dSStefan Eßer * A function pointer to call when another token is needed. Mostly called by the 49544d4804dSStefan Eßer * parser. 49644d4804dSStefan Eßer * @param l The lexer. 49744d4804dSStefan Eßer */ 49844d4804dSStefan Eßer typedef void (*BcLexNext)(struct BcLex* l); 49944d4804dSStefan Eßer 50044d4804dSStefan Eßer /// The lexer. 50178bc019dSStefan Eßer typedef struct BcLex 50278bc019dSStefan Eßer { 50344d4804dSStefan Eßer /// A pointer to the text to lex. 504252884aeSStefan Eßer const char* buf; 50544d4804dSStefan Eßer 50644d4804dSStefan Eßer /// The current index into buf. 507252884aeSStefan Eßer size_t i; 50844d4804dSStefan Eßer 50944d4804dSStefan Eßer /// The current line. 510252884aeSStefan Eßer size_t line; 51144d4804dSStefan Eßer 51244d4804dSStefan Eßer /// The length of buf. 513252884aeSStefan Eßer size_t len; 514252884aeSStefan Eßer 51544d4804dSStefan Eßer /// The current token. 516252884aeSStefan Eßer BcLexType t; 51744d4804dSStefan Eßer 51844d4804dSStefan Eßer /// The previous token. 519252884aeSStefan Eßer BcLexType last; 52044d4804dSStefan Eßer 52144d4804dSStefan Eßer /// A string to store extra data for tokens. For example, the @a BC_LEX_STR 52244d4804dSStefan Eßer /// token really needs to store the actual string, and numbers also need the 52344d4804dSStefan Eßer /// string. 524252884aeSStefan Eßer BcVec str; 525252884aeSStefan Eßer 526d101cdd6SStefan Eßer /// The mode the lexer is in. 527d101cdd6SStefan Eßer BcMode mode; 52823210c9fSStefan Eßer 529252884aeSStefan Eßer } BcLex; 530252884aeSStefan Eßer 53144d4804dSStefan Eßer /** 53244d4804dSStefan Eßer * Initializes a lexer. 53344d4804dSStefan Eßer * @param l The lexer to initialize. 53444d4804dSStefan Eßer */ 53578bc019dSStefan Eßer void 53678bc019dSStefan Eßer bc_lex_init(BcLex* l); 53744d4804dSStefan Eßer 53844d4804dSStefan Eßer /** 539103d7cdfSStefan Eßer * Frees a lexer. This is not guarded by #if BC_DEBUG because a separate 54044d4804dSStefan Eßer * parser is created at runtime to parse read() expressions and dc strings, and 54144d4804dSStefan Eßer * that parser needs a lexer. 54244d4804dSStefan Eßer * @param l The lexer to free. 54344d4804dSStefan Eßer */ 54478bc019dSStefan Eßer void 54578bc019dSStefan Eßer bc_lex_free(BcLex* l); 54644d4804dSStefan Eßer 54744d4804dSStefan Eßer /** 54844d4804dSStefan Eßer * Sets the filename that the lexer will be lexing. 54944d4804dSStefan Eßer * @param l The lexer. 55044d4804dSStefan Eßer * @param file The filename that the lexer will lex. 55144d4804dSStefan Eßer */ 55278bc019dSStefan Eßer void 55378bc019dSStefan Eßer bc_lex_file(BcLex* l, const char* file); 55444d4804dSStefan Eßer 55544d4804dSStefan Eßer /** 55644d4804dSStefan Eßer * Sets the text the lexer will lex. 55744d4804dSStefan Eßer * @param l The lexer. 55844d4804dSStefan Eßer * @param text The text to lex. 559d101cdd6SStefan Eßer * @param mode The mode to lex in. 56044d4804dSStefan Eßer */ 56178bc019dSStefan Eßer void 562d101cdd6SStefan Eßer bc_lex_text(BcLex* l, const char* text, BcMode mode); 56344d4804dSStefan Eßer 56444d4804dSStefan Eßer /** 56544d4804dSStefan Eßer * Generic next function for the parser to call. It takes care of calling the 56644d4804dSStefan Eßer * correct @a BcLexNext function and consuming whitespace. 56744d4804dSStefan Eßer * @param l The lexer. 56844d4804dSStefan Eßer */ 56978bc019dSStefan Eßer void 57078bc019dSStefan Eßer bc_lex_next(BcLex* l); 571252884aeSStefan Eßer 57244d4804dSStefan Eßer /** 57344d4804dSStefan Eßer * Lexes a line comment (one beginning with '#' and going to a newline). 57444d4804dSStefan Eßer * @param l The lexer. 57544d4804dSStefan Eßer */ 57678bc019dSStefan Eßer void 57778bc019dSStefan Eßer bc_lex_lineComment(BcLex* l); 57844d4804dSStefan Eßer 57944d4804dSStefan Eßer /** 58044d4804dSStefan Eßer * Lexes a general comment (C-style comment). 58144d4804dSStefan Eßer * @param l The lexer. 58244d4804dSStefan Eßer */ 58378bc019dSStefan Eßer void 58478bc019dSStefan Eßer bc_lex_comment(BcLex* l); 58544d4804dSStefan Eßer 58644d4804dSStefan Eßer /** 58744d4804dSStefan Eßer * Lexes whitespace, finding as much as possible. 58844d4804dSStefan Eßer * @param l The lexer. 58944d4804dSStefan Eßer */ 59078bc019dSStefan Eßer void 59178bc019dSStefan Eßer bc_lex_whitespace(BcLex* l); 59244d4804dSStefan Eßer 59344d4804dSStefan Eßer /** 59444d4804dSStefan Eßer * Lexes a number that begins with char @a start. This takes care of parsing 59544d4804dSStefan Eßer * numbers in scientific and engineering notations. 59644d4804dSStefan Eßer * @param l The lexer. 59744d4804dSStefan Eßer * @param start The starting char of the number. To detect a number and call 59844d4804dSStefan Eßer * this function, the lexer had to eat the first char. It fixes 59944d4804dSStefan Eßer * that by passing it in. 60044d4804dSStefan Eßer */ 60178bc019dSStefan Eßer void 60278bc019dSStefan Eßer bc_lex_number(BcLex* l, char start); 60344d4804dSStefan Eßer 60444d4804dSStefan Eßer /** 60544d4804dSStefan Eßer * Lexes a name/identifier. 60644d4804dSStefan Eßer * @param l The lexer. 60744d4804dSStefan Eßer */ 60878bc019dSStefan Eßer void 60978bc019dSStefan Eßer bc_lex_name(BcLex* l); 61044d4804dSStefan Eßer 61144d4804dSStefan Eßer /** 61244d4804dSStefan Eßer * Lexes common whitespace characters. 61344d4804dSStefan Eßer * @param l The lexer. 61444d4804dSStefan Eßer * @param c The character to lex. 61544d4804dSStefan Eßer */ 61678bc019dSStefan Eßer void 61778bc019dSStefan Eßer bc_lex_commonTokens(BcLex* l, char c); 618252884aeSStefan Eßer 61944d4804dSStefan Eßer /** 62044d4804dSStefan Eßer * Throws a parse error because char @a c was invalid. 62144d4804dSStefan Eßer * @param l The lexer. 62244d4804dSStefan Eßer * @param c The problem character. 62344d4804dSStefan Eßer */ 62478bc019dSStefan Eßer void 62578bc019dSStefan Eßer bc_lex_invalidChar(BcLex* l, char c); 626252884aeSStefan Eßer 62744d4804dSStefan Eßer /** 62844d4804dSStefan Eßer * Reads a line from stdin and puts it into the lexer's buffer. 62944d4804dSStefan Eßer * @param l The lexer. 63044d4804dSStefan Eßer */ 63178bc019dSStefan Eßer bool 63278bc019dSStefan Eßer bc_lex_readLine(BcLex* l); 63344d4804dSStefan Eßer 634252884aeSStefan Eßer #endif // BC_LEX_H 635