1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 610328f8bSStefan Eßer * Copyright (c) 2018-2021 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 4644d4804dSStefan Eßer // Two convencience macros for throwing errors in lex code. They take care of 4744d4804dSStefan Eßer // plumbing like passing in the current line the lexer is on. 4850696a6eSStefan Eßer #define bc_lex_err(l, e) (bc_vm_handleError((e), (l)->line)) 4950696a6eSStefan Eßer #define bc_lex_verr(l, e, ...) (bc_vm_handleError((e), (l)->line, __VA_ARGS__)) 50252884aeSStefan Eßer 5144d4804dSStefan Eßer // BC_LEX_NEG_CHAR returns the char that corresponds to negative for the 5244d4804dSStefan Eßer // current calculator. 5344d4804dSStefan Eßer // 5444d4804dSStefan Eßer // BC_LEX_LAST_NUM_CHAR returns the char that corresponds to the last valid 5544d4804dSStefan Eßer // char for numbers. In bc and dc, capital letters are part of numbers, to a 5644d4804dSStefan Eßer // point. (dc only goes up to hex, so its last valid char is 'F'.) 573aa99676SStefan Eßer #if BC_ENABLED 583aa99676SStefan Eßer 593aa99676SStefan Eßer #if DC_ENABLED 60252884aeSStefan Eßer #define BC_LEX_NEG_CHAR (BC_IS_BC ? '-' : '_') 61252884aeSStefan Eßer #define BC_LEX_LAST_NUM_CHAR (BC_IS_BC ? 'Z' : 'F') 623aa99676SStefan Eßer #else // DC_ENABLED 633aa99676SStefan Eßer #define BC_LEX_NEG_CHAR ('-') 643aa99676SStefan Eßer #define BC_LEX_LAST_NUM_CHAR ('Z') 653aa99676SStefan Eßer #endif // DC_ENABLED 663aa99676SStefan Eßer 673aa99676SStefan Eßer #else // BC_ENABLED 683aa99676SStefan Eßer 693aa99676SStefan Eßer #define BC_LEX_NEG_CHAR ('_') 703aa99676SStefan Eßer #define BC_LEX_LAST_NUM_CHAR ('F') 713aa99676SStefan Eßer 723aa99676SStefan Eßer #endif // BC_ENABLED 733aa99676SStefan Eßer 7444d4804dSStefan Eßer /** 7544d4804dSStefan Eßer * Returns true if c is a valid number character. 7644d4804dSStefan Eßer * @param c The char to check. 7744d4804dSStefan Eßer * @param pt If a decimal point has already been seen. 7844d4804dSStefan Eßer * @param int_only True if the number is expected to be an int only, false if 7944d4804dSStefan Eßer * non-integers are allowed. 8044d4804dSStefan Eßer * @return True if @a c is a valid number character. 8144d4804dSStefan Eßer */ 82252884aeSStefan Eßer #define BC_LEX_NUM_CHAR(c, pt, int_only) \ 8344d4804dSStefan Eßer (isdigit(c) != 0 || ((c) >= 'A' && (c) <= BC_LEX_LAST_NUM_CHAR) || \ 84252884aeSStefan Eßer ((c) == '.' && !(pt) && !(int_only))) 85252884aeSStefan Eßer 8644d4804dSStefan Eßer /// An enum of lex token types. 87*78bc019dSStefan Eßer typedef enum BcLexType 88*78bc019dSStefan Eßer { 8944d4804dSStefan Eßer /// End of file. 90252884aeSStefan Eßer BC_LEX_EOF, 9144d4804dSStefan Eßer 9244d4804dSStefan Eßer /// Marker for invalid tokens, used by bc and dc for const data. 93252884aeSStefan Eßer BC_LEX_INVALID, 94252884aeSStefan Eßer 95252884aeSStefan Eßer #if BC_ENABLED 9644d4804dSStefan Eßer 9744d4804dSStefan Eßer /// Increment operator. 98252884aeSStefan Eßer BC_LEX_OP_INC, 9944d4804dSStefan Eßer 10044d4804dSStefan Eßer /// Decrement operator. 101252884aeSStefan Eßer BC_LEX_OP_DEC, 10244d4804dSStefan Eßer 103252884aeSStefan Eßer #endif // BC_ENABLED 104252884aeSStefan Eßer 10544d4804dSStefan Eßer /// BC_LEX_NEG is not used in lexing; it is only for parsing. The lexer 10644d4804dSStefan Eßer /// marks all '-' characters as BC_LEX_OP_MINUS, but the parser needs to be 10744d4804dSStefan Eßer /// able to distinguish them. 108252884aeSStefan Eßer BC_LEX_NEG, 10944d4804dSStefan Eßer 11044d4804dSStefan Eßer /// Boolean not. 111252884aeSStefan Eßer BC_LEX_OP_BOOL_NOT, 11244d4804dSStefan Eßer 113252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 11444d4804dSStefan Eßer 11544d4804dSStefan Eßer /// Truncation operator. 116252884aeSStefan Eßer BC_LEX_OP_TRUNC, 11744d4804dSStefan Eßer 118252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 119252884aeSStefan Eßer 12044d4804dSStefan Eßer /// Power operator. 121252884aeSStefan Eßer BC_LEX_OP_POWER, 12244d4804dSStefan Eßer 12344d4804dSStefan Eßer /// Multiplication operator. 124252884aeSStefan Eßer BC_LEX_OP_MULTIPLY, 12544d4804dSStefan Eßer 12644d4804dSStefan Eßer /// Division operator. 127252884aeSStefan Eßer BC_LEX_OP_DIVIDE, 12844d4804dSStefan Eßer 12944d4804dSStefan Eßer /// Modulus operator. 130252884aeSStefan Eßer BC_LEX_OP_MODULUS, 13144d4804dSStefan Eßer 13244d4804dSStefan Eßer /// Addition operator. 133252884aeSStefan Eßer BC_LEX_OP_PLUS, 13444d4804dSStefan Eßer 13544d4804dSStefan Eßer /// Subtraction operator. 136252884aeSStefan Eßer BC_LEX_OP_MINUS, 137252884aeSStefan Eßer 138252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 13944d4804dSStefan Eßer /// Places (truncate or extend) operator. 140252884aeSStefan Eßer BC_LEX_OP_PLACES, 141252884aeSStefan Eßer 14244d4804dSStefan Eßer /// Left (decimal) shift operator. 143252884aeSStefan Eßer BC_LEX_OP_LSHIFT, 14444d4804dSStefan Eßer 14544d4804dSStefan Eßer /// Right (decimal) shift operator. 146252884aeSStefan Eßer BC_LEX_OP_RSHIFT, 147252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 148252884aeSStefan Eßer 14944d4804dSStefan Eßer /// Equal operator. 150252884aeSStefan Eßer BC_LEX_OP_REL_EQ, 15144d4804dSStefan Eßer 15244d4804dSStefan Eßer /// Less than or equal operator. 153252884aeSStefan Eßer BC_LEX_OP_REL_LE, 15444d4804dSStefan Eßer 15544d4804dSStefan Eßer /// Greater than or equal operator. 156252884aeSStefan Eßer BC_LEX_OP_REL_GE, 15744d4804dSStefan Eßer 15844d4804dSStefan Eßer /// Not equal operator. 159252884aeSStefan Eßer BC_LEX_OP_REL_NE, 16044d4804dSStefan Eßer 16144d4804dSStefan Eßer /// Less than operator. 162252884aeSStefan Eßer BC_LEX_OP_REL_LT, 16344d4804dSStefan Eßer 16444d4804dSStefan Eßer /// Greater than operator. 165252884aeSStefan Eßer BC_LEX_OP_REL_GT, 166252884aeSStefan Eßer 16744d4804dSStefan Eßer /// Boolean or operator. 168252884aeSStefan Eßer BC_LEX_OP_BOOL_OR, 16944d4804dSStefan Eßer 17044d4804dSStefan Eßer /// Boolean and operator. 171252884aeSStefan Eßer BC_LEX_OP_BOOL_AND, 172252884aeSStefan Eßer 173252884aeSStefan Eßer #if BC_ENABLED 17444d4804dSStefan Eßer /// Power assignment operator. 175252884aeSStefan Eßer BC_LEX_OP_ASSIGN_POWER, 17644d4804dSStefan Eßer 17744d4804dSStefan Eßer /// Multiplication assignment operator. 178252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MULTIPLY, 17944d4804dSStefan Eßer 18044d4804dSStefan Eßer /// Division assignment operator. 181252884aeSStefan Eßer BC_LEX_OP_ASSIGN_DIVIDE, 18244d4804dSStefan Eßer 18344d4804dSStefan Eßer /// Modulus assignment operator. 184252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MODULUS, 18544d4804dSStefan Eßer 18644d4804dSStefan Eßer /// Addition assignment operator. 187252884aeSStefan Eßer BC_LEX_OP_ASSIGN_PLUS, 18844d4804dSStefan Eßer 18944d4804dSStefan Eßer /// Subtraction assignment operator. 190252884aeSStefan Eßer BC_LEX_OP_ASSIGN_MINUS, 19144d4804dSStefan Eßer 192252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 19344d4804dSStefan Eßer 19444d4804dSStefan Eßer /// Places (truncate or extend) assignment operator. 195252884aeSStefan Eßer BC_LEX_OP_ASSIGN_PLACES, 19644d4804dSStefan Eßer 19744d4804dSStefan Eßer /// Left (decimal) shift assignment operator. 198252884aeSStefan Eßer BC_LEX_OP_ASSIGN_LSHIFT, 19944d4804dSStefan Eßer 20044d4804dSStefan Eßer /// Right (decimal) shift assignment operator. 201252884aeSStefan Eßer BC_LEX_OP_ASSIGN_RSHIFT, 20244d4804dSStefan Eßer 203252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 204252884aeSStefan Eßer #endif // BC_ENABLED 20544d4804dSStefan Eßer 20644d4804dSStefan Eßer /// Assignment operator. 207252884aeSStefan Eßer BC_LEX_OP_ASSIGN, 208252884aeSStefan Eßer 20944d4804dSStefan Eßer /// Newline. 210252884aeSStefan Eßer BC_LEX_NLINE, 21144d4804dSStefan Eßer 21244d4804dSStefan Eßer /// Whitespace. 213252884aeSStefan Eßer BC_LEX_WHITESPACE, 214252884aeSStefan Eßer 21544d4804dSStefan Eßer /// Left parenthesis. 216252884aeSStefan Eßer BC_LEX_LPAREN, 21744d4804dSStefan Eßer 21844d4804dSStefan Eßer /// Right parenthesis. 219252884aeSStefan Eßer BC_LEX_RPAREN, 220252884aeSStefan Eßer 22144d4804dSStefan Eßer /// Left bracket. 222252884aeSStefan Eßer BC_LEX_LBRACKET, 22344d4804dSStefan Eßer 22444d4804dSStefan Eßer /// Comma. 225252884aeSStefan Eßer BC_LEX_COMMA, 22644d4804dSStefan Eßer 22744d4804dSStefan Eßer /// Right bracket. 228252884aeSStefan Eßer BC_LEX_RBRACKET, 229252884aeSStefan Eßer 23044d4804dSStefan Eßer /// Left brace. 231252884aeSStefan Eßer BC_LEX_LBRACE, 23244d4804dSStefan Eßer 23344d4804dSStefan Eßer /// Semicolon. 234252884aeSStefan Eßer BC_LEX_SCOLON, 23544d4804dSStefan Eßer 23644d4804dSStefan Eßer /// Right brace. 237252884aeSStefan Eßer BC_LEX_RBRACE, 238252884aeSStefan Eßer 23944d4804dSStefan Eßer /// String. 240252884aeSStefan Eßer BC_LEX_STR, 24144d4804dSStefan Eßer 24244d4804dSStefan Eßer /// Identifier/name. 243252884aeSStefan Eßer BC_LEX_NAME, 24444d4804dSStefan Eßer 24544d4804dSStefan Eßer /// Constant number. 246252884aeSStefan Eßer BC_LEX_NUMBER, 247252884aeSStefan Eßer 24844d4804dSStefan Eßer // These keywords are in the order they are in for a reason. Don't change 24944d4804dSStefan Eßer // the order unless you want a bunch of weird failures in the test suite. 25044d4804dSStefan Eßer // In fact, almost all of these tokens are in a specific order for a reason. 25144d4804dSStefan Eßer 252252884aeSStefan Eßer #if BC_ENABLED 25344d4804dSStefan Eßer 25444d4804dSStefan Eßer /// bc auto keyword. 255252884aeSStefan Eßer BC_LEX_KW_AUTO, 25644d4804dSStefan Eßer 25744d4804dSStefan Eßer /// bc break keyword. 258252884aeSStefan Eßer BC_LEX_KW_BREAK, 25944d4804dSStefan Eßer 26044d4804dSStefan Eßer /// bc continue keyword. 261252884aeSStefan Eßer BC_LEX_KW_CONTINUE, 26244d4804dSStefan Eßer 26344d4804dSStefan Eßer /// bc define keyword. 264252884aeSStefan Eßer BC_LEX_KW_DEFINE, 26544d4804dSStefan Eßer 26644d4804dSStefan Eßer /// bc for keyword. 267252884aeSStefan Eßer BC_LEX_KW_FOR, 26844d4804dSStefan Eßer 26944d4804dSStefan Eßer /// bc if keyword. 270252884aeSStefan Eßer BC_LEX_KW_IF, 27144d4804dSStefan Eßer 27244d4804dSStefan Eßer /// bc limits keyword. 273252884aeSStefan Eßer BC_LEX_KW_LIMITS, 27444d4804dSStefan Eßer 27544d4804dSStefan Eßer /// bc return keyword. 276252884aeSStefan Eßer BC_LEX_KW_RETURN, 27744d4804dSStefan Eßer 27844d4804dSStefan Eßer /// bc while keyword. 279252884aeSStefan Eßer BC_LEX_KW_WHILE, 28044d4804dSStefan Eßer 28144d4804dSStefan Eßer /// bc halt keyword. 282252884aeSStefan Eßer BC_LEX_KW_HALT, 28344d4804dSStefan Eßer 28444d4804dSStefan Eßer /// bc last keyword. 285252884aeSStefan Eßer BC_LEX_KW_LAST, 28644d4804dSStefan Eßer 287252884aeSStefan Eßer #endif // BC_ENABLED 28844d4804dSStefan Eßer 28944d4804dSStefan Eßer /// bc ibase keyword. 290252884aeSStefan Eßer BC_LEX_KW_IBASE, 29144d4804dSStefan Eßer 29244d4804dSStefan Eßer /// bc obase keyword. 293252884aeSStefan Eßer BC_LEX_KW_OBASE, 29444d4804dSStefan Eßer 29544d4804dSStefan Eßer /// bc scale keyword. 296252884aeSStefan Eßer BC_LEX_KW_SCALE, 29744d4804dSStefan Eßer 29844d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 29944d4804dSStefan Eßer 30044d4804dSStefan Eßer /// bc seed keyword. 301252884aeSStefan Eßer BC_LEX_KW_SEED, 30244d4804dSStefan Eßer 30344d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 30444d4804dSStefan Eßer 30544d4804dSStefan Eßer /// bc length keyword. 306252884aeSStefan Eßer BC_LEX_KW_LENGTH, 30744d4804dSStefan Eßer 30844d4804dSStefan Eßer /// bc print keyword. 309252884aeSStefan Eßer BC_LEX_KW_PRINT, 31044d4804dSStefan Eßer 31144d4804dSStefan Eßer /// bc sqrt keyword. 312252884aeSStefan Eßer BC_LEX_KW_SQRT, 31344d4804dSStefan Eßer 31444d4804dSStefan Eßer /// bc abs keyword. 315252884aeSStefan Eßer BC_LEX_KW_ABS, 31644d4804dSStefan Eßer 31744d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 31844d4804dSStefan Eßer 31944d4804dSStefan Eßer /// bc irand keyword. 320252884aeSStefan Eßer BC_LEX_KW_IRAND, 32144d4804dSStefan Eßer 32244d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 32344d4804dSStefan Eßer 32444d4804dSStefan Eßer /// bc asciffy keyword. 32544d4804dSStefan Eßer BC_LEX_KW_ASCIIFY, 32644d4804dSStefan Eßer 32744d4804dSStefan Eßer /// bc modexp keyword. 32844d4804dSStefan Eßer BC_LEX_KW_MODEXP, 32944d4804dSStefan Eßer 33044d4804dSStefan Eßer /// bc divmod keyword. 33144d4804dSStefan Eßer BC_LEX_KW_DIVMOD, 33244d4804dSStefan Eßer 33344d4804dSStefan Eßer /// bc quit keyword. 334252884aeSStefan Eßer BC_LEX_KW_QUIT, 33544d4804dSStefan Eßer 33644d4804dSStefan Eßer /// bc read keyword. 337252884aeSStefan Eßer BC_LEX_KW_READ, 33844d4804dSStefan Eßer 33944d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 34044d4804dSStefan Eßer 34144d4804dSStefan Eßer /// bc rand keyword. 342252884aeSStefan Eßer BC_LEX_KW_RAND, 34344d4804dSStefan Eßer 34444d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 34544d4804dSStefan Eßer 34644d4804dSStefan Eßer /// bc maxibase keyword. 347252884aeSStefan Eßer BC_LEX_KW_MAXIBASE, 34844d4804dSStefan Eßer 34944d4804dSStefan Eßer /// bc maxobase keyword. 350252884aeSStefan Eßer BC_LEX_KW_MAXOBASE, 35144d4804dSStefan Eßer 35244d4804dSStefan Eßer /// bc maxscale keyword. 353252884aeSStefan Eßer BC_LEX_KW_MAXSCALE, 35444d4804dSStefan Eßer 35544d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH 35644d4804dSStefan Eßer /// bc maxrand keyword. 357252884aeSStefan Eßer BC_LEX_KW_MAXRAND, 35844d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 35944d4804dSStefan Eßer 360d43fa8efSStefan Eßer /// bc line_length keyword. 361d43fa8efSStefan Eßer BC_LEX_KW_LINE_LENGTH, 362d43fa8efSStefan Eßer 363d43fa8efSStefan Eßer #if BC_ENABLED 364d43fa8efSStefan Eßer 365d43fa8efSStefan Eßer /// bc global_stacks keyword. 366d43fa8efSStefan Eßer BC_LEX_KW_GLOBAL_STACKS, 367d43fa8efSStefan Eßer 368d43fa8efSStefan Eßer #endif // BC_ENABLED 369d43fa8efSStefan Eßer 370d43fa8efSStefan Eßer /// bc leading_zero keyword. 371d43fa8efSStefan Eßer BC_LEX_KW_LEADING_ZERO, 372d43fa8efSStefan Eßer 37344d4804dSStefan Eßer /// bc stream keyword. 37444d4804dSStefan Eßer BC_LEX_KW_STREAM, 37544d4804dSStefan Eßer 37644d4804dSStefan Eßer /// bc else keyword. 377252884aeSStefan Eßer BC_LEX_KW_ELSE, 378252884aeSStefan Eßer 379252884aeSStefan Eßer #if DC_ENABLED 380252884aeSStefan Eßer 38144d4804dSStefan Eßer /// A special token for dc to calculate equal without a register. 38244d4804dSStefan Eßer BC_LEX_EQ_NO_REG, 38344d4804dSStefan Eßer 38444d4804dSStefan Eßer /// Colon (array) operator. 385252884aeSStefan Eßer BC_LEX_COLON, 38644d4804dSStefan Eßer 38744d4804dSStefan Eßer /// Execute command. 388252884aeSStefan Eßer BC_LEX_EXECUTE, 38944d4804dSStefan Eßer 39044d4804dSStefan Eßer /// Print stack command. 391252884aeSStefan Eßer BC_LEX_PRINT_STACK, 39244d4804dSStefan Eßer 39344d4804dSStefan Eßer /// Clear stack command. 394252884aeSStefan Eßer BC_LEX_CLEAR_STACK, 39544d4804dSStefan Eßer 39644d4804dSStefan Eßer /// Register stack level command. 39744d4804dSStefan Eßer BC_LEX_REG_STACK_LEVEL, 39844d4804dSStefan Eßer 39944d4804dSStefan Eßer /// Main stack level command. 400252884aeSStefan Eßer BC_LEX_STACK_LEVEL, 40144d4804dSStefan Eßer 40244d4804dSStefan Eßer /// Duplicate command. 403252884aeSStefan Eßer BC_LEX_DUPLICATE, 40444d4804dSStefan Eßer 40544d4804dSStefan Eßer /// Swap (reverse) command. 406252884aeSStefan Eßer BC_LEX_SWAP, 40744d4804dSStefan Eßer 40844d4804dSStefan Eßer /// Pop (remove) command. 409252884aeSStefan Eßer BC_LEX_POP, 410252884aeSStefan Eßer 41144d4804dSStefan Eßer /// Store ibase command. 412252884aeSStefan Eßer BC_LEX_STORE_IBASE, 41344d4804dSStefan Eßer 41444d4804dSStefan Eßer /// Store obase command. 415252884aeSStefan Eßer BC_LEX_STORE_OBASE, 41644d4804dSStefan Eßer 41744d4804dSStefan Eßer /// Store scale command. 418252884aeSStefan Eßer BC_LEX_STORE_SCALE, 41944d4804dSStefan Eßer 420252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 42144d4804dSStefan Eßer /// Store seed command. 422252884aeSStefan Eßer BC_LEX_STORE_SEED, 423252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 42444d4804dSStefan Eßer 42544d4804dSStefan Eßer /// Load variable onto stack command. 426252884aeSStefan Eßer BC_LEX_LOAD, 42744d4804dSStefan Eßer 42844d4804dSStefan Eßer /// Pop off of variable stack onto results stack command. 429252884aeSStefan Eßer BC_LEX_LOAD_POP, 43044d4804dSStefan Eßer 43144d4804dSStefan Eßer /// Push onto variable stack command. 432252884aeSStefan Eßer BC_LEX_STORE_PUSH, 43344d4804dSStefan Eßer 43444d4804dSStefan Eßer /// Print with pop command. 435252884aeSStefan Eßer BC_LEX_PRINT_POP, 43644d4804dSStefan Eßer 43744d4804dSStefan Eßer /// Parameterized quit command. 438252884aeSStefan Eßer BC_LEX_NQUIT, 43944d4804dSStefan Eßer 44044d4804dSStefan Eßer /// Execution stack depth command. 44144d4804dSStefan Eßer BC_LEX_EXEC_STACK_LENGTH, 44244d4804dSStefan Eßer 44344d4804dSStefan Eßer /// Scale of number command. This is needed specifically for dc because bc 44444d4804dSStefan Eßer /// parses the scale function in parts. 445252884aeSStefan Eßer BC_LEX_SCALE_FACTOR, 44644d4804dSStefan Eßer 44744d4804dSStefan Eßer /// Array length command. This is needed specifically for dc because bc 44844d4804dSStefan Eßer /// just reuses its length keyword. 44944d4804dSStefan Eßer BC_LEX_ARRAY_LENGTH, 45044d4804dSStefan Eßer 451252884aeSStefan Eßer #endif // DC_ENABLED 452252884aeSStefan Eßer 453252884aeSStefan Eßer } BcLexType; 454252884aeSStefan Eßer 455252884aeSStefan Eßer struct BcLex; 456252884aeSStefan Eßer 45744d4804dSStefan Eßer /** 45844d4804dSStefan Eßer * A function pointer to call when another token is needed. Mostly called by the 45944d4804dSStefan Eßer * parser. 46044d4804dSStefan Eßer * @param l The lexer. 46144d4804dSStefan Eßer */ 46244d4804dSStefan Eßer typedef void (*BcLexNext)(struct BcLex* l); 46344d4804dSStefan Eßer 46444d4804dSStefan Eßer /// The lexer. 465*78bc019dSStefan Eßer typedef struct BcLex 466*78bc019dSStefan Eßer { 46744d4804dSStefan Eßer /// A pointer to the text to lex. 468252884aeSStefan Eßer const char* buf; 46944d4804dSStefan Eßer 47044d4804dSStefan Eßer /// The current index into buf. 471252884aeSStefan Eßer size_t i; 47244d4804dSStefan Eßer 47344d4804dSStefan Eßer /// The current line. 474252884aeSStefan Eßer size_t line; 47544d4804dSStefan Eßer 47644d4804dSStefan Eßer /// The length of buf. 477252884aeSStefan Eßer size_t len; 478252884aeSStefan Eßer 47944d4804dSStefan Eßer /// The current token. 480252884aeSStefan Eßer BcLexType t; 48144d4804dSStefan Eßer 48244d4804dSStefan Eßer /// The previous token. 483252884aeSStefan Eßer BcLexType last; 48444d4804dSStefan Eßer 48544d4804dSStefan Eßer /// A string to store extra data for tokens. For example, the @a BC_LEX_STR 48644d4804dSStefan Eßer /// token really needs to store the actual string, and numbers also need the 48744d4804dSStefan Eßer /// string. 488252884aeSStefan Eßer BcVec str; 489252884aeSStefan Eßer 49044d4804dSStefan Eßer /// If this is true, the lexer is processing stdin and can ask for more data 49144d4804dSStefan Eßer /// if a string or comment are not properly terminated. 49244d4804dSStefan Eßer bool is_stdin; 49344d4804dSStefan Eßer 49423210c9fSStefan Eßer /// If this is true, the lexer is processing expressions from the 49523210c9fSStefan Eßer /// command-line and can ask for more data if a string or comment are not 49623210c9fSStefan Eßer /// properly terminated. 49723210c9fSStefan Eßer bool is_exprs; 49823210c9fSStefan Eßer 499252884aeSStefan Eßer } BcLex; 500252884aeSStefan Eßer 50144d4804dSStefan Eßer /** 50244d4804dSStefan Eßer * Initializes a lexer. 50344d4804dSStefan Eßer * @param l The lexer to initialize. 50444d4804dSStefan Eßer */ 505*78bc019dSStefan Eßer void 506*78bc019dSStefan Eßer bc_lex_init(BcLex* l); 50744d4804dSStefan Eßer 50844d4804dSStefan Eßer /** 50944d4804dSStefan Eßer * Frees a lexer. This is not guarded by #ifndef NDEBUG because a separate 51044d4804dSStefan Eßer * parser is created at runtime to parse read() expressions and dc strings, and 51144d4804dSStefan Eßer * that parser needs a lexer. 51244d4804dSStefan Eßer * @param l The lexer to free. 51344d4804dSStefan Eßer */ 514*78bc019dSStefan Eßer void 515*78bc019dSStefan Eßer bc_lex_free(BcLex* l); 51644d4804dSStefan Eßer 51744d4804dSStefan Eßer /** 51844d4804dSStefan Eßer * Sets the filename that the lexer will be lexing. 51944d4804dSStefan Eßer * @param l The lexer. 52044d4804dSStefan Eßer * @param file The filename that the lexer will lex. 52144d4804dSStefan Eßer */ 522*78bc019dSStefan Eßer void 523*78bc019dSStefan Eßer bc_lex_file(BcLex* l, const char* file); 52444d4804dSStefan Eßer 52544d4804dSStefan Eßer /** 52644d4804dSStefan Eßer * Sets the text the lexer will lex. 52744d4804dSStefan Eßer * @param l The lexer. 52844d4804dSStefan Eßer * @param text The text to lex. 52944d4804dSStefan Eßer * @param is_stdin True if the text is from stdin, false otherwise. 53023210c9fSStefan Eßer * @param is_exprs True if the text is from command-line expressions, false 53123210c9fSStefan Eßer * otherwise. 53244d4804dSStefan Eßer */ 533*78bc019dSStefan Eßer void 534*78bc019dSStefan Eßer bc_lex_text(BcLex* l, const char* text, bool is_stdin, bool is_exprs); 53544d4804dSStefan Eßer 53644d4804dSStefan Eßer /** 53744d4804dSStefan Eßer * Generic next function for the parser to call. It takes care of calling the 53844d4804dSStefan Eßer * correct @a BcLexNext function and consuming whitespace. 53944d4804dSStefan Eßer * @param l The lexer. 54044d4804dSStefan Eßer */ 541*78bc019dSStefan Eßer void 542*78bc019dSStefan Eßer bc_lex_next(BcLex* l); 543252884aeSStefan Eßer 54444d4804dSStefan Eßer /** 54544d4804dSStefan Eßer * Lexes a line comment (one beginning with '#' and going to a newline). 54644d4804dSStefan Eßer * @param l The lexer. 54744d4804dSStefan Eßer */ 548*78bc019dSStefan Eßer void 549*78bc019dSStefan Eßer bc_lex_lineComment(BcLex* l); 55044d4804dSStefan Eßer 55144d4804dSStefan Eßer /** 55244d4804dSStefan Eßer * Lexes a general comment (C-style comment). 55344d4804dSStefan Eßer * @param l The lexer. 55444d4804dSStefan Eßer */ 555*78bc019dSStefan Eßer void 556*78bc019dSStefan Eßer bc_lex_comment(BcLex* l); 55744d4804dSStefan Eßer 55844d4804dSStefan Eßer /** 55944d4804dSStefan Eßer * Lexes whitespace, finding as much as possible. 56044d4804dSStefan Eßer * @param l The lexer. 56144d4804dSStefan Eßer */ 562*78bc019dSStefan Eßer void 563*78bc019dSStefan Eßer bc_lex_whitespace(BcLex* l); 56444d4804dSStefan Eßer 56544d4804dSStefan Eßer /** 56644d4804dSStefan Eßer * Lexes a number that begins with char @a start. This takes care of parsing 56744d4804dSStefan Eßer * numbers in scientific and engineering notations. 56844d4804dSStefan Eßer * @param l The lexer. 56944d4804dSStefan Eßer * @param start The starting char of the number. To detect a number and call 57044d4804dSStefan Eßer * this function, the lexer had to eat the first char. It fixes 57144d4804dSStefan Eßer * that by passing it in. 57244d4804dSStefan Eßer */ 573*78bc019dSStefan Eßer void 574*78bc019dSStefan Eßer bc_lex_number(BcLex* l, char start); 57544d4804dSStefan Eßer 57644d4804dSStefan Eßer /** 57744d4804dSStefan Eßer * Lexes a name/identifier. 57844d4804dSStefan Eßer * @param l The lexer. 57944d4804dSStefan Eßer */ 580*78bc019dSStefan Eßer void 581*78bc019dSStefan Eßer bc_lex_name(BcLex* l); 58244d4804dSStefan Eßer 58344d4804dSStefan Eßer /** 58444d4804dSStefan Eßer * Lexes common whitespace characters. 58544d4804dSStefan Eßer * @param l The lexer. 58644d4804dSStefan Eßer * @param c The character to lex. 58744d4804dSStefan Eßer */ 588*78bc019dSStefan Eßer void 589*78bc019dSStefan Eßer bc_lex_commonTokens(BcLex* l, char c); 590252884aeSStefan Eßer 59144d4804dSStefan Eßer /** 59244d4804dSStefan Eßer * Throws a parse error because char @a c was invalid. 59344d4804dSStefan Eßer * @param l The lexer. 59444d4804dSStefan Eßer * @param c The problem character. 59544d4804dSStefan Eßer */ 596*78bc019dSStefan Eßer void 597*78bc019dSStefan Eßer bc_lex_invalidChar(BcLex* l, char c); 598252884aeSStefan Eßer 59944d4804dSStefan Eßer /** 60044d4804dSStefan Eßer * Reads a line from stdin and puts it into the lexer's buffer. 60144d4804dSStefan Eßer * @param l The lexer. 60244d4804dSStefan Eßer */ 603*78bc019dSStefan Eßer bool 604*78bc019dSStefan Eßer bc_lex_readLine(BcLex* l); 60544d4804dSStefan Eßer 606252884aeSStefan Eßer #endif // BC_LEX_H 607