├── LICENSE ├── Lemon ├── lemon.c ├── lempar.c └── parse.y ├── MyBase.vs2017.sln ├── MyBase ├── MyBase.aps ├── MyBase.rc ├── MyBase.vcxproj ├── MyBase.vcxproj.filters ├── MyBase.vcxproj.user ├── arena.cpp ├── arena.h ├── condition.cpp ├── condition.h ├── dbval.h ├── error_code.cpp ├── error_code.h ├── log.h ├── mybase.cpp ├── mybase.ico ├── page.h ├── parse.cpp ├── parse.h ├── query.cpp ├── query.h ├── resource.h ├── result_field.h ├── sql_parser.cpp ├── sql_parser.h ├── sql_part.cpp ├── sql_part.h ├── sql_tokenize.cpp ├── sql_tokenize.h ├── string_tool.cpp ├── string_tool.h ├── table.cpp ├── table.h ├── table_set.cpp └── table_set.h ├── README.md ├── doc └── mybase_user_manual.pdf └── test └── scoreinfo.sql /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Lemon/lempar.c: -------------------------------------------------------------------------------- 1 | /* Driver template for the LEMON parser generator. 2 | ** The author disclaims copyright to this source code. 3 | */ 4 | /* First off, code is include which follows the "include" declaration 5 | ** in the input file. */ 6 | #include 7 | %% 8 | /* Next is all token values, in a form suitable for use by makeheaders. 9 | ** This section will be null unless lemon is run with the -m switch. 10 | */ 11 | /* 12 | ** These constants (all generated automatically by the parser generator) 13 | ** specify the various kinds of tokens (terminals) that the parser 14 | ** understands. 15 | ** 16 | ** Each symbol here is a terminal symbol in the grammar. 17 | */ 18 | %% 19 | /* Make sure the INTERFACE macro is defined. 20 | */ 21 | #ifndef INTERFACE 22 | # define INTERFACE 1 23 | #endif 24 | /* The next thing included is series of defines which control 25 | ** various aspects of the generated parser. 26 | ** YYCODETYPE is the data type used for storing terminal 27 | ** and nonterminal numbers. "unsigned char" is 28 | ** used if there are fewer than 250 terminals 29 | ** and nonterminals. "int" is used otherwise. 30 | ** YYNOCODE is a number of type YYCODETYPE which corresponds 31 | ** to no legal terminal or nonterminal number. This 32 | ** number is used to fill in empty slots of the hash 33 | ** table. 34 | ** YYFALLBACK If defined, this indicates that one or more tokens 35 | ** have fall-back values which should be used if the 36 | ** original value of the token will not parse. 37 | ** YYACTIONTYPE is the data type used for storing terminal 38 | ** and nonterminal numbers. "unsigned char" is 39 | ** used if there are fewer than 250 rules and 40 | ** states combined. "int" is used otherwise. 41 | ** ParseTOKENTYPE is the data type used for minor tokens given 42 | ** directly to the parser from the tokenizer. 43 | ** YYMINORTYPE is the data type used for all minor tokens. 44 | ** This is typically a union of many types, one of 45 | ** which is ParseTOKENTYPE. The entry in the union 46 | ** for base tokens is called "yy0". 47 | ** YYSTACKDEPTH is the maximum depth of the parser's stack. 48 | ** ParseARG_SDECL A static variable declaration for the %extra_argument 49 | ** ParseARG_PDECL A parameter declaration for the %extra_argument 50 | ** ParseARG_STORE Code to store %extra_argument into yypParser 51 | ** ParseARG_FETCH Code to extract %extra_argument from yypParser 52 | ** YYNSTATE the combined number of states. 53 | ** YYNRULE the number of rules in the grammar 54 | ** YYERRORSYMBOL is the code number of the error symbol. If not 55 | ** defined, then do no error processing. 56 | */ 57 | %% 58 | #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) 59 | #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) 60 | #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) 61 | 62 | /* Next are that tables used to determine what action to take based on the 63 | ** current state and lookahead token. These tables are used to implement 64 | ** functions that take a state number and lookahead value and return an 65 | ** action integer. 66 | ** 67 | ** Suppose the action integer is N. Then the action is determined as 68 | ** follows 69 | ** 70 | ** 0 <= N < YYNSTATE Shift N. That is, push the lookahead 71 | ** token onto the stack and goto state N. 72 | ** 73 | ** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. 74 | ** 75 | ** N == YYNSTATE+YYNRULE A syntax error has occurred. 76 | ** 77 | ** N == YYNSTATE+YYNRULE+1 The parser accepts its input. 78 | ** 79 | ** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused 80 | ** slots in the yy_action[] table. 81 | ** 82 | ** The action table is constructed as a single large table named yy_action[]. 83 | ** Given state S and lookahead X, the action is computed as 84 | ** 85 | ** yy_action[ yy_shift_ofst[S] + X ] 86 | ** 87 | ** If the index value yy_shift_ofst[S]+X is out of range or if the value 88 | ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] 89 | ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table 90 | ** and that yy_default[S] should be used instead. 91 | ** 92 | ** The formula above is for computing the action when the lookahead is 93 | ** a terminal symbol. If the lookahead is a non-terminal (as occurs after 94 | ** a reduce action) then the yy_reduce_ofst[] array is used in place of 95 | ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of 96 | ** YY_SHIFT_USE_DFLT. 97 | ** 98 | ** The following are the tables generated in this section: 99 | ** 100 | ** yy_action[] A single table containing all actions. 101 | ** yy_lookahead[] A table containing the lookahead for each entry in 102 | ** yy_action. Used to detect hash collisions. 103 | ** yy_shift_ofst[] For each state, the offset into yy_action for 104 | ** shifting terminals. 105 | ** yy_reduce_ofst[] For each state, the offset into yy_action for 106 | ** shifting non-terminals after a reduce. 107 | ** yy_default[] Default action for each state. 108 | */ 109 | %% 110 | #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) 111 | 112 | /* The next table maps tokens into fallback tokens. If a construct 113 | ** like the following: 114 | ** 115 | ** %fallback ID X Y Z. 116 | ** 117 | ** appears in the grammer, then ID becomes a fallback token for X, Y, 118 | ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser 119 | ** but it does not parse, the type of the token is changed to ID and 120 | ** the parse is retried before an error is thrown. 121 | */ 122 | #ifdef YYFALLBACK 123 | static const YYCODETYPE yyFallback[] = { 124 | %% 125 | }; 126 | #endif /* YYFALLBACK */ 127 | 128 | /* The following structure represents a single element of the 129 | ** parser's stack. Information stored includes: 130 | ** 131 | ** + The state number for the parser at this level of the stack. 132 | ** 133 | ** + The value of the token stored at this level of the stack. 134 | ** (In other words, the "major" token.) 135 | ** 136 | ** + The semantic value stored at this level of the stack. This is 137 | ** the information used by the action routines in the grammar. 138 | ** It is sometimes called the "minor" token. 139 | */ 140 | struct yyStackEntry { 141 | int stateno; /* The state-number */ 142 | int major; /* The major token value. This is the code 143 | ** number for the token at this stack level */ 144 | YYMINORTYPE minor; /* The user-supplied minor token value. This 145 | ** is the value of the token */ 146 | }; 147 | typedef struct yyStackEntry yyStackEntry; 148 | 149 | /* The state of the parser is completely contained in an instance of 150 | ** the following structure */ 151 | struct yyParser { 152 | int yyidx; /* Index of top element in stack */ 153 | int yyerrcnt; /* Shifts left before out of the error */ 154 | ParseARG_SDECL /* A place to hold %extra_argument */ 155 | yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ 156 | }; 157 | typedef struct yyParser yyParser; 158 | 159 | #ifndef NDEBUG 160 | #include 161 | static FILE *yyTraceFILE = 0; 162 | static char *yyTracePrompt = 0; 163 | #endif /* NDEBUG */ 164 | 165 | #ifndef NDEBUG 166 | /* 167 | ** Turn parser tracing on by giving a stream to which to write the trace 168 | ** and a prompt to preface each trace message. Tracing is turned off 169 | ** by making either argument NULL 170 | ** 171 | ** Inputs: 172 | **
    173 | **
  • A FILE* to which trace output should be written. 174 | ** If NULL, then tracing is turned off. 175 | **
  • A prefix string written at the beginning of every 176 | ** line of trace output. If NULL, then tracing is 177 | ** turned off. 178 | **
179 | ** 180 | ** Outputs: 181 | ** None. 182 | */ 183 | void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ 184 | yyTraceFILE = TraceFILE; 185 | yyTracePrompt = zTracePrompt; 186 | if( yyTraceFILE==0 ) yyTracePrompt = 0; 187 | else if( yyTracePrompt==0 ) yyTraceFILE = 0; 188 | } 189 | #endif /* NDEBUG */ 190 | 191 | #ifndef NDEBUG 192 | /* For tracing shifts, the names of all terminals and nonterminals 193 | ** are required. The following table supplies these names */ 194 | static const char *yyTokenName[] = { 195 | %% 196 | }; 197 | #endif /* NDEBUG */ 198 | 199 | #ifndef NDEBUG 200 | /* For tracing reduce actions, the names of all rules are required. 201 | */ 202 | static const char *yyRuleName[] = { 203 | %% 204 | }; 205 | #endif /* NDEBUG */ 206 | 207 | /* 208 | ** This function returns the symbolic name associated with a token 209 | ** value. 210 | */ 211 | const char *ParseTokenName(int tokenType){ 212 | #ifndef NDEBUG 213 | if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ 214 | return yyTokenName[tokenType]; 215 | }else{ 216 | return "Unknown"; 217 | } 218 | #else 219 | return ""; 220 | #endif 221 | } 222 | 223 | /* 224 | ** This function allocates a new parser. 225 | ** The only argument is a pointer to a function which works like 226 | ** malloc. 227 | ** 228 | ** Inputs: 229 | ** A pointer to the function used to allocate memory. 230 | ** 231 | ** Outputs: 232 | ** A pointer to a parser. This pointer is used in subsequent calls 233 | ** to Parse and ParseFree. 234 | */ 235 | void *ParseAlloc(void *(*mallocProc)(size_t)){ 236 | yyParser *pParser; 237 | pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); 238 | if( pParser ){ 239 | pParser->yyidx = -1; 240 | } 241 | return pParser; 242 | } 243 | 244 | /* The following function deletes the value associated with a 245 | ** symbol. The symbol can be either a terminal or nonterminal. 246 | ** "yymajor" is the symbol code, and "yypminor" is a pointer to 247 | ** the value. 248 | */ 249 | static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ 250 | switch( yymajor ){ 251 | /* Here is inserted the actions which take place when a 252 | ** terminal or non-terminal is destroyed. This can happen 253 | ** when the symbol is popped from the stack during a 254 | ** reduce or during error processing or when a parser is 255 | ** being destroyed before it is finished parsing. 256 | ** 257 | ** Note: during a reduce, the only symbols destroyed are those 258 | ** which appear on the RHS of the rule, but which are not used 259 | ** inside the C code. 260 | */ 261 | %% 262 | default: break; /* If no destructor action specified: do nothing */ 263 | } 264 | } 265 | 266 | /* 267 | ** Pop the parser's stack once. 268 | ** 269 | ** If there is a destructor routine associated with the token which 270 | ** is popped from the stack, then call it. 271 | ** 272 | ** Return the major token number for the symbol popped. 273 | */ 274 | static int yy_pop_parser_stack(yyParser *pParser){ 275 | YYCODETYPE yymajor; 276 | yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; 277 | 278 | if( pParser->yyidx<0 ) return 0; 279 | #ifndef NDEBUG 280 | if( yyTraceFILE && pParser->yyidx>=0 ){ 281 | fprintf(yyTraceFILE,"%sPopping %s\n", 282 | yyTracePrompt, 283 | yyTokenName[yytos->major]); 284 | } 285 | #endif 286 | yymajor = yytos->major; 287 | yy_destructor( yymajor, &yytos->minor); 288 | pParser->yyidx--; 289 | return yymajor; 290 | } 291 | 292 | /* 293 | ** Deallocate and destroy a parser. Destructors are all called for 294 | ** all stack elements before shutting the parser down. 295 | ** 296 | ** Inputs: 297 | **
    298 | **
  • A pointer to the parser. This should be a pointer 299 | ** obtained from ParseAlloc. 300 | **
  • A pointer to a function used to reclaim memory obtained 301 | ** from malloc. 302 | **
303 | */ 304 | void ParseFree( 305 | void *p, /* The parser to be deleted */ 306 | void (*freeProc)(void*) /* Function used to reclaim memory */ 307 | ){ 308 | yyParser *pParser = (yyParser*)p; 309 | if( pParser==0 ) return; 310 | while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); 311 | (*freeProc)((void*)pParser); 312 | } 313 | 314 | /* 315 | ** Find the appropriate action for a parser given the terminal 316 | ** look-ahead token iLookAhead. 317 | ** 318 | ** If the look-ahead token is YYNOCODE, then check to see if the action is 319 | ** independent of the look-ahead. If it is, return the action, otherwise 320 | ** return YY_NO_ACTION. 321 | */ 322 | static int yy_find_shift_action( 323 | yyParser *pParser, /* The parser */ 324 | int iLookAhead /* The look-ahead token */ 325 | ){ 326 | int i; 327 | int stateno = pParser->yystack[pParser->yyidx].stateno; 328 | 329 | /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ 330 | i = yy_shift_ofst[stateno]; 331 | if( i==YY_SHIFT_USE_DFLT ){ 332 | return yy_default[stateno]; 333 | } 334 | if( iLookAhead==YYNOCODE ){ 335 | return YY_NO_ACTION; 336 | } 337 | i += iLookAhead; 338 | if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ 339 | #ifdef YYFALLBACK 340 | int iFallback; /* Fallback token */ 341 | if( iLookAhead %s\n", 346 | yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); 347 | } 348 | #endif 349 | return yy_find_shift_action(pParser, iFallback); 350 | } 351 | #endif 352 | return yy_default[stateno]; 353 | }else{ 354 | return yy_action[i]; 355 | } 356 | } 357 | 358 | /* 359 | ** Find the appropriate action for a parser given the non-terminal 360 | ** look-ahead token iLookAhead. 361 | ** 362 | ** If the look-ahead token is YYNOCODE, then check to see if the action is 363 | ** independent of the look-ahead. If it is, return the action, otherwise 364 | ** return YY_NO_ACTION. 365 | */ 366 | static int yy_find_reduce_action( 367 | yyParser *pParser, /* The parser */ 368 | int iLookAhead /* The look-ahead token */ 369 | ){ 370 | int i; 371 | int stateno = pParser->yystack[pParser->yyidx].stateno; 372 | 373 | i = yy_reduce_ofst[stateno]; 374 | if( i==YY_REDUCE_USE_DFLT ){ 375 | return yy_default[stateno]; 376 | } 377 | if( iLookAhead==YYNOCODE ){ 378 | return YY_NO_ACTION; 379 | } 380 | i += iLookAhead; 381 | if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ 382 | return yy_default[stateno]; 383 | }else{ 384 | return yy_action[i]; 385 | } 386 | } 387 | 388 | /* 389 | ** Perform a shift action. 390 | */ 391 | static void yy_shift( 392 | yyParser *yypParser, /* The parser to be shifted */ 393 | int yyNewState, /* The new state to shift in */ 394 | int yyMajor, /* The major token to shift in */ 395 | YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ 396 | ){ 397 | yyStackEntry *yytos; 398 | yypParser->yyidx++; 399 | if( yypParser->yyidx>=YYSTACKDEPTH ){ 400 | ParseARG_FETCH; 401 | yypParser->yyidx--; 402 | #ifndef NDEBUG 403 | if( yyTraceFILE ){ 404 | fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); 405 | } 406 | #endif 407 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 408 | /* Here code is inserted which will execute if the parser 409 | ** stack every overflows */ 410 | %% 411 | ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ 412 | return; 413 | } 414 | yytos = &yypParser->yystack[yypParser->yyidx]; 415 | yytos->stateno = yyNewState; 416 | yytos->major = yyMajor; 417 | yytos->minor = *yypMinor; 418 | #ifndef NDEBUG 419 | if( yyTraceFILE && yypParser->yyidx>0 ){ 420 | int i; 421 | fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); 422 | fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); 423 | for(i=1; i<=yypParser->yyidx; i++) 424 | fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); 425 | fprintf(yyTraceFILE,"\n"); 426 | } 427 | #endif 428 | } 429 | 430 | /* The following table contains information about every rule that 431 | ** is used during the reduce. 432 | */ 433 | static struct { 434 | YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ 435 | unsigned char nrhs; /* Number of right-hand side symbols in the rule */ 436 | } yyRuleInfo[] = { 437 | %% 438 | }; 439 | 440 | static void yy_accept(yyParser*); /* Forward Declaration */ 441 | 442 | /* 443 | ** Perform a reduce action and the shift that must immediately 444 | ** follow the reduce. 445 | */ 446 | static void yy_reduce( 447 | yyParser *yypParser, /* The parser */ 448 | int yyruleno /* Number of the rule by which to reduce */ 449 | ){ 450 | int yygoto; /* The next state */ 451 | int yyact; /* The next action */ 452 | YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ 453 | yyStackEntry *yymsp; /* The top of the parser's stack */ 454 | int yysize; /* Amount to pop the stack */ 455 | ParseARG_FETCH; 456 | yymsp = &yypParser->yystack[yypParser->yyidx]; 457 | #ifndef NDEBUG 458 | if( yyTraceFILE && yyruleno>=0 459 | && yyruleno 470 | ** { ... } // User supplied code 471 | ** #line 472 | ** break; 473 | */ 474 | %% 475 | }; 476 | yygoto = yyRuleInfo[yyruleno].lhs; 477 | yysize = yyRuleInfo[yyruleno].nrhs; 478 | yypParser->yyidx -= yysize; 479 | yyact = yy_find_reduce_action(yypParser,yygoto); 480 | if( yyact < YYNSTATE ){ 481 | yy_shift(yypParser,yyact,yygoto,&yygotominor); 482 | }else if( yyact == YYNSTATE + YYNRULE + 1 ){ 483 | yy_accept(yypParser); 484 | } 485 | } 486 | 487 | /* 488 | ** The following code executes when the parse fails 489 | */ 490 | static void yy_parse_failed( 491 | yyParser *yypParser /* The parser */ 492 | ){ 493 | ParseARG_FETCH; 494 | #ifndef NDEBUG 495 | if( yyTraceFILE ){ 496 | fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); 497 | } 498 | #endif 499 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 500 | /* Here code is inserted which will be executed whenever the 501 | ** parser fails */ 502 | %% 503 | ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 504 | } 505 | 506 | /* 507 | ** The following code executes when a syntax error first occurs. 508 | */ 509 | static void yy_syntax_error( 510 | yyParser *yypParser, /* The parser */ 511 | int yymajor, /* The major type of the error token */ 512 | YYMINORTYPE yyminor /* The minor type of the error token */ 513 | ){ 514 | ParseARG_FETCH; 515 | #define TOKEN (yyminor.yy0) 516 | %% 517 | ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 518 | } 519 | 520 | /* 521 | ** The following is executed when the parser accepts 522 | */ 523 | static void yy_accept( 524 | yyParser *yypParser /* The parser */ 525 | ){ 526 | ParseARG_FETCH; 527 | #ifndef NDEBUG 528 | if( yyTraceFILE ){ 529 | fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); 530 | } 531 | #endif 532 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 533 | /* Here code is inserted which will be executed whenever the 534 | ** parser accepts */ 535 | %% 536 | ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 537 | } 538 | 539 | /* The main parser program. 540 | ** The first argument is a pointer to a structure obtained from 541 | ** "ParseAlloc" which describes the current state of the parser. 542 | ** The second argument is the major token number. The third is 543 | ** the minor token. The fourth optional argument is whatever the 544 | ** user wants (and specified in the grammar) and is available for 545 | ** use by the action routines. 546 | ** 547 | ** Inputs: 548 | **
    549 | **
  • A pointer to the parser (an opaque structure.) 550 | **
  • The major token number. 551 | **
  • The minor token number. 552 | **
  • An option argument of a grammar-specified type. 553 | **
554 | ** 555 | ** Outputs: 556 | ** None. 557 | */ 558 | void Parse( 559 | void *yyp, /* The parser */ 560 | int yymajor, /* The major token code number */ 561 | ParseTOKENTYPE yyminor /* The value for the token */ 562 | ParseARG_PDECL /* Optional %extra_argument parameter */ 563 | ){ 564 | YYMINORTYPE yyminorunion; 565 | int yyact; /* The parser action. */ 566 | int yyendofinput; /* True if we are at the end of input */ 567 | int yyerrorhit = 0; /* True if yymajor has invoked an error */ 568 | yyParser *yypParser; /* The parser */ 569 | 570 | /* (re)initialize the parser, if necessary */ 571 | yypParser = (yyParser*)yyp; 572 | if( yypParser->yyidx<0 ){ 573 | if( yymajor==0 ) return; 574 | yypParser->yyidx = 0; 575 | yypParser->yyerrcnt = -1; 576 | yypParser->yystack[0].stateno = 0; 577 | yypParser->yystack[0].major = 0; 578 | } 579 | yyminorunion.yy0 = yyminor; 580 | yyendofinput = (yymajor==0); 581 | ParseARG_STORE; 582 | 583 | #ifndef NDEBUG 584 | if( yyTraceFILE ){ 585 | fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); 586 | } 587 | #endif 588 | 589 | do{ 590 | yyact = yy_find_shift_action(yypParser,yymajor); 591 | if( yyactyyerrcnt--; 594 | if( yyendofinput && yypParser->yyidx>=0 ){ 595 | yymajor = 0; 596 | }else{ 597 | yymajor = YYNOCODE; 598 | } 599 | }else if( yyact < YYNSTATE + YYNRULE ){ 600 | yy_reduce(yypParser,yyact-YYNSTATE); 601 | }else if( yyact == YY_ERROR_ACTION ){ 602 | int yymx; 603 | #ifndef NDEBUG 604 | if( yyTraceFILE ){ 605 | fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); 606 | } 607 | #endif 608 | #ifdef YYERRORSYMBOL 609 | /* A syntax error has occurred. 610 | ** The response to an error depends upon whether or not the 611 | ** grammar defines an error token "ERROR". 612 | ** 613 | ** This is what we do if the grammar does define ERROR: 614 | ** 615 | ** * Call the %syntax_error function. 616 | ** 617 | ** * Begin popping the stack until we enter a state where 618 | ** it is legal to shift the error symbol, then shift 619 | ** the error symbol. 620 | ** 621 | ** * Set the error count to three. 622 | ** 623 | ** * Begin accepting and shifting new tokens. No new error 624 | ** processing will occur until three tokens have been 625 | ** shifted successfully. 626 | ** 627 | */ 628 | if( yypParser->yyerrcnt<0 ){ 629 | yy_syntax_error(yypParser,yymajor,yyminorunion); 630 | } 631 | yymx = yypParser->yystack[yypParser->yyidx].major; 632 | if( yymx==YYERRORSYMBOL || yyerrorhit ){ 633 | #ifndef NDEBUG 634 | if( yyTraceFILE ){ 635 | fprintf(yyTraceFILE,"%sDiscard input token %s\n", 636 | yyTracePrompt,yyTokenName[yymajor]); 637 | } 638 | #endif 639 | yy_destructor(yymajor,&yyminorunion); 640 | yymajor = YYNOCODE; 641 | }else{ 642 | while( 643 | yypParser->yyidx >= 0 && 644 | yymx != YYERRORSYMBOL && 645 | (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE 646 | ){ 647 | yy_pop_parser_stack(yypParser); 648 | } 649 | if( yypParser->yyidx < 0 || yymajor==0 ){ 650 | yy_destructor(yymajor,&yyminorunion); 651 | yy_parse_failed(yypParser); 652 | yymajor = YYNOCODE; 653 | }else if( yymx!=YYERRORSYMBOL ){ 654 | YYMINORTYPE u2; 655 | u2.YYERRSYMDT = 0; 656 | yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); 657 | } 658 | } 659 | yypParser->yyerrcnt = 3; 660 | yyerrorhit = 1; 661 | #else /* YYERRORSYMBOL is not defined */ 662 | /* This is what we do if the grammar does not define ERROR: 663 | ** 664 | ** * Report an error message, and throw away the input token. 665 | ** 666 | ** * If the input token is $, then fail the parse. 667 | ** 668 | ** As before, subsequent error messages are suppressed until 669 | ** three input tokens have been successfully shifted. 670 | */ 671 | if( yypParser->yyerrcnt<=0 ){ 672 | yy_syntax_error(yypParser,yymajor,yyminorunion); 673 | } 674 | yypParser->yyerrcnt = 3; 675 | yy_destructor(yymajor,&yyminorunion); 676 | if( yyendofinput ){ 677 | yy_parse_failed(yypParser); 678 | } 679 | yymajor = YYNOCODE; 680 | #endif 681 | }else{ 682 | yy_accept(yypParser); 683 | yymajor = YYNOCODE; 684 | } 685 | }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); 686 | return; 687 | } 688 | -------------------------------------------------------------------------------- /Lemon/parse.y: -------------------------------------------------------------------------------- 1 | %include { 2 | #include "parse.h" 3 | #include "dbval.h" 4 | #include "sql_part.h" 5 | #include "sql_parser.h" 6 | } 7 | 8 | %token_prefix TK_ 9 | %token_type {Token} 10 | %default_type {Token} 11 | %extra_argument {SQLParser *pParse} 12 | %syntax_error { 13 | pParse->SetError(TOKEN.pos_); 14 | } 15 | %name mydbParse 16 | 17 | %nonassoc FUNC ILLEGAL SPACE COMMENT. 18 | 19 | //////////////////// SHOW TABLES //////////////////////////////////// 20 | cmd ::= SHOW TABLES SEMI. { 21 | pParse->SetShowTables(); 22 | } 23 | 24 | cmd ::= SHOW COLUMNS FROM ID(X) SEMI. { 25 | pParse->SetShowTableColumns(&X); 26 | } 27 | 28 | //////////////////// DROP TABLE ///////////////////////////////// 29 | cmd ::= DROP TABLE ID(X) SEMI. { 30 | pParse->SetDropTable(&X); 31 | } 32 | 33 | /////////////////// CREATE Command ////////////////////////////// 34 | 35 | cmd ::= CREATE TABLE ID(T) LP col_list(C) RP SEMI. { 36 | pParse->SetCreateTable(&T, C); 37 | } 38 | 39 | %type col_item { ColumnItem* } 40 | %destructor col_item { delete ($$); } 41 | %type col_list { ColumnList* } 42 | %destructor col_list { delete ($$); } 43 | 44 | col_item(A) ::= ID(X) INT_TYPE. { A = new ColumnItem(&X, VALUE_TYPE::VAL_INT); } 45 | col_item(A) ::= ID(X) DOUBLE_TYPE. { A = new ColumnItem(&X, VALUE_TYPE::VAL_DOUBLE); } 46 | col_item(A) ::= ID(X) STRING_TYPE. { A = new ColumnItem(&X, VALUE_TYPE::VAL_STRING); } 47 | col_list(A) ::= col_item(X). { 48 | A = sqlAppendColumn(nullptr, X); 49 | } 50 | col_list(A) ::= col_list(X) COMMA col_item(Y). { 51 | A = sqlAppendColumn(X, Y); 52 | } 53 | 54 | 55 | //////////////////// DELETE Command ///////////////////////////// 56 | cmd ::= DELETE FROM ID(T) where_opt(W) SEMI. { 57 | pParse->SetDelete(&T, W); 58 | } 59 | 60 | //////////////////// INSERT Command //////////////////////////// 61 | 62 | cmd ::= INSERT INTO ID(T) LP name_list(N) RP VALUES LP val_list(V) RP SEMI. { 63 | pParse->SetInsert(&T, N, V); 64 | } 65 | 66 | %type name_list { ExprList* } 67 | %destructor name_list { delete ($$); } 68 | 69 | name_list(A) ::= ID(N). { 70 | A = new ExprList(); 71 | A->AddExprItem(new ExprItem(TK_ID, &N)); 72 | } 73 | name_list(A) ::= name_list(P) COMMA ID(N). { 74 | A = P->AddExprItem(new ExprItem(TK_ID, &N)); 75 | } 76 | 77 | %type val_list { ExprList* } 78 | %destructor val_list { delete ($$); } 79 | 80 | val_list(A) ::= val_item(V). { 81 | A = new ExprList(); 82 | A->AddExprItem(V); 83 | } 84 | val_list(A) ::= val_list(P) COMMA val_item(V). { 85 | A = P->AddExprItem(V); 86 | } 87 | 88 | /////////////////// Query ////////////////////////////////////// 89 | cmd ::= SELECT target_list(S) from(T) where_opt(W) groupby_opt(G) limit_opt(L) SEMI. 90 | { 91 | pParse->SetQuery(S, &T, W, G, L); 92 | } 93 | 94 | %type target_list { ExprList* } 95 | %destructor target_list { delete ($$); } 96 | %type target_item { ExprItem* } 97 | %destructor target_item { delete ($$); } 98 | 99 | target_item(A) ::= STAR(S). { A = new ExprItem(TK_STAR, &S); } 100 | target_item(A) ::= ID(X). { A = new ExprItem(TK_ID, &X); } 101 | target_item(A) ::= ID(X) LP arg_list(L) RP. { A = new ExprItem(TK_FUNC, &X, L); } 102 | 103 | target_list(A) ::= target_item(X). { 104 | A = new ExprList(); 105 | A->AddExprItem(X); 106 | } 107 | target_list(A) ::= target_list(P) COMMA target_item(X). { 108 | A = P->AddExprItem(X); 109 | } 110 | 111 | %type arg_item { ExprItem* } 112 | %destructor arg_item { delete ($$); } 113 | %type arg_list { ExprList* } 114 | %destructor arg_list { delete ($$); } 115 | 116 | arg_item(A) ::= ID(X). { A = new ExprItem(TK_ID, &X); } 117 | arg_item(A) ::= STAR(X). { A = new ExprItem(TK_STAR, &X); } 118 | 119 | arg_list(A) ::= arg_item(I). { 120 | A = new ExprList(); 121 | A->AddExprItem(I); 122 | } 123 | arg_list(A) ::= arg_list(P) COMMA arg_item(I). { 124 | A = P->AddExprItem(I); 125 | } 126 | 127 | %type from {Token} 128 | from(A) ::= FROM ID(X). {A = X;} 129 | 130 | %type where_opt { ExprItem* } 131 | %destructor where_opt { delete ($$); } 132 | 133 | where_opt(A) ::= . { A = nullptr; } 134 | where_opt(A) ::= WHERE condi_expr(X). { A = X; } 135 | 136 | %type groupby_opt { GroupOpt* } 137 | %destructor groupby_opt { delete ($$); } 138 | 139 | groupby_opt(A) ::= . { A = nullptr; } 140 | groupby_opt(A) ::= GROUP BY ID(X). { A = new GroupOpt(&X); } 141 | 142 | %type limit_opt { LimitOpt* } 143 | %destructor limit_opt { delete ($$); } 144 | 145 | limit_opt(A) ::= . { A = nullptr; } 146 | limit_opt(A) ::= LIMIT INTEGER(Y). { A = new LimitOpt(&Y); } 147 | limit_opt(A) ::= LIMIT INTEGER(X) COMMA INTEGER(Y). { A = new LimitOpt(&X, &Y); } 148 | 149 | %left AND. 150 | %left EQ NE. 151 | %left GT GE LT LE. 152 | 153 | /////////////////////////////////// Condition Expression //////////// 154 | 155 | %type condi_expr { ExprItem* } 156 | %destructor condi_expr { delete ($$); } 157 | 158 | condi_expr(A) ::= ID(X) LT val_item(Y). { A = new ExprItem(TK_LT, new ExprItem(TK_ID, &X), Y); } 159 | condi_expr(A) ::= ID(X) LE val_item(Y). { A = new ExprItem(TK_LE, new ExprItem(TK_ID, &X), Y); } 160 | condi_expr(A) ::= ID(X) GT val_item(Y). { A = new ExprItem(TK_GT, new ExprItem(TK_ID, &X), Y); } 161 | condi_expr(A) ::= ID(X) GE val_item(Y). { A = new ExprItem(TK_GE, new ExprItem(TK_ID, &X), Y); } 162 | condi_expr(A) ::= ID(X) EQ val_item(Y). { A = new ExprItem(TK_EQ, new ExprItem(TK_ID, &X), Y); } 163 | condi_expr(A) ::= ID(X) NE val_item(Y). { A = new ExprItem(TK_NE, new ExprItem(TK_ID, &X), Y); } 164 | condi_expr(A) ::= ID(X) LIKE val_item(Y). { A = new ExprItem(TK_LIKE, new ExprItem(TK_ID, &X), Y); } 165 | condi_expr(A) ::= ID(X) IS NOT NULL. [ISNOTNULL] { A = new ExprItem(TK_ISNOTNULL, new ExprItem(TK_ID, &X), nullptr); } 166 | condi_expr(A) ::= ID(X) IS NULL. [ISNULL] { A = new ExprItem(TK_ISNULL, new ExprItem(TK_ID, &X), nullptr); } 167 | 168 | condi_expr(A) ::= val_item(Y) LT ID(X). { A = new ExprItem(TK_GT, new ExprItem(TK_ID, &X), Y); } 169 | condi_expr(A) ::= val_item(Y) LE ID(X). { A = new ExprItem(TK_GE, new ExprItem(TK_ID, &X), Y); } 170 | condi_expr(A) ::= val_item(Y) GT ID(X). { A = new ExprItem(TK_LT, new ExprItem(TK_ID, &X), Y); } 171 | condi_expr(A) ::= val_item(Y) GE ID(X). { A = new ExprItem(TK_LE, new ExprItem(TK_ID, &X), Y); } 172 | condi_expr(A) ::= val_item(Y) EQ ID(X). { A = new ExprItem(TK_EQ, new ExprItem(TK_ID, &X), Y); } 173 | condi_expr(A) ::= val_item(Y) NE ID(X). { A = new ExprItem(TK_NE, new ExprItem(TK_ID, &X), Y); } 174 | 175 | condi_expr(A) ::= condi_expr(X) AND condi_expr(Y). { A = new ExprItem(TK_AND, X, Y); } 176 | 177 | %type val_item { ExprItem* } 178 | %destructor val_item { delete ($$); } 179 | 180 | val_item(A) ::= INTEGER(X). { A = new ExprItem(TK_INTEGER, &X); } 181 | val_item(A) ::= DOUBLE(X). { A = new ExprItem(TK_DOUBLE, &X); } 182 | val_item(A) ::= PLUS INTEGER(X). { A = new ExprItem(TK_INTEGER, &X); } 183 | val_item(A) ::= PLUS DOUBLE(X). { A = new ExprItem(TK_DOUBLE, &X); } 184 | val_item(A) ::= MINUS INTEGER(X). [UINTEGER] { A = new ExprItem(TK_UINTEGER, &X); } 185 | val_item(A) ::= MINUS DOUBLE(X). [UDOUBLE] { A = new ExprItem(TK_UDOUBLE, &X); } 186 | val_item(A) ::= STRING(X). { A = new ExprItem(TK_STRING, &X); } 187 | -------------------------------------------------------------------------------- /MyBase.vs2017.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.421 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyBase", "MyBase\MyBase.vcxproj", "{615851FB-97CF-4144-B0B6-D3D18F0637A9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Debug|x64.ActiveCfg = Debug|x64 17 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Debug|x64.Build.0 = Debug|x64 18 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Debug|x86.Build.0 = Debug|Win32 20 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Release|x64.ActiveCfg = Release|x64 21 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Release|x64.Build.0 = Release|x64 22 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Release|x86.ActiveCfg = Release|Win32 23 | {615851FB-97CF-4144-B0B6-D3D18F0637A9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {DA6EA45C-14ED-4D92-93F1-D3710F2DD487} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /MyBase/MyBase.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/MyBase.aps -------------------------------------------------------------------------------- /MyBase/MyBase.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/MyBase.rc -------------------------------------------------------------------------------- /MyBase/MyBase.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 15.0 61 | {615851FB-97CF-4144-B0B6-D3D18F0637A9} 62 | Win32Proj 63 | MyBase 64 | 10.0.17763.0 65 | 66 | 67 | 68 | Application 69 | true 70 | v141 71 | MultiByte 72 | 73 | 74 | Application 75 | false 76 | v141 77 | true 78 | MultiByte 79 | 80 | 81 | Application 82 | true 83 | v141 84 | MultiByte 85 | 86 | 87 | Application 88 | false 89 | v141 90 | true 91 | MultiByte 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | true 113 | 114 | 115 | true 116 | 117 | 118 | false 119 | 120 | 121 | false 122 | 123 | 124 | 125 | NotUsing 126 | Level3 127 | Disabled 128 | true 129 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | true 131 | pch.h 132 | 133 | 134 | Console 135 | true 136 | 137 | 138 | 139 | 140 | NotUsing 141 | Level3 142 | Disabled 143 | true 144 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 145 | true 146 | pch.h 147 | 148 | 149 | Console 150 | true 151 | 152 | 153 | 154 | 155 | NotUsing 156 | Level3 157 | MaxSpeed 158 | true 159 | true 160 | true 161 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 162 | true 163 | pch.h 164 | 165 | 166 | Console 167 | true 168 | true 169 | true 170 | 171 | 172 | 173 | 174 | NotUsing 175 | Level3 176 | MaxSpeed 177 | true 178 | true 179 | true 180 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 181 | true 182 | pch.h 183 | 184 | 185 | Console 186 | true 187 | true 188 | true 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /MyBase/MyBase.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 头文件 20 | 21 | 22 | 头文件 23 | 24 | 25 | 头文件 26 | 27 | 28 | 头文件 29 | 30 | 31 | 头文件 32 | 33 | 34 | 头文件 35 | 36 | 37 | 头文件 38 | 39 | 40 | 头文件 41 | 42 | 43 | 头文件 44 | 45 | 46 | 头文件 47 | 48 | 49 | 头文件 50 | 51 | 52 | 头文件 53 | 54 | 55 | 头文件 56 | 57 | 58 | 头文件 59 | 60 | 61 | 头文件 62 | 63 | 64 | 头文件 65 | 66 | 67 | 68 | 69 | 源文件 70 | 71 | 72 | 源文件 73 | 74 | 75 | 源文件 76 | 77 | 78 | 源文件 79 | 80 | 81 | 源文件 82 | 83 | 84 | 源文件 85 | 86 | 87 | 源文件 88 | 89 | 90 | 源文件 91 | 92 | 93 | 源文件 94 | 95 | 96 | 源文件 97 | 98 | 99 | 源文件 100 | 101 | 102 | 源文件 103 | 104 | 105 | 106 | 107 | 资源文件 108 | 109 | 110 | 111 | 112 | 资源文件 113 | 114 | 115 | -------------------------------------------------------------------------------- /MyBase/MyBase.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MyBase/arena.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2019 ZhangQuan 3 | ** 4 | ** This program is free software; you can redistribute it and/or 5 | ** modify it under the terms of the GNU General Public 6 | ** License as published by the Free Software Foundation; either 7 | ** version 3 of the License, or (at your option) any later version. 8 | ** 9 | ** Author contact information: 10 | ** zhangqhn@foxmail.com 11 | */ 12 | 13 | #include "arena.h" 14 | #include 15 | 16 | static const int kBlockSize = 4096; 17 | 18 | Arena::Arena() 19 | { 20 | alloc_ptr_ = nullptr; 21 | alloc_bytes_remaining_ = 0; 22 | } 23 | 24 | Arena::~Arena() 25 | { 26 | for (size_t i = 0; i < blocks_.size(); i++) { 27 | delete[] blocks_[i]; 28 | } 29 | } 30 | 31 | char* Arena::Allocate(size_t bytes) 32 | { 33 | assert(bytes > 0); 34 | if (bytes <= alloc_bytes_remaining_) { 35 | char* result = alloc_ptr_; 36 | alloc_ptr_ += bytes; 37 | alloc_bytes_remaining_ -= bytes; 38 | return result; 39 | } 40 | 41 | return AllocateFallback(bytes); 42 | } 43 | 44 | char* Arena::AllocateAligned(size_t bytes) 45 | { 46 | const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; 47 | assert((align & (align - 1)) == 0); 48 | size_t current_mod = reinterpret_cast(alloc_ptr_) & (align - 1); 49 | size_t slop = (current_mod == 0 ? 0 : (align - current_mod)); 50 | size_t needed = bytes + slop; 51 | char* result; 52 | if (needed <= alloc_bytes_remaining_) { 53 | result = alloc_ptr_ + slop; 54 | alloc_ptr_ += needed; 55 | alloc_bytes_remaining_ -= needed; 56 | } 57 | else { 58 | result = AllocateFallback(bytes); 59 | } 60 | assert((reinterpret_cast(result) & (align - 1)) == 0); 61 | return result; 62 | } 63 | 64 | char* Arena::AllocateFallback(size_t bytes) 65 | { 66 | if (bytes > (kBlockSize / 4)) 67 | { 68 | char* result = AllocateNewBlock(bytes); 69 | return result; 70 | } 71 | 72 | alloc_ptr_ = AllocateNewBlock(kBlockSize); 73 | alloc_bytes_remaining_ = kBlockSize; 74 | 75 | char* result = alloc_ptr_; 76 | alloc_ptr_ += bytes; 77 | alloc_bytes_remaining_ -= bytes; 78 | return result; 79 | } 80 | 81 | char* Arena::AllocateNewBlock(size_t block_bytes) 82 | { 83 | char* result = new char[block_bytes]; 84 | blocks_.push_back(result); 85 | return result; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /MyBase/arena.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | 16 | class Arena 17 | { 18 | public: 19 | Arena(); 20 | ~Arena(); 21 | 22 | // Return a pointer to a newly allocated memory block of "bytes" bytes. 23 | char* Allocate(size_t bytes); 24 | 25 | // Allocate memory with the normal alignment guarantees provided by malloc 26 | char* AllocateAligned(size_t bytes); 27 | 28 | private: 29 | char* AllocateFallback(size_t bytes); 30 | char* AllocateNewBlock(size_t block_bytes); 31 | 32 | // Allocation state 33 | char* alloc_ptr_; 34 | size_t alloc_bytes_remaining_; 35 | 36 | // Array of new[] allocated memory blocks 37 | std::vector blocks_; 38 | 39 | // No copying allowed 40 | Arena(const Arena&); 41 | void operator=(const Arena&); 42 | }; -------------------------------------------------------------------------------- /MyBase/condition.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2019 ZhangQuan 3 | ** 4 | ** This program is free software; you can redistribute it and/or 5 | ** modify it under the terms of the GNU General Public 6 | ** License as published by the Free Software Foundation; either 7 | ** version 3 of the License, or (at your option) any later version. 8 | ** 9 | ** Author contact information: 10 | ** zhangqhn@foxmail.com 11 | */ 12 | 13 | #include "condition.h" 14 | 15 | Condition::Condition() 16 | { 17 | 18 | } 19 | 20 | Condition::~Condition() 21 | { 22 | for (auto condiIt = condiVec_.begin(); condiIt != condiVec_.end(); condiIt++) 23 | { 24 | delete *condiIt; 25 | } 26 | } 27 | 28 | void Condition::AddCondition(ConditionItem* pItem) 29 | { 30 | if (pItem != nullptr) 31 | { 32 | condiVec_.push_back(pItem); 33 | } 34 | } 35 | 36 | bool Condition::RunCondition(const std::vector& rec) 37 | { 38 | for (auto condiIt = condiVec_.begin(); condiIt != condiVec_.end(); condiIt++) 39 | { 40 | if (!((*condiIt)->GetLogic(rec))) 41 | return false; 42 | } 43 | 44 | return true; 45 | } 46 | -------------------------------------------------------------------------------- /MyBase/condition.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/condition.h -------------------------------------------------------------------------------- /MyBase/dbval.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | 16 | enum VALUE_TYPE{ 17 | VAL_NULL = 0, 18 | VAL_INT = 1, 19 | VAL_DOUBLE = 2, 20 | VAL_STRING = 3, 21 | }; 22 | 23 | typedef struct _DBVal 24 | { 25 | int valType_; //value type , null, int, double, string 26 | int dataLen_; //data length 27 | union { 28 | int64_t intVal_; 29 | double doubleVal_; 30 | const char* strVal_; 31 | } val_; 32 | }DBVal; 33 | 34 | #define DBVAL_SET_NULL(pVal) do { \ 35 | (pVal)->valType_ = VALUE_TYPE::VAL_NULL; \ 36 | (pVal)->dataLen_ = 0; \ 37 | (pVal)->val_.intVal_ = 0; \ 38 | } while(false) 39 | 40 | #define DBVAL_SET_INT(pVal, v) do { \ 41 | (pVal)->valType_ = VALUE_TYPE::VAL_INT; \ 42 | (pVal)->dataLen_ = 8; \ 43 | (pVal)->val_.intVal_ = v; \ 44 | } while(false) 45 | 46 | #define DBVAL_SET_DOUBLE(pVal, v) do { \ 47 | (pVal)->valType_ = VALUE_TYPE::VAL_DOUBLE; \ 48 | (pVal)->dataLen_ = 8; \ 49 | (pVal)->val_.doubleVal_ = v; \ 50 | } while(false) 51 | 52 | #define DBVAL_SET_STRING(pVal, pStr, len) do { \ 53 | (pVal)->valType_ = VALUE_TYPE::VAL_STRING; \ 54 | (pVal)->dataLen_ = len; \ 55 | (pVal)->val_.strVal_ = pStr; \ 56 | } while(false) 57 | 58 | #define DBVAL_IS_NULL(pVal) ((pVal)->valType_ == VALUE_TYPE::VAL_NULL) 59 | 60 | -------------------------------------------------------------------------------- /MyBase/error_code.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/error_code.cpp -------------------------------------------------------------------------------- /MyBase/error_code.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | 15 | #define ER_OK 0 16 | #define ER_INIT_ERR 10000 17 | #define ER_INVALID_PARAM 10001 18 | #define ER_FIELD_NOT_FOUND 10002 19 | #define ER_SQL_ERR 10003 20 | #define ER_TABLE_NOT_FOUND 10004 21 | #define ER_TABLE_EXISTS 10005 22 | #define ER_NOMEM 10006 23 | #define ER_DATA_TOO_LONG 10007 24 | #define ER_TABLE_FULL 10008 25 | #define ER_HANDLE_OPEND 10009 26 | #define ER_INVALID_FIELD_NAME 10010 27 | #define ER_FILE_EXISTS 10011 28 | #define ER_IO_ERR 10012 29 | #define ER_TOO_LESS_COLUMN 10013 30 | #define ER_TOO_MANY_COLUMN 10014 31 | #define ER_TYPE_MISTAKE 10015 32 | 33 | 34 | #define ER_MIN_VAL 10000 35 | #define ER_MAX_VAL 10015 36 | 37 | const char* GetErrMsg(int errCode); -------------------------------------------------------------------------------- /MyBase/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | 16 | #define LOG_OUT(FORMAT, ...) do { printf("%s, line: %d, ", __FUNCTION__, __LINE__); printf(FORMAT, ## __VA_ARGS__); printf("\n");} while(false) -------------------------------------------------------------------------------- /MyBase/mybase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2019 ZhangQuan 3 | ** 4 | ** This program is free software; you can redistribute it and/or 5 | ** modify it under the terms of the GNU General Public 6 | ** License as published by the Free Software Foundation; either 7 | ** version 3 of the License, or (at your option) any later version. 8 | ** 9 | ** Author contact information: 10 | ** zhangqhn@foxmail.com 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "page.h" 21 | #include "table.h" 22 | #include "sql_tokenize.h" 23 | #include "sql_parser.h" 24 | #include "table_set.h" 25 | #include "error_code.h" 26 | 27 | std::string glbDataPath; 28 | const char * pVersion = "1.0"; 29 | 30 | std::string GbkToUtf8(const std::string& gbkStr); 31 | std::string Utf8ToGbk(const std::string& utf8Str); 32 | int ExecuteSql(TableSet* pTabSet, const char* pSql, int* pErrPos); 33 | void ShowHelp(); 34 | 35 | void ShowTables(TableSet* pTabSet); 36 | int ShowTableColumns(TableSet* pTabSet, const std::string& tabName); 37 | int ExecQuery(TableSet* pTabSet, const std::string& tabName, const QueryParam* pQueryParam, int* pErrPos); 38 | void SourceFile(TableSet* pTabSet, const char* pFile); 39 | 40 | int main(int argc, char* argv[]) 41 | { 42 | //将数据目录设置为应用程序所在目录 43 | glbDataPath = argv[0]; 44 | glbDataPath = glbDataPath.substr(0, glbDataPath.find_last_of('\\')); 45 | 46 | char readBuf[2048]; 47 | 48 | //初始化SQL关键字 49 | SQLTokenize::InitTokenize(); 50 | 51 | std::cout << "MyBase 版本: " << pVersion << std::endl; 52 | 53 | TableSet tabSet; 54 | if (tabSet.LoadTables() != 0) 55 | { 56 | std::cout << "加载表失败" << std::endl; 57 | system("pause"); 58 | return -1; 59 | } 60 | 61 | while (true) 62 | { 63 | std::cout << "MyBase > " << std::flush; 64 | 65 | std::cin.getline(readBuf, sizeof(readBuf)); 66 | std::string cmdStr = readBuf; 67 | size_t bgpos = cmdStr.find_first_not_of(' '); 68 | if (bgpos != std::string::npos) 69 | { 70 | size_t edpos = cmdStr.find_first_of(' ', bgpos); 71 | std::string startStr; 72 | 73 | if (edpos != std::string::npos) 74 | startStr = cmdStr.substr(bgpos, (edpos - bgpos)); 75 | else 76 | startStr = cmdStr.substr(bgpos); 77 | 78 | std::transform(startStr.begin(), startStr.end(), startStr.begin(), ::tolower); 79 | if (startStr.compare("exit") == 0 || startStr.compare("quit") == 0) 80 | break; 81 | else if (startStr.compare("clear") == 0 || startStr.compare("cls") == 0) 82 | system("cls"); 83 | else if (startStr.compare("help") == 0 || startStr.compare("?") == 0) 84 | ShowHelp(); 85 | else if (startStr.compare("source") == 0) 86 | { 87 | if (edpos == std::string::npos) 88 | { 89 | std::cout << "未指定输入文件" << std::endl; 90 | continue; 91 | } 92 | 93 | size_t fileBg = cmdStr.find_first_not_of(' ', edpos); 94 | if (fileBg == std::string::npos) 95 | { 96 | std::cout << "未指定输入文件" << std::endl; 97 | continue; 98 | } 99 | 100 | std::string filePath = cmdStr.substr(fileBg); 101 | SourceFile(&tabSet, filePath.c_str()); 102 | } 103 | else 104 | { 105 | //SQL 只有 sql 才需要转utf8编码 106 | std::string sqlStr = GbkToUtf8(cmdStr); 107 | int errPos = -1; 108 | int retVal = ExecuteSql(&tabSet, sqlStr.c_str(), &errPos); 109 | if (retVal != ER_OK) 110 | { 111 | if (errPos >= 0) 112 | { 113 | //errPos是UTF8编码, 输出时是GBK编码 114 | size_t spacePos = sqlStr.find_first_of(' ', errPos); 115 | std::string errPart = sqlStr.substr(errPos, (spacePos - errPos)); 116 | std::cout <<"SQL: " << Utf8ToGbk(errPart).c_str() <<" ,附近有错误" << std::endl; 117 | } 118 | std::cout << GetErrMsg(retVal) << std::endl; 119 | } 120 | } 121 | } 122 | } 123 | 124 | return 0; 125 | } 126 | 127 | int ExecuteSql(TableSet* pTabSet, const char* pSql, int* pErrPos) 128 | { 129 | SQLParser parser; 130 | Arena arena; 131 | int retVal = ER_OK; 132 | 133 | if (pErrPos != nullptr) 134 | *pErrPos = -1; 135 | 136 | retVal = SQLTokenize::RunParser(&parser, &arena, pSql, strlen(pSql)); 137 | if (retVal != ER_OK) 138 | return retVal; 139 | 140 | if (parser.GetError()) 141 | { 142 | if (pErrPos != nullptr) 143 | *pErrPos = parser.GetErrPos(); 144 | 145 | return ER_SQL_ERR; 146 | } 147 | else 148 | { 149 | switch (parser.GetCmdType()) 150 | { 151 | case SQLParser::SQLType::ShowTables: 152 | ShowTables(pTabSet); 153 | break; 154 | case SQLParser::SQLType::ShowTableColumns: 155 | return ShowTableColumns(pTabSet, parser.GetTableName()); 156 | case SQLParser::SQLType::CreateTable: 157 | retVal = pTabSet->CreateTable(parser.GetTableName(), parser.GetCreateTableParam(), pErrPos); 158 | break; 159 | case SQLParser::SQLType::DropTable: 160 | retVal = pTabSet->DropTable(parser.GetTableName()); 161 | break; 162 | case SQLParser::SQLType::Delete: 163 | retVal = pTabSet->Delete(parser.GetTableName(), parser.GetDeleteParam(), pErrPos); 164 | break; 165 | case SQLParser::SQLType::Query: 166 | retVal = ExecQuery(pTabSet, parser.GetTableName(), parser.GetQueryParam(), pErrPos); 167 | break; 168 | case SQLParser::SQLType::Insert: 169 | retVal = pTabSet->Insert(parser.GetTableName(), parser.GetInsertParam(), pErrPos); 170 | break; 171 | default: 172 | retVal = ER_SQL_ERR; 173 | break; 174 | } 175 | } 176 | 177 | return retVal; 178 | } 179 | 180 | void ShowHelp() 181 | { 182 | std::cout << "MyBase 版本: " << pVersion << std::endl; 183 | std::cout << "CMD:" << std::endl; 184 | std::cout << " ? | HELP - 打印帮助信息" << std::endl; 185 | std::cout << " CLS | CLEAR - 清屏" << std::endl; 186 | std::cout << " EXIT | QUIT - 退出" << std::endl; 187 | std::cout << " SOURCE - 执行SQL文件" << std::endl; 188 | std::cout << "SQL:" << std::endl; 189 | std::cout << " SHOW TABLES" << std::endl; 190 | std::cout << " SHOW COLUMNS FROM " << std::endl; 191 | std::cout << " CREATE TABLE ( [, ...])" << std::endl; 192 | std::cout << " DROP TABLE " << std::endl; 193 | std::cout << " INSERT INTO ( ) VALUES( )" << std::endl; 194 | std::cout << " SELECT FROM [WHERE ] [GROUP BY ] [LIMIT offset,cnt]" << std::endl; 195 | std::cout << " DELETE FROM [WHERE ]" << std::endl; 196 | } 197 | 198 | std::string GbkToUtf8(const std::string& gbkStr) 199 | { 200 | int len = MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, NULL, 0); 201 | wchar_t* wstr = new wchar_t[len + 1]; 202 | memset(wstr, 0, len + 1); 203 | MultiByteToWideChar(CP_ACP, 0, gbkStr.c_str(), -1, wstr, len); 204 | len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); 205 | char* pStr = new char[len + 1]; 206 | memset(pStr, 0, len + 1); 207 | WideCharToMultiByte(CP_UTF8, 0, wstr, -1, pStr, len, NULL, NULL); 208 | std::string result(pStr); 209 | delete pStr; 210 | delete wstr; 211 | return result; 212 | } 213 | 214 | std::string Utf8ToGbk(const std::string& utf8Str) 215 | { 216 | int len = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0); 217 | wchar_t* wstr = new wchar_t[len + 1]; 218 | memset(wstr, 0, len + 1); 219 | MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, wstr, len); 220 | len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); 221 | char* pStr = new char[len + 1]; 222 | memset(pStr, 0, len + 1); 223 | WideCharToMultiByte(CP_ACP, 0, wstr, -1, pStr, len, NULL, NULL); 224 | std::string result(pStr); 225 | delete pStr; 226 | delete wstr; 227 | return result; 228 | } 229 | 230 | #define PRINT_LINE(lineLen) do { std::cout.fill('-'); std::cout.width(lineLen); std::cout<< "-" << std::endl; std::cout.fill(' '); } while(false) 231 | #define PRINT_VAL_LEFT(val) do { std::cout.width(9); std::cout.setf(std::ios::left); std::cout << (val) << "|"; std::cout.unsetf(std::ios::left); } while(false) 232 | #define PRINT_VAL_RIGHT(val) do { std::cout.width(9); std::cout.setf(std::ios::right); std::cout << (val) << "|"; std::cout.unsetf(std::ios::right); } while(false) 233 | 234 | int ExecQuery(TableSet* pTabSet, const std::string& tabName, const QueryParam* pQueryParam, int* pErrPos) 235 | { 236 | int retVal = ER_OK; 237 | Query* pQuery = nullptr; 238 | 239 | retVal = pTabSet->ExecQuery(tabName, pQueryParam, &pQuery, pErrPos); 240 | if (retVal != ER_OK) 241 | return retVal; 242 | 243 | //输出查询结果 244 | const std::vector& nameVec = pQuery->getNameVec(); 245 | size_t lineSize = nameVec.size() * 10; 246 | PRINT_LINE(lineSize); 247 | for (auto nameIt = nameVec.begin(); nameIt != nameVec.end(); nameIt++) 248 | { 249 | PRINT_VAL_LEFT(nameIt->c_str()); 250 | } 251 | std::cout << std::endl; 252 | PRINT_LINE(lineSize); 253 | 254 | std::string strVal; 255 | std::vector valVec; 256 | const std::vector& dataVec = pQuery->getResultData(); 257 | for (auto dataIt = dataVec.begin(); dataIt != dataVec.end(); dataIt++) 258 | { 259 | (*dataIt)->GetDataRec(valVec); 260 | 261 | for (auto valIt = valVec.begin(); valIt != valVec.end(); valIt++) 262 | { 263 | switch (valIt->valType_) 264 | { 265 | case VALUE_TYPE::VAL_NULL: 266 | PRINT_VAL_RIGHT("null"); 267 | break; 268 | case VALUE_TYPE::VAL_INT: 269 | PRINT_VAL_RIGHT(valIt->val_.intVal_); 270 | break; 271 | case VALUE_TYPE::VAL_DOUBLE: 272 | PRINT_VAL_RIGHT(valIt->val_.doubleVal_); 273 | break; 274 | case VALUE_TYPE::VAL_STRING: 275 | strVal = std::string(valIt->val_.strVal_, valIt->dataLen_); 276 | PRINT_VAL_LEFT(Utf8ToGbk(strVal).c_str()); 277 | break; 278 | } 279 | } 280 | 281 | std::cout << std::endl; 282 | } 283 | PRINT_LINE(lineSize); 284 | 285 | if (pQuery != nullptr) 286 | { 287 | delete pQuery; 288 | } 289 | 290 | return ER_OK; 291 | } 292 | 293 | void ShowTables(TableSet* pTabSet) 294 | { 295 | std::vector nameVec; 296 | pTabSet->ShowTables(nameVec); 297 | std::cout << "TABLES:" << std::endl; 298 | for (auto nameIt = nameVec.begin(); nameIt != nameVec.end(); nameIt++) 299 | { 300 | std::cout << " " << nameIt->c_str() << std::endl; 301 | } 302 | } 303 | 304 | int ShowTableColumns(TableSet* pTabSet, const std::string& tabName) 305 | { 306 | int retVal = ER_OK; 307 | std::vector colVec; 308 | retVal = pTabSet->ShowTableColumns(tabName, colVec); 309 | if (retVal != ER_OK) 310 | return retVal; 311 | 312 | std::cout << tabName.c_str() << std::endl; 313 | PRINT_LINE(20); 314 | PRINT_VAL_LEFT("COL NAME"); 315 | PRINT_VAL_LEFT("TYPE"); 316 | std::cout << std::endl; 317 | PRINT_LINE(20); 318 | for (auto colIt = colVec.begin(); colIt != colVec.end(); colIt++) 319 | { 320 | PRINT_VAL_LEFT(colIt->colName_); 321 | switch (colIt->colType_) 322 | { 323 | case VALUE_TYPE::VAL_INT: 324 | PRINT_VAL_LEFT("INT"); 325 | break; 326 | case VALUE_TYPE::VAL_DOUBLE: 327 | PRINT_VAL_LEFT("DOUBLE"); 328 | break; 329 | case VALUE_TYPE::VAL_STRING: 330 | PRINT_VAL_LEFT("STRING"); 331 | break; 332 | } 333 | std::cout << std::endl; 334 | } 335 | PRINT_LINE(20); 336 | 337 | return ER_OK; 338 | } 339 | 340 | void SourceFile(TableSet* pTabSet, const char* pFile) 341 | { 342 | std::ifstream sqlFile; 343 | sqlFile.open(pFile); 344 | if (!sqlFile.is_open()) 345 | { 346 | std::cout << "打开文件:" << pFile << ", 失败" << std::endl; 347 | return; 348 | } 349 | 350 | int retVal = ER_OK; 351 | int errPos = -1; 352 | int idx = 0; 353 | 354 | std::string line; 355 | while (std::getline(sqlFile, line)) 356 | { 357 | idx++; 358 | 359 | if (line.find_first_not_of(' ') == std::string::npos) 360 | continue; 361 | 362 | retVal = ExecuteSql(pTabSet, line.c_str(), &errPos); 363 | if (retVal != ER_OK) 364 | { 365 | std::cout << "第 " << idx << " 条SQL错误" << std::endl; 366 | if (errPos >= 0) 367 | { 368 | //errPos是UTF8编码, 输出时是GBK编码 369 | size_t spacePos = line.find_first_of(' ', errPos); 370 | std::string errPart = line.substr(errPos, (spacePos - errPos)); 371 | std::cout << "SQL: " << Utf8ToGbk(errPart).c_str() << " ,附近有错误" << std::endl; 372 | } 373 | std::cout << GetErrMsg(retVal) << std::endl; 374 | break; 375 | } 376 | } 377 | sqlFile.close(); 378 | } 379 | -------------------------------------------------------------------------------- /MyBase/mybase.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/mybase.ico -------------------------------------------------------------------------------- /MyBase/page.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/page.h -------------------------------------------------------------------------------- /MyBase/parse.cpp: -------------------------------------------------------------------------------- 1 | /* Driver template for the LEMON parser generator. 2 | ** The author disclaims copyright to this source code. 3 | */ 4 | /* First off, code is include which follows the "include" declaration 5 | ** in the input file. */ 6 | #include 7 | #line 1 "parse.y" 8 | 9 | #include "parse.h" 10 | #include "dbval.h" 11 | #include "sql_part.h" 12 | #include "sql_parser.h" 13 | 14 | #line 15 "parse.c" 15 | /* Next is all token values, in a form suitable for use by makeheaders. 16 | ** This section will be null unless lemon is run with the -m switch. 17 | */ 18 | /* 19 | ** These constants (all generated automatically by the parser generator) 20 | ** specify the various kinds of tokens (terminals) that the parser 21 | ** understands. 22 | ** 23 | ** Each symbol here is a terminal symbol in the grammar. 24 | */ 25 | /* Make sure the INTERFACE macro is defined. 26 | */ 27 | #ifndef INTERFACE 28 | # define INTERFACE 1 29 | #endif 30 | /* The next thing included is series of defines which control 31 | ** various aspects of the generated parser. 32 | ** YYCODETYPE is the data type used for storing terminal 33 | ** and nonterminal numbers. "unsigned char" is 34 | ** used if there are fewer than 250 terminals 35 | ** and nonterminals. "int" is used otherwise. 36 | ** YYNOCODE is a number of type YYCODETYPE which corresponds 37 | ** to no legal terminal or nonterminal number. This 38 | ** number is used to fill in empty slots of the hash 39 | ** table. 40 | ** YYFALLBACK If defined, this indicates that one or more tokens 41 | ** have fall-back values which should be used if the 42 | ** original value of the token will not parse. 43 | ** YYACTIONTYPE is the data type used for storing terminal 44 | ** and nonterminal numbers. "unsigned char" is 45 | ** used if there are fewer than 250 rules and 46 | ** states combined. "int" is used otherwise. 47 | ** mydbParseTOKENTYPE is the data type used for minor tokens given 48 | ** directly to the parser from the tokenizer. 49 | ** YYMINORTYPE is the data type used for all minor tokens. 50 | ** This is typically a union of many types, one of 51 | ** which is mydbParseTOKENTYPE. The entry in the union 52 | ** for base tokens is called "yy0". 53 | ** YYSTACKDEPTH is the maximum depth of the parser's stack. 54 | ** mydbParseARG_SDECL A static variable declaration for the %extra_argument 55 | ** mydbParseARG_PDECL A parameter declaration for the %extra_argument 56 | ** mydbParseARG_STORE Code to store %extra_argument into yypParser 57 | ** mydbParseARG_FETCH Code to extract %extra_argument from yypParser 58 | ** YYNSTATE the combined number of states. 59 | ** YYNRULE the number of rules in the grammar 60 | ** YYERRORSYMBOL is the code number of the error symbol. If not 61 | ** defined, then do no error processing. 62 | */ 63 | /*  */ 64 | #define YYCODETYPE unsigned char 65 | #define YYNOCODE 67 66 | #define YYACTIONTYPE unsigned char 67 | #define mydbParseTOKENTYPE Token 68 | typedef union { 69 | mydbParseTOKENTYPE yy0; 70 | ExprItem* yy1; 71 | GroupOpt* yy3; 72 | ExprList* yy58; 73 | ColumnItem* yy68; 74 | Token yy78; 75 | ColumnList* yy125; 76 | LimitOpt* yy126; 77 | int yy133; 78 | } YYMINORTYPE; 79 | #define YYSTACKDEPTH 100 80 | #define mydbParseARG_SDECL SQLParser *pParse; 81 | #define mydbParseARG_PDECL ,SQLParser *pParse 82 | #define mydbParseARG_FETCH SQLParser *pParse = yypParser->pParse 83 | #define mydbParseARG_STORE yypParser->pParse = pParse 84 | #define YYNSTATE 122 85 | #define YYNRULE 56 86 | #define YYERRORSYMBOL 50 87 | #define YYERRSYMDT yy133 88 | #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) 89 | #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) 90 | #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) 91 | 92 | /* Next are that tables used to determine what action to take based on the 93 | ** current state and lookahead token. These tables are used to implement 94 | ** functions that take a state number and lookahead value and return an 95 | ** action integer. 96 | ** 97 | ** Suppose the action integer is N. Then the action is determined as 98 | ** follows 99 | ** 100 | ** 0 <= N < YYNSTATE Shift N. That is, push the lookahead 101 | ** token onto the stack and goto state N. 102 | ** 103 | ** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. 104 | ** 105 | ** N == YYNSTATE+YYNRULE A syntax error has occurred. 106 | ** 107 | ** N == YYNSTATE+YYNRULE+1 The parser accepts its input. 108 | ** 109 | ** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused 110 | ** slots in the yy_action[] table. 111 | ** 112 | ** The action table is constructed as a single large table named yy_action[]. 113 | ** Given state S and lookahead X, the action is computed as 114 | ** 115 | ** yy_action[ yy_shift_ofst[S] + X ] 116 | ** 117 | ** If the index value yy_shift_ofst[S]+X is out of range or if the value 118 | ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] 119 | ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table 120 | ** and that yy_default[S] should be used instead. 121 | ** 122 | ** The formula above is for computing the action when the lookahead is 123 | ** a terminal symbol. If the lookahead is a non-terminal (as occurs after 124 | ** a reduce action) then the yy_reduce_ofst[] array is used in place of 125 | ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of 126 | ** YY_SHIFT_USE_DFLT. 127 | ** 128 | ** The following are the tables generated in this section: 129 | ** 130 | ** yy_action[] A single table containing all actions. 131 | ** yy_lookahead[] A table containing the lookahead for each entry in 132 | ** yy_action. Used to detect hash collisions. 133 | ** yy_shift_ofst[] For each state, the offset into yy_action for 134 | ** shifting terminals. 135 | ** yy_reduce_ofst[] For each state, the offset into yy_action for 136 | ** shifting non-terminals after a reduce. 137 | ** yy_default[] Default action for each state. 138 | */ 139 | static YYACTIONTYPE yy_action[] = { 140 | /* 0 */ 52, 54, 48, 50, 35, 46, 56, 58, 34, 98, 141 | /* 10 */ 1, 21, 22, 23, 59, 61, 8, 109, 12, 71, 142 | /* 20 */ 73, 67, 69, 63, 65, 26, 76, 43, 37, 93, 143 | /* 30 */ 62, 40, 108, 81, 37, 112, 85, 90, 75, 113, 144 | /* 40 */ 87, 44, 38, 39, 42, 41, 62, 45, 38, 39, 145 | /* 50 */ 42, 111, 117, 45, 32, 84, 89, 114, 153, 148, 146 | /* 60 */ 16, 25, 152, 17, 94, 119, 24, 19, 121, 2, 147 | /* 70 */ 102, 4, 115, 125, 20, 107, 99, 97, 31, 96, 148 | /* 80 */ 104, 95, 18, 31, 100, 137, 91, 88, 110, 101, 149 | /* 90 */ 28, 132, 15, 29, 30, 86, 131, 103, 13, 14, 150 | /* 100 */ 154, 33, 6, 124, 5, 105, 11, 36, 83, 80, 151 | /* 110 */ 106, 92, 79, 82, 10, 78, 74, 72, 70, 77, 152 | /* 120 */ 68, 9, 66, 64, 122, 120, 7, 118, 47, 57, 153 | /* 130 */ 3, 123, 116, 179, 27, 124, 49, 124, 55, 124, 154 | /* 140 */ 51, 53, 124, 60, 155 | }; 156 | static YYCODETYPE yy_lookahead[] = { 157 | /* 0 */ 32, 33, 34, 35, 36, 37, 38, 39, 10, 61, 158 | /* 10 */ 5, 16, 17, 18, 40, 41, 11, 10, 13, 32, 159 | /* 20 */ 33, 34, 35, 36, 37, 20, 21, 30, 30, 24, 160 | /* 30 */ 57, 30, 25, 15, 30, 15, 15, 19, 65, 19, 161 | /* 40 */ 19, 44, 44, 45, 46, 44, 57, 49, 44, 45, 162 | /* 50 */ 46, 63, 64, 49, 65, 56, 57, 10, 7, 7, 163 | /* 60 */ 52, 53, 7, 15, 58, 9, 53, 19, 62, 6, 164 | /* 70 */ 19, 8, 25, 0, 10, 19, 7, 60, 26, 54, 165 | /* 80 */ 27, 59, 7, 26, 29, 0, 10, 57, 14, 30, 166 | /* 90 */ 10, 0, 14, 54, 7, 7, 0, 30, 12, 10, 167 | /* 100 */ 7, 31, 10, 0, 9, 28, 7, 57, 14, 55, 168 | /* 110 */ 10, 10, 14, 23, 10, 10, 10, 10, 10, 22, 169 | /* 120 */ 10, 12, 10, 10, 0, 10, 7, 62, 57, 57, 170 | /* 130 */ 7, 0, 64, 51, 9, 66, 57, 66, 57, 66, 171 | /* 140 */ 57, 57, 66, 41, 172 | }; 173 | #define YY_SHIFT_USE_DFLT (-33) 174 | static short yy_shift_ofst[] = { 175 | /* 0 */ 5, 63, 123, 124, 95, 92, 119, 131, 109, 104, 176 | /* 10 */ 99, 103, 86, 89, 78, 64, 48, 75, 73, 64, 177 | /* 20 */ -5, -33, -33, -33, -33, -33, 125, 80, 52, 87, 178 | /* 30 */ 96, -2, 70, -2, -32, 4, -33, -33, -33, 1, 179 | /* 40 */ -33, -33, -3, -33, -33, -33, 4, -33, 4, -33, 180 | /* 50 */ 4, -33, 4, -33, 4, -33, 4, -33, -26, 102, 181 | /* 60 */ -33, -33, -13, 113, -33, 112, -33, 110, -33, 108, 182 | /* 70 */ -33, 107, -33, 106, -33, -33, 97, 105, 98, 101, 183 | /* 80 */ 18, 90, 94, 4, 21, 88, 91, 4, -33, -33, 184 | /* 90 */ 76, -33, -33, 7, 56, 57, 53, 55, 69, 85, 185 | /* 100 */ 59, 51, 67, 93, 77, 100, -33, 7, -33, 74, 186 | /* 110 */ 47, 20, -33, 47, -33, -33, -33, -33, -33, 115, 187 | /* 120 */ -33, -33, 188 | }; 189 | #define YY_REDUCE_USE_DFLT (-53) 190 | static signed char yy_reduce_ofst[] = { 191 | /* 0 */ 82, -53, -53, -53, -53, -53, -53, -53, -53, -53, 192 | /* 10 */ -53, -53, -53, -53, -53, 8, -53, -53, -53, 13, 193 | /* 20 */ -53, -53, -53, -53, -53, -53, -53, -53, 39, -53, 194 | /* 30 */ -53, -11, -53, -27, -53, 50, -53, -53, -53, -53, 195 | /* 40 */ -53, -53, -53, -53, -53, -53, 71, -53, 79, -53, 196 | /* 50 */ 83, -53, 84, -53, 81, -53, 72, -53, -53, -53, 197 | /* 60 */ -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, 198 | /* 70 */ -53, -53, -53, -53, -53, -53, -53, -53, -53, 54, 199 | /* 80 */ -53, -53, -53, -1, -53, -53, -53, 30, -53, -53, 200 | /* 90 */ -53, -53, -53, 6, 22, 25, 17, -52, -53, -53, 201 | /* 100 */ -53, -53, -53, -53, -53, -53, -53, 65, -53, -53, 202 | /* 110 */ -12, -53, -53, 68, -53, -53, -53, -53, -53, -53, 203 | /* 120 */ -53, -53, 204 | }; 205 | static YYACTIONTYPE yy_default[] = { 206 | /* 0 */ 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 207 | /* 10 */ 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 208 | /* 20 */ 178, 126, 127, 128, 130, 129, 178, 178, 178, 178, 209 | /* 30 */ 178, 178, 149, 178, 178, 178, 155, 171, 172, 178, 210 | /* 40 */ 173, 174, 178, 175, 176, 177, 178, 156, 178, 157, 211 | /* 50 */ 178, 158, 178, 159, 178, 160, 178, 161, 178, 178, 212 | /* 60 */ 162, 163, 178, 178, 164, 178, 165, 178, 166, 178, 213 | /* 70 */ 167, 178, 168, 178, 169, 170, 178, 178, 178, 178, 214 | /* 80 */ 178, 178, 178, 178, 178, 178, 178, 178, 136, 135, 215 | /* 90 */ 178, 134, 133, 178, 178, 148, 150, 178, 178, 178, 216 | /* 100 */ 178, 178, 178, 178, 178, 178, 151, 178, 138, 139, 217 | /* 110 */ 178, 178, 140, 178, 143, 144, 146, 145, 142, 178, 218 | /* 120 */ 147, 141, 219 | }; 220 | #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) 221 | 222 | /* The next table maps tokens into fallback tokens. If a construct 223 | ** like the following: 224 | ** 225 | ** %fallback ID X Y Z. 226 | ** 227 | ** appears in the grammer, then ID becomes a fallback token for X, Y, 228 | ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser 229 | ** but it does not parse, the type of the token is changed to ID and 230 | ** the parse is retried before an error is thrown. 231 | */ 232 | #ifdef YYFALLBACK 233 | static const YYCODETYPE yyFallback[] = { 234 | }; 235 | #endif /* YYFALLBACK */ 236 | 237 | /* The following structure represents a single element of the 238 | ** parser's stack. Information stored includes: 239 | ** 240 | ** + The state number for the parser at this level of the stack. 241 | ** 242 | ** + The value of the token stored at this level of the stack. 243 | ** (In other words, the "major" token.) 244 | ** 245 | ** + The semantic value stored at this level of the stack. This is 246 | ** the information used by the action routines in the grammar. 247 | ** It is sometimes called the "minor" token. 248 | */ 249 | struct yyStackEntry { 250 | int stateno; /* The state-number */ 251 | int major; /* The major token value. This is the code 252 | ** number for the token at this stack level */ 253 | YYMINORTYPE minor; /* The user-supplied minor token value. This 254 | ** is the value of the token */ 255 | }; 256 | typedef struct yyStackEntry yyStackEntry; 257 | 258 | /* The state of the parser is completely contained in an instance of 259 | ** the following structure */ 260 | struct yyParser { 261 | int yyidx; /* Index of top element in stack */ 262 | int yyerrcnt; /* Shifts left before out of the error */ 263 | mydbParseARG_SDECL /* A place to hold %extra_argument */ 264 | yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ 265 | }; 266 | typedef struct yyParser yyParser; 267 | 268 | #ifndef NDEBUG 269 | #include 270 | static FILE *yyTraceFILE = 0; 271 | static char *yyTracePrompt = 0; 272 | #endif /* NDEBUG */ 273 | 274 | #ifndef NDEBUG 275 | /* 276 | ** Turn parser tracing on by giving a stream to which to write the trace 277 | ** and a prompt to preface each trace message. Tracing is turned off 278 | ** by making either argument NULL 279 | ** 280 | ** Inputs: 281 | **
    282 | **
  • A FILE* to which trace output should be written. 283 | ** If NULL, then tracing is turned off. 284 | **
  • A prefix string written at the beginning of every 285 | ** line of trace output. If NULL, then tracing is 286 | ** turned off. 287 | **
288 | ** 289 | ** Outputs: 290 | ** None. 291 | */ 292 | void mydbParseTrace(FILE *TraceFILE, char *zTracePrompt){ 293 | yyTraceFILE = TraceFILE; 294 | yyTracePrompt = zTracePrompt; 295 | if( yyTraceFILE==0 ) yyTracePrompt = 0; 296 | else if( yyTracePrompt==0 ) yyTraceFILE = 0; 297 | } 298 | #endif /* NDEBUG */ 299 | 300 | #ifndef NDEBUG 301 | /* For tracing shifts, the names of all terminals and nonterminals 302 | ** are required. The following table supplies these names */ 303 | static const char *yyTokenName[] = { 304 | "$", "FUNC", "ILLEGAL", "SPACE", 305 | "COMMENT", "SHOW", "TABLES", "SEMI", 306 | "COLUMNS", "FROM", "ID", "DROP", 307 | "TABLE", "CREATE", "LP", "RP", 308 | "INT_TYPE", "DOUBLE_TYPE", "STRING_TYPE", "COMMA", 309 | "DELETE", "INSERT", "INTO", "VALUES", 310 | "SELECT", "STAR", "WHERE", "GROUP", 311 | "BY", "LIMIT", "INTEGER", "AND", 312 | "EQ", "NE", "GT", "GE", 313 | "LT", "LE", "LIKE", "IS", 314 | "NOT", "NULL", "ISNOTNULL", "ISNULL", 315 | "DOUBLE", "PLUS", "MINUS", "UINTEGER", 316 | "UDOUBLE", "STRING", "error", "cmd", 317 | "col_list", "col_item", "where_opt", "name_list", 318 | "val_list", "val_item", "target_list", "from", 319 | "groupby_opt", "limit_opt", "target_item", "arg_list", 320 | "arg_item", "condi_expr", 321 | }; 322 | #endif /* NDEBUG */ 323 | 324 | #ifndef NDEBUG 325 | /* For tracing reduce actions, the names of all rules are required. 326 | */ 327 | static const char *yyRuleName[] = { 328 | /* 0 */ "cmd ::= SHOW TABLES SEMI", 329 | /* 1 */ "cmd ::= SHOW COLUMNS FROM ID SEMI", 330 | /* 2 */ "cmd ::= DROP TABLE ID SEMI", 331 | /* 3 */ "cmd ::= CREATE TABLE ID LP col_list RP SEMI", 332 | /* 4 */ "col_item ::= ID INT_TYPE", 333 | /* 5 */ "col_item ::= ID DOUBLE_TYPE", 334 | /* 6 */ "col_item ::= ID STRING_TYPE", 335 | /* 7 */ "col_list ::= col_item", 336 | /* 8 */ "col_list ::= col_list COMMA col_item", 337 | /* 9 */ "cmd ::= DELETE FROM ID where_opt SEMI", 338 | /* 10 */ "cmd ::= INSERT INTO ID LP name_list RP VALUES LP val_list RP SEMI", 339 | /* 11 */ "name_list ::= ID", 340 | /* 12 */ "name_list ::= name_list COMMA ID", 341 | /* 13 */ "val_list ::= val_item", 342 | /* 14 */ "val_list ::= val_list COMMA val_item", 343 | /* 15 */ "cmd ::= SELECT target_list from where_opt groupby_opt limit_opt SEMI", 344 | /* 16 */ "target_item ::= STAR", 345 | /* 17 */ "target_item ::= ID", 346 | /* 18 */ "target_item ::= ID LP arg_list RP", 347 | /* 19 */ "target_list ::= target_item", 348 | /* 20 */ "target_list ::= target_list COMMA target_item", 349 | /* 21 */ "arg_item ::= ID", 350 | /* 22 */ "arg_item ::= STAR", 351 | /* 23 */ "arg_list ::= arg_item", 352 | /* 24 */ "arg_list ::= arg_list COMMA arg_item", 353 | /* 25 */ "from ::= FROM ID", 354 | /* 26 */ "where_opt ::=", 355 | /* 27 */ "where_opt ::= WHERE condi_expr", 356 | /* 28 */ "groupby_opt ::=", 357 | /* 29 */ "groupby_opt ::= GROUP BY ID", 358 | /* 30 */ "limit_opt ::=", 359 | /* 31 */ "limit_opt ::= LIMIT INTEGER", 360 | /* 32 */ "limit_opt ::= LIMIT INTEGER COMMA INTEGER", 361 | /* 33 */ "condi_expr ::= ID LT val_item", 362 | /* 34 */ "condi_expr ::= ID LE val_item", 363 | /* 35 */ "condi_expr ::= ID GT val_item", 364 | /* 36 */ "condi_expr ::= ID GE val_item", 365 | /* 37 */ "condi_expr ::= ID EQ val_item", 366 | /* 38 */ "condi_expr ::= ID NE val_item", 367 | /* 39 */ "condi_expr ::= ID LIKE val_item", 368 | /* 40 */ "condi_expr ::= ID IS NOT NULL", 369 | /* 41 */ "condi_expr ::= ID IS NULL", 370 | /* 42 */ "condi_expr ::= val_item LT ID", 371 | /* 43 */ "condi_expr ::= val_item LE ID", 372 | /* 44 */ "condi_expr ::= val_item GT ID", 373 | /* 45 */ "condi_expr ::= val_item GE ID", 374 | /* 46 */ "condi_expr ::= val_item EQ ID", 375 | /* 47 */ "condi_expr ::= val_item NE ID", 376 | /* 48 */ "condi_expr ::= condi_expr AND condi_expr", 377 | /* 49 */ "val_item ::= INTEGER", 378 | /* 50 */ "val_item ::= DOUBLE", 379 | /* 51 */ "val_item ::= PLUS INTEGER", 380 | /* 52 */ "val_item ::= PLUS DOUBLE", 381 | /* 53 */ "val_item ::= MINUS INTEGER", 382 | /* 54 */ "val_item ::= MINUS DOUBLE", 383 | /* 55 */ "val_item ::= STRING", 384 | }; 385 | #endif /* NDEBUG */ 386 | 387 | /* 388 | ** This function returns the symbolic name associated with a token 389 | ** value. 390 | */ 391 | const char *mydbParseTokenName(int tokenType){ 392 | #ifndef NDEBUG 393 | if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ 394 | return yyTokenName[tokenType]; 395 | }else{ 396 | return "Unknown"; 397 | } 398 | #else 399 | return ""; 400 | #endif 401 | } 402 | 403 | /* 404 | ** This function allocates a new parser. 405 | ** The only argument is a pointer to a function which works like 406 | ** malloc. 407 | ** 408 | ** Inputs: 409 | ** A pointer to the function used to allocate memory. 410 | ** 411 | ** Outputs: 412 | ** A pointer to a parser. This pointer is used in subsequent calls 413 | ** to mydbParse and mydbParseFree. 414 | */ 415 | void *mydbParseAlloc(void *(*mallocProc)(size_t)){ 416 | yyParser *pParser; 417 | pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); 418 | if( pParser ){ 419 | pParser->yyidx = -1; 420 | } 421 | return pParser; 422 | } 423 | 424 | /* The following function deletes the value associated with a 425 | ** symbol. The symbol can be either a terminal or nonterminal. 426 | ** "yymajor" is the symbol code, and "yypminor" is a pointer to 427 | ** the value. 428 | */ 429 | static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ 430 | switch( yymajor ){ 431 | /* Here is inserted the actions which take place when a 432 | ** terminal or non-terminal is destroyed. This can happen 433 | ** when the symbol is popped from the stack during a 434 | ** reduce or during error processing or when a parser is 435 | ** being destroyed before it is finished parsing. 436 | ** 437 | ** Note: during a reduce, the only symbols destroyed are those 438 | ** which appear on the RHS of the rule, but which are not used 439 | ** inside the C code. 440 | */ 441 | case 52: 442 | #line 42 "parse.y" 443 | { delete ((yypminor->yy125)); } 444 | #line 444 "parse.c" 445 | break; 446 | case 53: 447 | #line 40 "parse.y" 448 | { delete ((yypminor->yy68)); } 449 | #line 449 "parse.c" 450 | break; 451 | case 54: 452 | #line 131 "parse.y" 453 | { delete ((yypminor->yy1)); } 454 | #line 454 "parse.c" 455 | break; 456 | case 55: 457 | #line 67 "parse.y" 458 | { delete ((yypminor->yy58)); } 459 | #line 459 "parse.c" 460 | break; 461 | case 56: 462 | #line 78 "parse.y" 463 | { delete ((yypminor->yy58)); } 464 | #line 464 "parse.c" 465 | break; 466 | case 57: 467 | #line 178 "parse.y" 468 | { delete ((yypminor->yy1)); } 469 | #line 469 "parse.c" 470 | break; 471 | case 58: 472 | #line 95 "parse.y" 473 | { delete ((yypminor->yy58)); } 474 | #line 474 "parse.c" 475 | break; 476 | case 60: 477 | #line 137 "parse.y" 478 | { delete ((yypminor->yy3)); } 479 | #line 479 "parse.c" 480 | break; 481 | case 61: 482 | #line 143 "parse.y" 483 | { delete ((yypminor->yy126)); } 484 | #line 484 "parse.c" 485 | break; 486 | case 62: 487 | #line 97 "parse.y" 488 | { delete ((yypminor->yy1)); } 489 | #line 489 "parse.c" 490 | break; 491 | case 63: 492 | #line 114 "parse.y" 493 | { delete ((yypminor->yy58)); } 494 | #line 494 "parse.c" 495 | break; 496 | case 64: 497 | #line 112 "parse.y" 498 | { delete ((yypminor->yy1)); } 499 | #line 499 "parse.c" 500 | break; 501 | case 65: 502 | #line 156 "parse.y" 503 | { delete ((yypminor->yy1)); } 504 | #line 504 "parse.c" 505 | break; 506 | default: break; /* If no destructor action specified: do nothing */ 507 | } 508 | } 509 | 510 | /* 511 | ** Pop the parser's stack once. 512 | ** 513 | ** If there is a destructor routine associated with the token which 514 | ** is popped from the stack, then call it. 515 | ** 516 | ** Return the major token number for the symbol popped. 517 | */ 518 | static int yy_pop_parser_stack(yyParser *pParser){ 519 | YYCODETYPE yymajor; 520 | yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; 521 | 522 | if( pParser->yyidx<0 ) return 0; 523 | #ifndef NDEBUG 524 | if( yyTraceFILE && pParser->yyidx>=0 ){ 525 | fprintf(yyTraceFILE,"%sPopping %s\n", 526 | yyTracePrompt, 527 | yyTokenName[yytos->major]); 528 | } 529 | #endif 530 | yymajor = yytos->major; 531 | yy_destructor( yymajor, &yytos->minor); 532 | pParser->yyidx--; 533 | return yymajor; 534 | } 535 | 536 | /* 537 | ** Deallocate and destroy a parser. Destructors are all called for 538 | ** all stack elements before shutting the parser down. 539 | ** 540 | ** Inputs: 541 | **
    542 | **
  • A pointer to the parser. This should be a pointer 543 | ** obtained from mydbParseAlloc. 544 | **
  • A pointer to a function used to reclaim memory obtained 545 | ** from malloc. 546 | **
547 | */ 548 | void mydbParseFree( 549 | void *p, /* The parser to be deleted */ 550 | void (*freeProc)(void*) /* Function used to reclaim memory */ 551 | ){ 552 | yyParser *pParser = (yyParser*)p; 553 | if( pParser==0 ) return; 554 | while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); 555 | (*freeProc)((void*)pParser); 556 | } 557 | 558 | /* 559 | ** Find the appropriate action for a parser given the terminal 560 | ** look-ahead token iLookAhead. 561 | ** 562 | ** If the look-ahead token is YYNOCODE, then check to see if the action is 563 | ** independent of the look-ahead. If it is, return the action, otherwise 564 | ** return YY_NO_ACTION. 565 | */ 566 | static int yy_find_shift_action( 567 | yyParser *pParser, /* The parser */ 568 | int iLookAhead /* The look-ahead token */ 569 | ){ 570 | int i; 571 | int stateno = pParser->yystack[pParser->yyidx].stateno; 572 | 573 | /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ 574 | i = yy_shift_ofst[stateno]; 575 | if( i==YY_SHIFT_USE_DFLT ){ 576 | return yy_default[stateno]; 577 | } 578 | if( iLookAhead==YYNOCODE ){ 579 | return YY_NO_ACTION; 580 | } 581 | i += iLookAhead; 582 | if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ 583 | #ifdef YYFALLBACK 584 | int iFallback; /* Fallback token */ 585 | if( iLookAhead %s\n", 590 | yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); 591 | } 592 | #endif 593 | return yy_find_shift_action(pParser, iFallback); 594 | } 595 | #endif 596 | return yy_default[stateno]; 597 | }else{ 598 | return yy_action[i]; 599 | } 600 | } 601 | 602 | /* 603 | ** Find the appropriate action for a parser given the non-terminal 604 | ** look-ahead token iLookAhead. 605 | ** 606 | ** If the look-ahead token is YYNOCODE, then check to see if the action is 607 | ** independent of the look-ahead. If it is, return the action, otherwise 608 | ** return YY_NO_ACTION. 609 | */ 610 | static int yy_find_reduce_action( 611 | yyParser *pParser, /* The parser */ 612 | int iLookAhead /* The look-ahead token */ 613 | ){ 614 | int i; 615 | int stateno = pParser->yystack[pParser->yyidx].stateno; 616 | 617 | i = yy_reduce_ofst[stateno]; 618 | if( i==YY_REDUCE_USE_DFLT ){ 619 | return yy_default[stateno]; 620 | } 621 | if( iLookAhead==YYNOCODE ){ 622 | return YY_NO_ACTION; 623 | } 624 | i += iLookAhead; 625 | if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ 626 | return yy_default[stateno]; 627 | }else{ 628 | return yy_action[i]; 629 | } 630 | } 631 | 632 | /* 633 | ** Perform a shift action. 634 | */ 635 | static void yy_shift( 636 | yyParser *yypParser, /* The parser to be shifted */ 637 | int yyNewState, /* The new state to shift in */ 638 | int yyMajor, /* The major token to shift in */ 639 | YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ 640 | ){ 641 | yyStackEntry *yytos; 642 | yypParser->yyidx++; 643 | if( yypParser->yyidx>=YYSTACKDEPTH ){ 644 | mydbParseARG_FETCH; 645 | yypParser->yyidx--; 646 | #ifndef NDEBUG 647 | if( yyTraceFILE ){ 648 | fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); 649 | } 650 | #endif 651 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 652 | /* Here code is inserted which will execute if the parser 653 | ** stack every overflows */ 654 | mydbParseARG_STORE; /* Suppress warning about unused %extra_argument var */ 655 | return; 656 | } 657 | yytos = &yypParser->yystack[yypParser->yyidx]; 658 | yytos->stateno = yyNewState; 659 | yytos->major = yyMajor; 660 | yytos->minor = *yypMinor; 661 | #ifndef NDEBUG 662 | if( yyTraceFILE && yypParser->yyidx>0 ){ 663 | int i; 664 | fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); 665 | fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); 666 | for(i=1; i<=yypParser->yyidx; i++) 667 | fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); 668 | fprintf(yyTraceFILE,"\n"); 669 | } 670 | #endif 671 | } 672 | 673 | /* The following table contains information about every rule that 674 | ** is used during the reduce. 675 | */ 676 | static struct { 677 | YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ 678 | unsigned char nrhs; /* Number of right-hand side symbols in the rule */ 679 | } yyRuleInfo[] = { 680 | { 51, 3 }, 681 | { 51, 5 }, 682 | { 51, 4 }, 683 | { 51, 7 }, 684 | { 53, 2 }, 685 | { 53, 2 }, 686 | { 53, 2 }, 687 | { 52, 1 }, 688 | { 52, 3 }, 689 | { 51, 5 }, 690 | { 51, 11 }, 691 | { 55, 1 }, 692 | { 55, 3 }, 693 | { 56, 1 }, 694 | { 56, 3 }, 695 | { 51, 7 }, 696 | { 62, 1 }, 697 | { 62, 1 }, 698 | { 62, 4 }, 699 | { 58, 1 }, 700 | { 58, 3 }, 701 | { 64, 1 }, 702 | { 64, 1 }, 703 | { 63, 1 }, 704 | { 63, 3 }, 705 | { 59, 2 }, 706 | { 54, 0 }, 707 | { 54, 2 }, 708 | { 60, 0 }, 709 | { 60, 3 }, 710 | { 61, 0 }, 711 | { 61, 2 }, 712 | { 61, 4 }, 713 | { 65, 3 }, 714 | { 65, 3 }, 715 | { 65, 3 }, 716 | { 65, 3 }, 717 | { 65, 3 }, 718 | { 65, 3 }, 719 | { 65, 3 }, 720 | { 65, 4 }, 721 | { 65, 3 }, 722 | { 65, 3 }, 723 | { 65, 3 }, 724 | { 65, 3 }, 725 | { 65, 3 }, 726 | { 65, 3 }, 727 | { 65, 3 }, 728 | { 65, 3 }, 729 | { 57, 1 }, 730 | { 57, 1 }, 731 | { 57, 2 }, 732 | { 57, 2 }, 733 | { 57, 2 }, 734 | { 57, 2 }, 735 | { 57, 1 }, 736 | }; 737 | 738 | static void yy_accept(yyParser*); /* Forward Declaration */ 739 | 740 | /* 741 | ** Perform a reduce action and the shift that must immediately 742 | ** follow the reduce. 743 | */ 744 | static void yy_reduce( 745 | yyParser *yypParser, /* The parser */ 746 | int yyruleno /* Number of the rule by which to reduce */ 747 | ){ 748 | int yygoto; /* The next state */ 749 | int yyact; /* The next action */ 750 | YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ 751 | yyStackEntry *yymsp; /* The top of the parser's stack */ 752 | int yysize; /* Amount to pop the stack */ 753 | mydbParseARG_FETCH; 754 | yymsp = &yypParser->yystack[yypParser->yyidx]; 755 | #ifndef NDEBUG 756 | if( yyTraceFILE && yyruleno>=0 757 | && yyruleno 768 | ** { ... } // User supplied code 769 | ** #line 770 | ** break; 771 | */ 772 | case 0: 773 | #line 20 "parse.y" 774 | { 775 | pParse->SetShowTables(); 776 | } 777 | #line 777 "parse.c" 778 | /* No destructor defined for SHOW */ 779 | /* No destructor defined for TABLES */ 780 | /* No destructor defined for SEMI */ 781 | break; 782 | case 1: 783 | #line 24 "parse.y" 784 | { 785 | pParse->SetShowTableColumns(&yymsp[-1].minor.yy0); 786 | } 787 | #line 787 "parse.c" 788 | /* No destructor defined for SHOW */ 789 | /* No destructor defined for COLUMNS */ 790 | /* No destructor defined for FROM */ 791 | /* No destructor defined for SEMI */ 792 | break; 793 | case 2: 794 | #line 29 "parse.y" 795 | { 796 | pParse->SetDropTable(&yymsp[-1].minor.yy0); 797 | } 798 | #line 798 "parse.c" 799 | /* No destructor defined for DROP */ 800 | /* No destructor defined for TABLE */ 801 | /* No destructor defined for SEMI */ 802 | break; 803 | case 3: 804 | #line 35 "parse.y" 805 | { 806 | pParse->SetCreateTable(&yymsp[-4].minor.yy0, yymsp[-2].minor.yy125); 807 | } 808 | #line 808 "parse.c" 809 | /* No destructor defined for CREATE */ 810 | /* No destructor defined for TABLE */ 811 | /* No destructor defined for LP */ 812 | /* No destructor defined for RP */ 813 | /* No destructor defined for SEMI */ 814 | break; 815 | case 4: 816 | #line 44 "parse.y" 817 | { yygotominor.yy68 = new ColumnItem(&yymsp[-1].minor.yy0, VALUE_TYPE::VAL_INT); } 818 | #line 818 "parse.c" 819 | /* No destructor defined for INT_TYPE */ 820 | break; 821 | case 5: 822 | #line 45 "parse.y" 823 | { yygotominor.yy68 = new ColumnItem(&yymsp[-1].minor.yy0, VALUE_TYPE::VAL_DOUBLE); } 824 | #line 824 "parse.c" 825 | /* No destructor defined for DOUBLE_TYPE */ 826 | break; 827 | case 6: 828 | #line 46 "parse.y" 829 | { yygotominor.yy68 = new ColumnItem(&yymsp[-1].minor.yy0, VALUE_TYPE::VAL_STRING); } 830 | #line 830 "parse.c" 831 | /* No destructor defined for STRING_TYPE */ 832 | break; 833 | case 7: 834 | #line 47 "parse.y" 835 | { 836 | yygotominor.yy125 = sqlAppendColumn(nullptr, yymsp[0].minor.yy68); 837 | } 838 | #line 838 "parse.c" 839 | break; 840 | case 8: 841 | #line 50 "parse.y" 842 | { 843 | yygotominor.yy125 = sqlAppendColumn(yymsp[-2].minor.yy125, yymsp[0].minor.yy68); 844 | } 845 | #line 845 "parse.c" 846 | /* No destructor defined for COMMA */ 847 | break; 848 | case 9: 849 | #line 56 "parse.y" 850 | { 851 | pParse->SetDelete(&yymsp[-2].minor.yy0, yymsp[-1].minor.yy1); 852 | } 853 | #line 853 "parse.c" 854 | /* No destructor defined for DELETE */ 855 | /* No destructor defined for FROM */ 856 | /* No destructor defined for SEMI */ 857 | break; 858 | case 10: 859 | #line 62 "parse.y" 860 | { 861 | pParse->SetInsert(&yymsp[-8].minor.yy0, yymsp[-6].minor.yy58, yymsp[-2].minor.yy58); 862 | } 863 | #line 863 "parse.c" 864 | /* No destructor defined for INSERT */ 865 | /* No destructor defined for INTO */ 866 | /* No destructor defined for LP */ 867 | /* No destructor defined for RP */ 868 | /* No destructor defined for VALUES */ 869 | /* No destructor defined for LP */ 870 | /* No destructor defined for RP */ 871 | /* No destructor defined for SEMI */ 872 | break; 873 | case 11: 874 | #line 69 "parse.y" 875 | { 876 | yygotominor.yy58 = new ExprList(); 877 | yygotominor.yy58->AddExprItem(new ExprItem(TK_ID, &yymsp[0].minor.yy0)); 878 | } 879 | #line 879 "parse.c" 880 | break; 881 | case 12: 882 | #line 73 "parse.y" 883 | { 884 | yygotominor.yy58 = yymsp[-2].minor.yy58->AddExprItem(new ExprItem(TK_ID, &yymsp[0].minor.yy0)); 885 | } 886 | #line 886 "parse.c" 887 | /* No destructor defined for COMMA */ 888 | break; 889 | case 13: 890 | #line 80 "parse.y" 891 | { 892 | yygotominor.yy58 = new ExprList(); 893 | yygotominor.yy58->AddExprItem(yymsp[0].minor.yy1); 894 | } 895 | #line 895 "parse.c" 896 | break; 897 | case 14: 898 | #line 84 "parse.y" 899 | { 900 | yygotominor.yy58 = yymsp[-2].minor.yy58->AddExprItem(yymsp[0].minor.yy1); 901 | } 902 | #line 902 "parse.c" 903 | /* No destructor defined for COMMA */ 904 | break; 905 | case 15: 906 | #line 90 "parse.y" 907 | { 908 | pParse->SetQuery(yymsp[-5].minor.yy58, &yymsp[-4].minor.yy78, yymsp[-3].minor.yy1, yymsp[-2].minor.yy3, yymsp[-1].minor.yy126); 909 | } 910 | #line 910 "parse.c" 911 | /* No destructor defined for SELECT */ 912 | /* No destructor defined for SEMI */ 913 | break; 914 | case 16: 915 | #line 99 "parse.y" 916 | { yygotominor.yy1 = new ExprItem(TK_STAR, &yymsp[0].minor.yy0); } 917 | #line 917 "parse.c" 918 | break; 919 | case 17: 920 | #line 100 "parse.y" 921 | { yygotominor.yy1 = new ExprItem(TK_ID, &yymsp[0].minor.yy0); } 922 | #line 922 "parse.c" 923 | break; 924 | case 18: 925 | #line 101 "parse.y" 926 | { yygotominor.yy1 = new ExprItem(TK_FUNC, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy58); } 927 | #line 927 "parse.c" 928 | /* No destructor defined for LP */ 929 | /* No destructor defined for RP */ 930 | break; 931 | case 19: 932 | #line 103 "parse.y" 933 | { 934 | yygotominor.yy58 = new ExprList(); 935 | yygotominor.yy58->AddExprItem(yymsp[0].minor.yy1); 936 | } 937 | #line 937 "parse.c" 938 | break; 939 | case 20: 940 | #line 107 "parse.y" 941 | { 942 | yygotominor.yy58 = yymsp[-2].minor.yy58->AddExprItem(yymsp[0].minor.yy1); 943 | } 944 | #line 944 "parse.c" 945 | /* No destructor defined for COMMA */ 946 | break; 947 | case 21: 948 | #line 116 "parse.y" 949 | { yygotominor.yy1 = new ExprItem(TK_ID, &yymsp[0].minor.yy0); } 950 | #line 950 "parse.c" 951 | break; 952 | case 22: 953 | #line 117 "parse.y" 954 | { yygotominor.yy1 = new ExprItem(TK_STAR, &yymsp[0].minor.yy0); } 955 | #line 955 "parse.c" 956 | break; 957 | case 23: 958 | #line 119 "parse.y" 959 | { 960 | yygotominor.yy58 = new ExprList(); 961 | yygotominor.yy58->AddExprItem(yymsp[0].minor.yy1); 962 | } 963 | #line 963 "parse.c" 964 | break; 965 | case 24: 966 | #line 123 "parse.y" 967 | { 968 | yygotominor.yy58 = yymsp[-2].minor.yy58->AddExprItem(yymsp[0].minor.yy1); 969 | } 970 | #line 970 "parse.c" 971 | /* No destructor defined for COMMA */ 972 | break; 973 | case 25: 974 | #line 128 "parse.y" 975 | {yygotominor.yy78 = yymsp[0].minor.yy0;} 976 | #line 976 "parse.c" 977 | /* No destructor defined for FROM */ 978 | break; 979 | case 26: 980 | #line 133 "parse.y" 981 | { yygotominor.yy1 = nullptr; } 982 | #line 982 "parse.c" 983 | break; 984 | case 27: 985 | #line 134 "parse.y" 986 | { yygotominor.yy1 = yymsp[0].minor.yy1; } 987 | #line 987 "parse.c" 988 | /* No destructor defined for WHERE */ 989 | break; 990 | case 28: 991 | #line 139 "parse.y" 992 | { yygotominor.yy3 = nullptr; } 993 | #line 993 "parse.c" 994 | break; 995 | case 29: 996 | #line 140 "parse.y" 997 | { yygotominor.yy3 = new GroupOpt(&yymsp[0].minor.yy0); } 998 | #line 998 "parse.c" 999 | /* No destructor defined for GROUP */ 1000 | /* No destructor defined for BY */ 1001 | break; 1002 | case 30: 1003 | #line 145 "parse.y" 1004 | { yygotominor.yy126 = nullptr; } 1005 | #line 1005 "parse.c" 1006 | break; 1007 | case 31: 1008 | #line 146 "parse.y" 1009 | { yygotominor.yy126 = new LimitOpt(&yymsp[0].minor.yy0); } 1010 | #line 1010 "parse.c" 1011 | /* No destructor defined for LIMIT */ 1012 | break; 1013 | case 32: 1014 | #line 147 "parse.y" 1015 | { yygotominor.yy126 = new LimitOpt(&yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } 1016 | #line 1016 "parse.c" 1017 | /* No destructor defined for LIMIT */ 1018 | /* No destructor defined for COMMA */ 1019 | break; 1020 | case 33: 1021 | #line 158 "parse.y" 1022 | { yygotominor.yy1 = new ExprItem(TK_LT, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1023 | #line 1023 "parse.c" 1024 | /* No destructor defined for LT */ 1025 | break; 1026 | case 34: 1027 | #line 159 "parse.y" 1028 | { yygotominor.yy1 = new ExprItem(TK_LE, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1029 | #line 1029 "parse.c" 1030 | /* No destructor defined for LE */ 1031 | break; 1032 | case 35: 1033 | #line 160 "parse.y" 1034 | { yygotominor.yy1 = new ExprItem(TK_GT, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1035 | #line 1035 "parse.c" 1036 | /* No destructor defined for GT */ 1037 | break; 1038 | case 36: 1039 | #line 161 "parse.y" 1040 | { yygotominor.yy1 = new ExprItem(TK_GE, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1041 | #line 1041 "parse.c" 1042 | /* No destructor defined for GE */ 1043 | break; 1044 | case 37: 1045 | #line 162 "parse.y" 1046 | { yygotominor.yy1 = new ExprItem(TK_EQ, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1047 | #line 1047 "parse.c" 1048 | /* No destructor defined for EQ */ 1049 | break; 1050 | case 38: 1051 | #line 163 "parse.y" 1052 | { yygotominor.yy1 = new ExprItem(TK_NE, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1053 | #line 1053 "parse.c" 1054 | /* No destructor defined for NE */ 1055 | break; 1056 | case 39: 1057 | #line 164 "parse.y" 1058 | { yygotominor.yy1 = new ExprItem(TK_LIKE, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), yymsp[0].minor.yy1); } 1059 | #line 1059 "parse.c" 1060 | /* No destructor defined for LIKE */ 1061 | break; 1062 | case 40: 1063 | #line 165 "parse.y" 1064 | { yygotominor.yy1 = new ExprItem(TK_ISNOTNULL, new ExprItem(TK_ID, &yymsp[-3].minor.yy0), nullptr); } 1065 | #line 1065 "parse.c" 1066 | /* No destructor defined for IS */ 1067 | /* No destructor defined for NOT */ 1068 | /* No destructor defined for NULL */ 1069 | break; 1070 | case 41: 1071 | #line 166 "parse.y" 1072 | { yygotominor.yy1 = new ExprItem(TK_ISNULL, new ExprItem(TK_ID, &yymsp[-2].minor.yy0), nullptr); } 1073 | #line 1073 "parse.c" 1074 | /* No destructor defined for IS */ 1075 | /* No destructor defined for NULL */ 1076 | break; 1077 | case 42: 1078 | #line 168 "parse.y" 1079 | { yygotominor.yy1 = new ExprItem(TK_GT, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1080 | #line 1080 "parse.c" 1081 | /* No destructor defined for LT */ 1082 | break; 1083 | case 43: 1084 | #line 169 "parse.y" 1085 | { yygotominor.yy1 = new ExprItem(TK_GE, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1086 | #line 1086 "parse.c" 1087 | /* No destructor defined for LE */ 1088 | break; 1089 | case 44: 1090 | #line 170 "parse.y" 1091 | { yygotominor.yy1 = new ExprItem(TK_LT, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1092 | #line 1092 "parse.c" 1093 | /* No destructor defined for GT */ 1094 | break; 1095 | case 45: 1096 | #line 171 "parse.y" 1097 | { yygotominor.yy1 = new ExprItem(TK_LE, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1098 | #line 1098 "parse.c" 1099 | /* No destructor defined for GE */ 1100 | break; 1101 | case 46: 1102 | #line 172 "parse.y" 1103 | { yygotominor.yy1 = new ExprItem(TK_EQ, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1104 | #line 1104 "parse.c" 1105 | /* No destructor defined for EQ */ 1106 | break; 1107 | case 47: 1108 | #line 173 "parse.y" 1109 | { yygotominor.yy1 = new ExprItem(TK_NE, new ExprItem(TK_ID, &yymsp[0].minor.yy0), yymsp[-2].minor.yy1); } 1110 | #line 1110 "parse.c" 1111 | /* No destructor defined for NE */ 1112 | break; 1113 | case 48: 1114 | #line 175 "parse.y" 1115 | { yygotominor.yy1 = new ExprItem(TK_AND, yymsp[-2].minor.yy1, yymsp[0].minor.yy1); } 1116 | #line 1116 "parse.c" 1117 | /* No destructor defined for AND */ 1118 | break; 1119 | case 49: 1120 | #line 180 "parse.y" 1121 | { yygotominor.yy1 = new ExprItem(TK_INTEGER, &yymsp[0].minor.yy0); } 1122 | #line 1122 "parse.c" 1123 | break; 1124 | case 50: 1125 | #line 181 "parse.y" 1126 | { yygotominor.yy1 = new ExprItem(TK_DOUBLE, &yymsp[0].minor.yy0); } 1127 | #line 1127 "parse.c" 1128 | break; 1129 | case 51: 1130 | #line 182 "parse.y" 1131 | { yygotominor.yy1 = new ExprItem(TK_INTEGER, &yymsp[0].minor.yy0); } 1132 | #line 1132 "parse.c" 1133 | /* No destructor defined for PLUS */ 1134 | break; 1135 | case 52: 1136 | #line 183 "parse.y" 1137 | { yygotominor.yy1 = new ExprItem(TK_DOUBLE, &yymsp[0].minor.yy0); } 1138 | #line 1138 "parse.c" 1139 | /* No destructor defined for PLUS */ 1140 | break; 1141 | case 53: 1142 | #line 184 "parse.y" 1143 | { yygotominor.yy1 = new ExprItem(TK_UINTEGER, &yymsp[0].minor.yy0); } 1144 | #line 1144 "parse.c" 1145 | /* No destructor defined for MINUS */ 1146 | break; 1147 | case 54: 1148 | #line 185 "parse.y" 1149 | { yygotominor.yy1 = new ExprItem(TK_UDOUBLE, &yymsp[0].minor.yy0); } 1150 | #line 1150 "parse.c" 1151 | /* No destructor defined for MINUS */ 1152 | break; 1153 | case 55: 1154 | #line 186 "parse.y" 1155 | { yygotominor.yy1 = new ExprItem(TK_STRING, &yymsp[0].minor.yy0); } 1156 | #line 1156 "parse.c" 1157 | break; 1158 | }; 1159 | yygoto = yyRuleInfo[yyruleno].lhs; 1160 | yysize = yyRuleInfo[yyruleno].nrhs; 1161 | yypParser->yyidx -= yysize; 1162 | yyact = yy_find_reduce_action(yypParser,yygoto); 1163 | if( yyact < YYNSTATE ){ 1164 | yy_shift(yypParser,yyact,yygoto,&yygotominor); 1165 | }else if( yyact == YYNSTATE + YYNRULE + 1 ){ 1166 | yy_accept(yypParser); 1167 | } 1168 | } 1169 | 1170 | /* 1171 | ** The following code executes when the parse fails 1172 | */ 1173 | static void yy_parse_failed( 1174 | yyParser *yypParser /* The parser */ 1175 | ){ 1176 | mydbParseARG_FETCH; 1177 | #ifndef NDEBUG 1178 | if( yyTraceFILE ){ 1179 | fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); 1180 | } 1181 | #endif 1182 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 1183 | /* Here code is inserted which will be executed whenever the 1184 | ** parser fails */ 1185 | mydbParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 1186 | } 1187 | 1188 | /* 1189 | ** The following code executes when a syntax error first occurs. 1190 | */ 1191 | static void yy_syntax_error( 1192 | yyParser *yypParser, /* The parser */ 1193 | int yymajor, /* The major type of the error token */ 1194 | YYMINORTYPE yyminor /* The minor type of the error token */ 1195 | ){ 1196 | mydbParseARG_FETCH; 1197 | #define TOKEN (yyminor.yy0) 1198 | #line 12 "parse.y" 1199 | 1200 | pParse->SetError(TOKEN.pos_); 1201 | 1202 | #line 1202 "parse.c" 1203 | mydbParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 1204 | } 1205 | 1206 | /* 1207 | ** The following is executed when the parser accepts 1208 | */ 1209 | static void yy_accept( 1210 | yyParser *yypParser /* The parser */ 1211 | ){ 1212 | mydbParseARG_FETCH; 1213 | #ifndef NDEBUG 1214 | if( yyTraceFILE ){ 1215 | fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); 1216 | } 1217 | #endif 1218 | while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); 1219 | /* Here code is inserted which will be executed whenever the 1220 | ** parser accepts */ 1221 | mydbParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ 1222 | } 1223 | 1224 | /* The main parser program. 1225 | ** The first argument is a pointer to a structure obtained from 1226 | ** "mydbParseAlloc" which describes the current state of the parser. 1227 | ** The second argument is the major token number. The third is 1228 | ** the minor token. The fourth optional argument is whatever the 1229 | ** user wants (and specified in the grammar) and is available for 1230 | ** use by the action routines. 1231 | ** 1232 | ** Inputs: 1233 | **
    1234 | **
  • A pointer to the parser (an opaque structure.) 1235 | **
  • The major token number. 1236 | **
  • The minor token number. 1237 | **
  • An option argument of a grammar-specified type. 1238 | **
1239 | ** 1240 | ** Outputs: 1241 | ** None. 1242 | */ 1243 | void mydbParse( 1244 | void *yyp, /* The parser */ 1245 | int yymajor, /* The major token code number */ 1246 | mydbParseTOKENTYPE yyminor /* The value for the token */ 1247 | mydbParseARG_PDECL /* Optional %extra_argument parameter */ 1248 | ){ 1249 | YYMINORTYPE yyminorunion; 1250 | int yyact; /* The parser action. */ 1251 | int yyendofinput; /* True if we are at the end of input */ 1252 | int yyerrorhit = 0; /* True if yymajor has invoked an error */ 1253 | yyParser *yypParser; /* The parser */ 1254 | 1255 | /* (re)initialize the parser, if necessary */ 1256 | yypParser = (yyParser*)yyp; 1257 | if( yypParser->yyidx<0 ){ 1258 | if( yymajor==0 ) return; 1259 | yypParser->yyidx = 0; 1260 | yypParser->yyerrcnt = -1; 1261 | yypParser->yystack[0].stateno = 0; 1262 | yypParser->yystack[0].major = 0; 1263 | } 1264 | yyminorunion.yy0 = yyminor; 1265 | yyendofinput = (yymajor==0); 1266 | mydbParseARG_STORE; 1267 | 1268 | #ifndef NDEBUG 1269 | if( yyTraceFILE ){ 1270 | fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); 1271 | } 1272 | #endif 1273 | 1274 | do{ 1275 | yyact = yy_find_shift_action(yypParser,yymajor); 1276 | if( yyactyyerrcnt--; 1279 | if( yyendofinput && yypParser->yyidx>=0 ){ 1280 | yymajor = 0; 1281 | }else{ 1282 | yymajor = YYNOCODE; 1283 | } 1284 | }else if( yyact < YYNSTATE + YYNRULE ){ 1285 | yy_reduce(yypParser,yyact-YYNSTATE); 1286 | }else if( yyact == YY_ERROR_ACTION ){ 1287 | int yymx; 1288 | #ifndef NDEBUG 1289 | if( yyTraceFILE ){ 1290 | fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); 1291 | } 1292 | #endif 1293 | #ifdef YYERRORSYMBOL 1294 | /* A syntax error has occurred. 1295 | ** The response to an error depends upon whether or not the 1296 | ** grammar defines an error token "ERROR". 1297 | ** 1298 | ** This is what we do if the grammar does define ERROR: 1299 | ** 1300 | ** * Call the %syntax_error function. 1301 | ** 1302 | ** * Begin popping the stack until we enter a state where 1303 | ** it is legal to shift the error symbol, then shift 1304 | ** the error symbol. 1305 | ** 1306 | ** * Set the error count to three. 1307 | ** 1308 | ** * Begin accepting and shifting new tokens. No new error 1309 | ** processing will occur until three tokens have been 1310 | ** shifted successfully. 1311 | ** 1312 | */ 1313 | if( yypParser->yyerrcnt<0 ){ 1314 | yy_syntax_error(yypParser,yymajor,yyminorunion); 1315 | } 1316 | yymx = yypParser->yystack[yypParser->yyidx].major; 1317 | if( yymx==YYERRORSYMBOL || yyerrorhit ){ 1318 | #ifndef NDEBUG 1319 | if( yyTraceFILE ){ 1320 | fprintf(yyTraceFILE,"%sDiscard input token %s\n", 1321 | yyTracePrompt,yyTokenName[yymajor]); 1322 | } 1323 | #endif 1324 | yy_destructor(yymajor,&yyminorunion); 1325 | yymajor = YYNOCODE; 1326 | }else{ 1327 | while( 1328 | yypParser->yyidx >= 0 && 1329 | yymx != YYERRORSYMBOL && 1330 | (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE 1331 | ){ 1332 | yy_pop_parser_stack(yypParser); 1333 | } 1334 | if( yypParser->yyidx < 0 || yymajor==0 ){ 1335 | yy_destructor(yymajor,&yyminorunion); 1336 | yy_parse_failed(yypParser); 1337 | yymajor = YYNOCODE; 1338 | }else if( yymx!=YYERRORSYMBOL ){ 1339 | YYMINORTYPE u2; 1340 | u2.YYERRSYMDT = 0; 1341 | yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); 1342 | } 1343 | } 1344 | yypParser->yyerrcnt = 3; 1345 | yyerrorhit = 1; 1346 | #else /* YYERRORSYMBOL is not defined */ 1347 | /* This is what we do if the grammar does not define ERROR: 1348 | ** 1349 | ** * Report an error message, and throw away the input token. 1350 | ** 1351 | ** * If the input token is $, then fail the parse. 1352 | ** 1353 | ** As before, subsequent error messages are suppressed until 1354 | ** three input tokens have been successfully shifted. 1355 | */ 1356 | if( yypParser->yyerrcnt<=0 ){ 1357 | yy_syntax_error(yypParser,yymajor,yyminorunion); 1358 | } 1359 | yypParser->yyerrcnt = 3; 1360 | yy_destructor(yymajor,&yyminorunion); 1361 | if( yyendofinput ){ 1362 | yy_parse_failed(yypParser); 1363 | } 1364 | yymajor = YYNOCODE; 1365 | #endif 1366 | }else{ 1367 | yy_accept(yypParser); 1368 | yymajor = YYNOCODE; 1369 | } 1370 | }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); 1371 | return; 1372 | } 1373 | -------------------------------------------------------------------------------- /MyBase/parse.h: -------------------------------------------------------------------------------- 1 | #define TK_FUNC 1 2 | #define TK_ILLEGAL 2 3 | #define TK_SPACE 3 4 | #define TK_COMMENT 4 5 | #define TK_SHOW 5 6 | #define TK_TABLES 6 7 | #define TK_SEMI 7 8 | #define TK_COLUMNS 8 9 | #define TK_FROM 9 10 | #define TK_ID 10 11 | #define TK_DROP 11 12 | #define TK_TABLE 12 13 | #define TK_CREATE 13 14 | #define TK_LP 14 15 | #define TK_RP 15 16 | #define TK_INT_TYPE 16 17 | #define TK_DOUBLE_TYPE 17 18 | #define TK_STRING_TYPE 18 19 | #define TK_COMMA 19 20 | #define TK_DELETE 20 21 | #define TK_INSERT 21 22 | #define TK_INTO 22 23 | #define TK_VALUES 23 24 | #define TK_SELECT 24 25 | #define TK_STAR 25 26 | #define TK_WHERE 26 27 | #define TK_GROUP 27 28 | #define TK_BY 28 29 | #define TK_LIMIT 29 30 | #define TK_INTEGER 30 31 | #define TK_AND 31 32 | #define TK_EQ 32 33 | #define TK_NE 33 34 | #define TK_GT 34 35 | #define TK_GE 35 36 | #define TK_LT 36 37 | #define TK_LE 37 38 | #define TK_LIKE 38 39 | #define TK_IS 39 40 | #define TK_NOT 40 41 | #define TK_NULL 41 42 | #define TK_ISNOTNULL 42 43 | #define TK_ISNULL 43 44 | #define TK_DOUBLE 44 45 | #define TK_PLUS 45 46 | #define TK_MINUS 46 47 | #define TK_UINTEGER 47 48 | #define TK_UDOUBLE 48 49 | #define TK_STRING 49 50 | -------------------------------------------------------------------------------- /MyBase/query.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/query.cpp -------------------------------------------------------------------------------- /MyBase/query.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/query.h -------------------------------------------------------------------------------- /MyBase/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/resource.h -------------------------------------------------------------------------------- /MyBase/result_field.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/result_field.h -------------------------------------------------------------------------------- /MyBase/sql_parser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2019 ZhangQuan 3 | ** 4 | ** This program is free software; you can redistribute it and/or 5 | ** modify it under the terms of the GNU General Public 6 | ** License as published by the Free Software Foundation; either 7 | ** version 3 of the License, or (at your option) any later version. 8 | ** 9 | ** Author contact information: 10 | ** zhangqhn@foxmail.com 11 | */ 12 | 13 | #include "sql_parser.h" 14 | 15 | SQLParser::SQLParser() 16 | { 17 | cmdType_ = SQLType::None; 18 | isError_ = false; 19 | errPos_ = -1; 20 | } 21 | SQLParser::~SQLParser() 22 | { 23 | 24 | } 25 | 26 | int SQLParser::GetErrPos() const 27 | { 28 | return errPos_; 29 | } 30 | 31 | bool SQLParser::GetError() const 32 | { 33 | return isError_; 34 | } 35 | 36 | void SQLParser::SetError(int errPos) 37 | { 38 | this->isError_ = true; 39 | this->errPos_ = errPos; 40 | } 41 | 42 | void SQLParser::SetShowTables() 43 | { 44 | this->cmdType_ = SQLType::ShowTables; 45 | } 46 | void SQLParser::SetShowTableColumns(Token* pTab) 47 | { 48 | this->cmdType_ = SQLType::ShowTableColumns; 49 | this->tabName_ = std::string(pTab->str_, pTab->len_); 50 | } 51 | void SQLParser::SetCreateTable(Token* pTab, ColumnList* pColList) 52 | { 53 | this->cmdType_ = SQLType::CreateTable; 54 | this->tabName_ = std::string(pTab->str_, pTab->len_); 55 | this->createTableParam_.pColList_ = pColList; 56 | } 57 | void SQLParser::SetDropTable(Token* pTab) 58 | { 59 | this->cmdType_ = SQLType::DropTable; 60 | this->tabName_ = std::string(pTab->str_, pTab->len_); 61 | } 62 | void SQLParser::SetDelete(Token* pTab, ExprItem* pCondition) 63 | { 64 | this->cmdType_ = SQLType::Delete; 65 | this->tabName_ = std::string(pTab->str_, pTab->len_); 66 | this->deleteParam_.pCondition_ = pCondition; 67 | } 68 | void SQLParser::SetQuery(ExprList* pTargetList, Token* pTab, ExprItem* pCondition, GroupOpt* pGroup, LimitOpt* pLimit) 69 | { 70 | this->cmdType_ = SQLType::Query; 71 | this->tabName_ = std::string(pTab->str_, pTab->len_); 72 | this->queryParam_.pTargetList_ = pTargetList; 73 | this->queryParam_.pCondition_ = pCondition; 74 | this->queryParam_.pGroup_ = pGroup; 75 | this->queryParam_.pLimit_ = pLimit; 76 | } 77 | void SQLParser::SetInsert(Token* pTab, ExprList* pNameList, ExprList* pValList) 78 | { 79 | this->cmdType_ = SQLType::Insert; 80 | this->tabName_ = std::string(pTab->str_, pTab->len_); 81 | this->insertParam_.pNameList_ = pNameList; 82 | this->insertParam_.pValList_ = pValList; 83 | } 84 | 85 | const std::string& SQLParser::GetTableName() const 86 | { 87 | return tabName_; 88 | } 89 | 90 | const CreateTableParam* SQLParser::GetCreateTableParam() const 91 | { 92 | return &createTableParam_; 93 | } 94 | const DeleteParam* SQLParser::GetDeleteParam() const 95 | { 96 | return &deleteParam_; 97 | } 98 | const QueryParam* SQLParser::GetQueryParam() const 99 | { 100 | return &queryParam_; 101 | } 102 | const InsertParam* SQLParser::GetInsertParam() const 103 | { 104 | return &insertParam_; 105 | } 106 | 107 | int32_t SQLParser::GetCmdType() const 108 | { 109 | return cmdType_; 110 | } 111 | -------------------------------------------------------------------------------- /MyBase/sql_parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include "sql_part.h" 15 | #include "parse.h" 16 | 17 | class CreateTableParam 18 | { 19 | public: 20 | ColumnList* pColList_; 21 | 22 | CreateTableParam() 23 | { 24 | this->pColList_ = nullptr; 25 | } 26 | 27 | ~CreateTableParam() 28 | { 29 | if (this->pColList_ != nullptr) 30 | delete this->pColList_; 31 | } 32 | }; 33 | 34 | class DeleteParam 35 | { 36 | public: 37 | ExprItem* pCondition_; 38 | 39 | DeleteParam() 40 | { 41 | this->pCondition_ = nullptr; 42 | } 43 | 44 | ~DeleteParam() 45 | { 46 | if (this->pCondition_ != nullptr) 47 | delete this->pCondition_; 48 | } 49 | }; 50 | 51 | class QueryParam 52 | { 53 | public: 54 | ExprList* pTargetList_; 55 | ExprItem* pCondition_; 56 | GroupOpt* pGroup_; 57 | LimitOpt* pLimit_; 58 | 59 | QueryParam() 60 | { 61 | this->pTargetList_ = nullptr; 62 | this->pCondition_ = nullptr; 63 | this->pGroup_ = nullptr; 64 | this->pLimit_ = nullptr; 65 | } 66 | 67 | ~QueryParam() 68 | { 69 | if (this->pTargetList_ != nullptr) 70 | delete this->pTargetList_; 71 | 72 | if (this->pCondition_ != nullptr) 73 | delete this->pCondition_; 74 | 75 | if (this->pGroup_ != nullptr) 76 | delete this->pGroup_; 77 | 78 | if (this->pLimit_ != nullptr) 79 | delete this->pLimit_; 80 | } 81 | }; 82 | 83 | class InsertParam 84 | { 85 | public: 86 | ExprList* pNameList_; 87 | ExprList* pValList_; 88 | 89 | InsertParam() 90 | { 91 | this->pNameList_ = nullptr; 92 | this->pValList_ = nullptr; 93 | } 94 | 95 | ~InsertParam() 96 | { 97 | if (this->pNameList_ != nullptr) 98 | delete this->pNameList_; 99 | 100 | if (this->pValList_ != nullptr) 101 | delete this->pValList_; 102 | } 103 | }; 104 | 105 | class SQLParser 106 | { 107 | public: 108 | SQLParser(); 109 | ~SQLParser(); 110 | 111 | int GetErrPos() const; 112 | bool GetError() const; 113 | void SetError(int errPos); 114 | 115 | void SetShowTables(); 116 | void SetShowTableColumns(Token* pTab); 117 | void SetCreateTable(Token* pTab, ColumnList* pColList); 118 | void SetDropTable(Token* pTab); 119 | void SetDelete(Token* pTab, ExprItem* pCondition); 120 | void SetQuery(ExprList* pTargetList, Token* pTab, ExprItem* pCondition, GroupOpt* pGroup, LimitOpt* pLimit); 121 | void SetInsert(Token* pTab, ExprList* pNameList, ExprList* pValList); 122 | 123 | enum SQLType 124 | { 125 | None = 0, 126 | ShowTables = 1, 127 | ShowTableColumns = 2, 128 | CreateTable = 3, 129 | DropTable = 4, 130 | Delete = 5, 131 | Query = 6, 132 | Insert = 7, 133 | }; 134 | 135 | const std::string& GetTableName() const; 136 | 137 | const CreateTableParam* GetCreateTableParam() const; 138 | const DeleteParam* GetDeleteParam() const; 139 | const QueryParam* GetQueryParam() const; 140 | const InsertParam* GetInsertParam() const; 141 | int32_t GetCmdType() const; 142 | 143 | private: 144 | int32_t cmdType_; 145 | bool isError_; 146 | int errPos_; 147 | 148 | std::string tabName_; 149 | 150 | CreateTableParam createTableParam_; 151 | DeleteParam deleteParam_; 152 | QueryParam queryParam_; 153 | InsertParam insertParam_; 154 | }; 155 | -------------------------------------------------------------------------------- /MyBase/sql_part.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/sql_part.cpp -------------------------------------------------------------------------------- /MyBase/sql_part.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/sql_part.h -------------------------------------------------------------------------------- /MyBase/sql_tokenize.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/sql_tokenize.cpp -------------------------------------------------------------------------------- /MyBase/sql_tokenize.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/sql_tokenize.h -------------------------------------------------------------------------------- /MyBase/string_tool.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2019 ZhangQuan 3 | ** 4 | ** This program is free software; you can redistribute it and/or 5 | ** modify it under the terms of the GNU General Public 6 | ** License as published by the Free Software Foundation; either 7 | ** version 3 of the License, or (at your option) any later version. 8 | ** 9 | ** Author contact information: 10 | ** zhangqhn@foxmail.com 11 | */ 12 | 13 | #include "string_tool.h" 14 | #include 15 | #include 16 | 17 | 18 | /* 19 | ** This table maps from the first byte of a UTF-8 character to the number 20 | ** of trailing bytes expected. A value '255' indicates that the table key 21 | ** is not a legal first byte for a UTF-8 character. 22 | */ 23 | static const uint8_t xtra_utf8_bytes[256] = { 24 | /* 0xxxxxxx */ 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33 | 34 | /* 10wwwwww */ 35 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 36 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 37 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 38 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 39 | 40 | /* 110yyyyy */ 41 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 42 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 43 | 44 | /* 1110zzzz */ 45 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 46 | 47 | /* 11110yyy */ 48 | 3, 3, 3, 3, 3, 3, 3, 3, 255, 255, 255, 255, 255, 255, 255, 255, 49 | }; 50 | 51 | #define SKIP_UTF8(zIn) { zIn += (xtra_utf8_bytes[*(uint8_t*)zIn] + 1); } 52 | 53 | bool StringTool::Utf8LikeCompare(const char* zPattern, const char* zString, size_t len) 54 | { 55 | int32_t c = 0; 56 | int32_t c2; 57 | 58 | const char* pEnd = zString + len; 59 | 60 | while ((zString < pEnd) && ((c = tolower((uint8_t)*zPattern)) != 0)) 61 | { 62 | switch (c) 63 | { 64 | case '%': 65 | { 66 | while ((c = zPattern[1]) == '%' || c == '_') 67 | { 68 | if (c == '_') 69 | { 70 | if (*zString == 0 || zString >= pEnd) 71 | return false; 72 | SKIP_UTF8(zString); 73 | } 74 | zPattern++; 75 | } 76 | 77 | if (c == 0) 78 | return true; 79 | 80 | c = tolower(c); 81 | while (zString < pEnd && ((c2 = tolower((uint8_t)*zString)) != 0)) 82 | { 83 | while (c2 != 0 && c2 != c) 84 | { 85 | zString++; 86 | c2 = tolower((uint8_t)*zString); 87 | } 88 | if (c2 == 0) 89 | return false; 90 | if (StringTool::Utf8LikeCompare(&zPattern[1], zString, (int32_t)(pEnd - zString))) 91 | return true; 92 | SKIP_UTF8(zString); 93 | } 94 | return false; 95 | } 96 | case '_': 97 | { 98 | if (zString >= pEnd || *zString == 0) 99 | return false; 100 | SKIP_UTF8(zString); 101 | zPattern++; 102 | break; 103 | } 104 | default: 105 | { 106 | if (c != tolower((uint8_t)*zString)) 107 | return false; 108 | zPattern++; 109 | zString++; 110 | break; 111 | } 112 | } 113 | } 114 | 115 | return (*zString == 0 || zString == pEnd) && (*zPattern == 0); 116 | } 117 | -------------------------------------------------------------------------------- /MyBase/string_tool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | 16 | class StringTool 17 | { 18 | public: 19 | static bool Utf8LikeCompare(const char* zPattern, const char* zString, size_t len); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /MyBase/table.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/table.cpp -------------------------------------------------------------------------------- /MyBase/table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "page.h" 20 | #include "dbval.h" 21 | #include "condition.h" 22 | #include "sql_parser.h" 23 | #include "query.h" 24 | #include "arena.h" 25 | 26 | class Table 27 | { 28 | public: 29 | Table(); 30 | ~Table(); 31 | 32 | int Create(const std::string& tabName, const CreateTableParam* pCreateParam, int* pErrPos); 33 | 34 | int Open(const char* pName); 35 | int Close(); 36 | 37 | int Insert(const InsertParam* pInsertParam, int* pErrPos); 38 | int ExecQuery(const QueryParam* pQueryParam, Query** ppQuery, int* pErrPos); 39 | int ExecDelete(const DeleteParam* pDeleteParam, int* pErrPos); 40 | 41 | const std::string& GetTableName() const; 42 | void GetColumnsInfo(std::vector& colVec) const; 43 | 44 | private: 45 | int GetFieldPos(const char* pName); 46 | 47 | int BuildQuery(const QueryParam* pQueryParam, Query** ppQuery, int* pErrPos); 48 | int BuildCondition(const ExprItem* pCondiExpr, Condition* pCondition, int* pErrPos); 49 | 50 | ConditionItem* BuildIntCondition(int fieldPos, int op, int64_t val); 51 | ConditionItem* BuildDoubleCondition(int fieldPos, int op, double val); 52 | ConditionItem* BuildStringCondition(int fieldPos, int op, const std::string& val); 53 | 54 | int BuildTarget(Query* pQuery, bool isGroup, int groupFieldPos, const ExprItem* pTarget); 55 | 56 | void LoadRecord(const uint8_t* pRec, std::vector& recVal); 57 | void CleanPage(DataPage* pPage); 58 | 59 | private: 60 | // No copying allowed 61 | Table(const Table&); 62 | void operator=(const Table&); 63 | 64 | private: 65 | HANDLE fileHandle_; 66 | HANDLE mapHandle_; 67 | LPVOID pBase_; 68 | 69 | std::string tabName_; 70 | std::unordered_map colPosMap_; 71 | 72 | }; 73 | 74 | -------------------------------------------------------------------------------- /MyBase/table_set.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/MyBase/table_set.cpp -------------------------------------------------------------------------------- /MyBase/table_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | ** Copyright (c) 2019 ZhangQuan 4 | ** 5 | ** This program is free software; you can redistribute it and/or 6 | ** modify it under the terms of the GNU General Public 7 | ** License as published by the Free Software Foundation; either 8 | ** version 3 of the License, or (at your option) any later version. 9 | ** 10 | ** Author contact information: 11 | ** zhangqhn@foxmail.com 12 | */ 13 | 14 | #include 15 | #include "table.h" 16 | #include "sql_parser.h" 17 | #include "query.h" 18 | 19 | class TableSet 20 | { 21 | public: 22 | TableSet(); 23 | ~TableSet(); 24 | 25 | int LoadTables(); 26 | 27 | int ShowTables(std::vector& tabVec); 28 | int ShowTableColumns(const std::string& tabName, std::vector& colVec); 29 | int CreateTable(const std::string& tabName, const CreateTableParam* pCreateParam, int* pErrPos); 30 | int DropTable(const std::string& tabName); 31 | int Insert(const std::string& tabName, const InsertParam* pInsertParam, int* pErrPos); 32 | int ExecQuery(const std::string& tabName, const QueryParam* pQueryParam, Query** ppQuery, int* pErrPos); 33 | int Delete(const std::string& tabName, const DeleteParam* pDeleteParam, int* pErrPos); 34 | 35 | private: 36 | Table* GetTable(const char* pName); 37 | 38 | private: 39 | // No copying allowed 40 | TableSet(const TableSet&); 41 | void operator=(const TableSet&); 42 | 43 | private: 44 | std::unordered_map tabSet_; 45 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 什么是MyBase 2 | MyBase是一个数据库实现,大约包含4000行c++代码,它极其简单,确切地说算不上一个数据库。 3 | 仅仅具备数据库的部分特点,但是您可以基于MyBase去实现一些数据库的功能,比如:主键、索引、 4 | B+树的存储、排序、网络等等。 5 | 6 | MyBase的目标是提供一个基本的、简单的数据库实现平台,让软件开发的初学者在学习完 7 | c++ 、 数据结构 、 数据库系统等基础课程后不光能使用数据库还能按照自己的想法实现一个数据库 8 | 9 | # 编译MyBase 10 | MyBase仅支持Windows平台,项目中已经包含vs2017的项目文件,不使用任何第三方的库,直接编译即可。 11 | 其中 parse.h 和 parse.cpp 由Lemon根据语法文件(Lemon\parse.y)生成。 Lemon的介绍见下一节。 12 | 13 | # 关于Lemon 14 | Lemon是Sqlite中对SQL语法分析的工具,更详细的内容请参考Sqlite中的相关部分。本项目使用Sqlite 3.0 对应的Lemon代码。 15 | 若修改了语法文件,只需执行以下步骤即可: 16 | 1. 使用lemon.c 生成一个执行程序,比如:lemon.exe。 17 | 18 | 2. 将语法文件(parse.y) 、 lempar.c 与 lemon.exe 放在同一个目录下。 19 | 20 | 3. 执行 lemon.exe parse.y ,若无错误会生成 parse.h 和 parse.c , 21 | 此时要注意:parse.y中使用了c++的代码,所以需要将parse.c修改为parse.cpp加入项目,否则会编译出错。 22 | 23 | # 运行MyBase 24 | MyBase是服务程序和客户程序的混合,运行后会以运行目录为库目录,读取后缀为 .dat 的文件加入当前系统。 25 | 创建的每个表作为一个独立的文件保存在当前目录下。MyBase的表有固定大小,写满后不会增长。 26 | 27 | MyBase功能列表 28 | 29 | * 打印帮助信息 30 | 31 | help 32 | 33 | * 清屏 34 | 35 | clear 36 | 37 | * 退出 38 | 39 | exit 40 | 41 | * 执行外部的sql文件 42 | 43 | source \ 44 | 45 | * 显示所有的表 46 | 47 | show tables 48 | 49 | * 显示指定表的列信息 50 | 51 | show columns from \ 52 | 53 | * 创建表 54 | 55 | 仅支持 int, double, string 类型 56 | 57 | create table \ (\ int|double|string, ...) 58 | 59 | * 删除表 60 | 61 | drop table \ 62 | 63 | * 插入数据 64 | 65 | insert into \ (\) values (\) 66 | 67 | * 查询数据 68 | 69 | 支持 max, min, sum, avg, count 聚合函数 70 | 71 | select \ from \ [where-expr] [group-by-expr] [limit-expr] 72 | 73 | * 删除数据 74 | 75 | delete from \ [where-expr] 76 | 77 | # 联系我 78 | 79 | 有任何问题欢迎与我联系,zhangqhn@foxmail.com 80 | 81 | 82 | -------------------------------------------------------------------------------- /doc/mybase_user_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangqhn/mybase/277fb10d2cc68b890a854033def02c6ac79d544f/doc/mybase_user_manual.pdf -------------------------------------------------------------------------------- /test/scoreinfo.sql: -------------------------------------------------------------------------------- 1 | insert into scoreinfo(id, name, subject, score) values(10001, '张三', 'C++程序设计', 87.6) 2 | insert into scoreinfo(id, name, subject, score) values(10002, '李四', 'C++程序设计', 92.5) 3 | insert into scoreinfo(id, name, subject, score) values(10003, '王五', 'C++程序设计', 88) 4 | insert into scoreinfo(id, name, subject, score) values(10004, '赵六', 'C++程序设计', 79) 5 | insert into scoreinfo(id, name, subject, score) values(10005, 'Frank', 'C++程序设计', 82) 6 | 7 | insert into scoreinfo(id, name, subject, score) values(10001, '张三', '数据结构', 83.3) 8 | insert into scoreinfo(id, name, subject, score) values(10002, '李四', '数据结构', 85) 9 | insert into scoreinfo(id, name, subject, score) values(10003, '王五', '数据结构', 77.4) 10 | insert into scoreinfo(id, name, subject, score) values(10004, '赵六', '数据结构', 83.8) 11 | insert into scoreinfo(id, name, subject, score) values(10005, 'Frank', '数据结构', 91.5) 12 | 13 | insert into scoreinfo(id, name, subject, score) values(10001, '张三', '数据库系统原理', 84) 14 | insert into scoreinfo(id, name, subject, score) values(10002, '李四', '数据库系统原理', 82) 15 | insert into scoreinfo(id, name, subject, score) values(10003, '王五', '数据库系统原理', 93.2) 16 | insert into scoreinfo(id, name, subject, score) values(10004, '赵六', '数据库系统原理', 81) 17 | insert into scoreinfo(id, name, subject, score) values(10005, 'Frank', '数据库系统原理', 83.7) --------------------------------------------------------------------------------