├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── cfuncs.go ├── example ├── test.txt ├── user_dict.tsv └── user_dict2.tsv ├── go.mod ├── go.sum ├── internal ├── rewindscanner.go └── rewindscanner_test.go ├── kiwi.go ├── kiwi_example_test.go ├── kiwi_test.go ├── postype.go ├── postype_test.go └── scripts └── install_kiwi.bash /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/go/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] Go version (use -bullseye variants on local arm64/Apple Silicon): 1, 1.16, 1.17, 1-bullseye, 1.16-bullseye, 1.17-bullseye, 1-buster, 1.16-buster, 1.17-buster 4 | ARG VARIANT="1.17-bullseye" 5 | FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT} 6 | 7 | # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 8 | ARG NODE_VERSION="none" 9 | RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi 10 | 11 | # [Optional] Uncomment this section to install additional OS packages. 12 | #RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 13 | # && apt-get -y install --no-install-recommends cmake \ 14 | # && apt-get --purge -y remove cmake \ 15 | # && apt autoremove -y \ 16 | # && rm -rf /var/lib/apt/lists/* 17 | 18 | 19 | RUN sh -c "$(curl -fsSL https://starship.rs/install.sh)" -- --yes 20 | 21 | # [Optional] Uncomment the next line to use go get to install anything else you need 22 | RUN su vscode -c "go install mvdan.cc/gofumpt@latest" 23 | 24 | # [Optional] Uncomment this line to install global node packages. 25 | # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/go 3 | { 4 | "name": "Go", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | "args": { 8 | // Update the VARIANT arg to pick a version of Go: 1, 1.16, 1.17 9 | // Append -bullseye or -buster to pin to an OS version. 10 | // Use -bullseye variants on local arm64/Apple Silicon. 11 | "VARIANT": "1.17-bullseye", 12 | // Options 13 | "NODE_VERSION": "none" 14 | } 15 | }, 16 | "runArgs": [ "--init", "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], 17 | 18 | // Set *default* container specific settings.json values on container create. 19 | "settings": { 20 | "go.toolsManagement.checkForUpdates": "local", 21 | "go.useLanguageServer": true, 22 | "go.gopath": "/go", 23 | "go.goroot": "/usr/local/go" 24 | }, 25 | 26 | // Add the IDs of extensions you want installed when the container is created. 27 | "extensions": [ 28 | "golang.Go" 29 | ], 30 | 31 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 32 | // "forwardPorts": [], 33 | 34 | // Use 'postCreateCommand' to run commands after the container is created. 35 | "postCreateCommand": "echo \"eval '$(starship init zsh)'\" >> ~/.zshrc", 36 | 37 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 38 | "remoteUser": "vscode" 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | name: CI 7 | jobs: 8 | test: 9 | strategy: 10 | matrix: 11 | go-version: 12 | - '1.23' 13 | os: 14 | - ubuntu-latest 15 | - macos-latest 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - name: Install Go ${{ matrix.go-version }} 19 | uses: actions/setup-go@v5 20 | with: 21 | go-version: ${{ matrix.go-version }} 22 | - uses: actions/checkout@v4 23 | - run: make install-kiwi 24 | - run: make test 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | .vscode 17 | 18 | __debug_bin 19 | 20 | base/ 21 | .idea/ 22 | models/ 23 | include/ 24 | ModelGenerator/ 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | KIWI_VERSION := v0.21.0 2 | 3 | .PHONY: test 4 | test: base/default.dict 5 | go test ./... 6 | 7 | base/default.dict: 8 | curl -L https://github.com/bab2min/Kiwi/releases/download/$(KIWI_VERSION)/kiwi_model_$(KIWI_VERSION)_base.tgz --output model.tgz 9 | tar --no-same-owner -xzvf model.tgz 10 | rm -f model.tgz 11 | 12 | 13 | .PHONY: install-kiwi 14 | install-kiwi: 15 | bash scripts/install_kiwi.bash $(KIWI_VERSION) 16 | 17 | .PHONY: clean 18 | clean: 19 | rm -f model.tgz 20 | rm -rf ./base 21 | 22 | .PHONY: format 23 | format: 24 | # go install mvdan.cc/gofumpt@latest 25 | gofumpt -l -w . 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kiwigo 2 | 3 | [![CI](https://github.com/codingpot/kiwigo/actions/workflows/ci.yaml/badge.svg)](https://github.com/codingpot/kiwigo/actions/workflows/ci.yaml) 4 | [![Go Reference](https://pkg.go.dev/badge/github.com/codingpot/kiwigo.svg)](https://pkg.go.dev/github.com/codingpot/kiwigo) 5 | 6 | https://github.com/bab2min/Kiwi for go 7 | 8 | ## Dependencies 9 | 10 | - Install Kiwi 11 | 12 | check out how to install Kiwi [here](https://github.com/bab2min/Kiwi#%EC%84%A4%EC%B9%98) 13 | 14 | ### Example script (install using the helper script) 15 | 16 | ```bash 17 | make install-kiwi 18 | ``` 19 | 20 | ### Example script (install from source) 21 | 22 | ```bash 23 | git clone git@github.com:bab2min/Kiwi.git 24 | cd Kiwi 25 | git submodule sync 26 | git submodule update --init --recursive 27 | mkdir build 28 | cd build 29 | cmake -DCMAKE_BUILD_TYPE=Release ../ 30 | make 31 | make install 32 | ldconfig 33 | ``` 34 | -------------------------------------------------------------------------------- /cfuncs.go: -------------------------------------------------------------------------------- 1 | package kiwi 2 | 3 | /* 4 | #cgo LDFLAGS: -l kiwi 5 | 6 | int KiwiReaderBridge(int lineNumber, char *buffer, void *userData) { 7 | int KiwiReaderImpl(int, char*, void*); 8 | return KiwiReaderImpl(lineNumber, buffer, userData); 9 | } 10 | */ 11 | import "C" 12 | -------------------------------------------------------------------------------- /example/test.txt: -------------------------------------------------------------------------------- 1 | 대한민국헌법 2 | 유구한 역사와 전통에 빛나는 우리 대한국민은 3·1운동으로 건립된 대한민국임시정부의 법통과 불의에 항거한 4·19민주이념을 계승하고, 조국의 민주개혁과 평화적 통일의 사명에 입각하여 정의·인도와 동포애로써 민족의 단결을 공고히 하고, 모든 사회적 폐습과 불의를 타파하며, 자율과 조화를 바탕으로 자유민주적 기본질서를 더욱 확고히 하여 정치·경제·사회·문화의 모든 영역에 있어서 각인의 기회를 균등히 하고, 능력을 최고도로 발휘하게 하며, 자유와 권리에 따르는 책임과 의무를 완수하게 하여, 안으로는 국민생활의 균등한 향상을 기하고 밖으로는 항구적인 세계평화와 인류공영에 이바지함으로써 우리들과 우리들의 자손의 안전과 자유와 행복을 영원히 확보할 것을 다짐하면서 1948년 7월 12일에 제정되고 8차에 걸쳐 개정된 헌법을 이제 국회의 의결을 거쳐 국민투표에 의하여 개정한다. 3 | 제1장 총강 4 | 제1조 ① 대한민국은 민주공화국이다. 5 | ②대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다. 6 | 제2조 ① 대한민국의 국민이 되는 요건은 법률로 정한다. 7 | ②국가는 법률이 정하는 바에 의하여 재외국민을 보호할 의무를 진다. 8 | 제3조 대한민국의 영토는 한반도와 그 부속도서로 한다. 9 | 제4조 대한민국은 통일을 지향하며, 자유민주적 기본질서에 입각한 평화적 통일 정책을 수립하고 이를 추진한다. 10 | 제5조 ① 대한민국은 국제평화의 유지에 노력하고 침략적 전쟁을 부인한다. 11 | ②국군은 국가의 안전보장과 국토방위의 신성한 의무를 수행함을 사명으로 하며, 그 정치적 중립성은 준수된다. 12 | 제6조 ① 헌법에 의하여 체결·공포된 조약과 일반적으로 승인된 국제법규는 국내법과 같은 효력을 가진다. 13 | ②외국인은 국제법과 조약이 정하는 바에 의하여 그 지위가 보장된다. 14 | 제7조 ① 공무원은 국민전체에 대한 봉사자이며, 국민에 대하여 책임을 진다. 15 | ②공무원의 신분과 정치적 중립성은 법률이 정하는 바에 의하여 보장된다. 16 | 제8조 ① 정당의 설립은 자유이며, 복수정당제는 보장된다. 17 | ②정당은 그 목적·조직과 활동이 민주적이어야 하며, 국민의 정치적 의사형성에 참여하는데 필요한 조직을 가져야 한다. 18 | ③정당은 법률이 정하는 바에 의하여 국가의 보호를 받으며, 국가는 법률이 정하는 바에 의하여 정당운영에 필요한 자금을 보조할 수 있다. 19 | ④정당의 목적이나 활동이 민주적 기본질서에 위배될 때에는 정부는 헌법재판소에 그 해산을 제소할 수 있고, 정당은 헌법재판소의 심판에 의하여 해산된다. 20 | 제9조 국가는 전통문화의 계승·발전과 민족문화의 창달에 노력하여야 한다. 21 | 22 | 제2장 국민의 권리와 의무 23 | 제10조 모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 24 | 제11조 ① 모든 국민은 법 앞에 평등하다. 누구든지 성별·종교 또는 사회적 신분에 의하여 정치적·경제적·사회적·문화적 생활의 모든 영역에 있어서 차별을 받지 아니한다. 25 | ②사회적 특수계급의 제도는 인정되지 아니하며, 어떠한 형태로도 이를 창설할 수 없다. 26 | ③훈장등의 영전은 이를 받은 자에게만 효력이 있고, 어떠한 특권도 이에 따르지 아니한다. 27 | 제12조 ① 모든 국민은 신체의 자유를 가진다. 누구든지 법률에 의하지 아니하고는 체포·구속·압수·수색 또는 심문을 받지 아니하며, 법률과 적법한 절차에 의하지 아니하고는 처벌·보안처분 또는 강제노역을 받지 아니한다. 28 | ②모든 국민은 고문을 받지 아니하며, 형사상 자기에게 불리한 진술을 강요당하지 아니한다. 29 | ③체포·구속·압수 또는 수색을 할 때에는 적법한 절차에 따라 검사의 신청에 의하여 법관이 발부한 영장을 제시하여야 한다. 다만, 현행범인인 경우와 장기 3년 이상의 형에 해당하는 죄를 범하고 도피 또는 증거인멸의 염려가 있을 때에는 사후에 영장을 청구할 수 있다. 30 | ④누구든지 체포 또는 구속을 당한 때에는 즉시 변호인의 조력을 받을 권리를 가진다. 다만, 형사피고인이 스스로 변호인을 구할 수 없을 때에는 법률이 정하는 바에 의하여 국가가 변호인을 붙인다. 31 | ⑤누구든지 체포 또는 구속의 이유와 변호인의 조력을 받을 권리가 있음을 고지받지 아니하고는 체포 또는 구속을 당하지 아니한다. 체포 또는 구속을 당한 자의 가족등 법률이 정하는 자에게는 그 이유와 일시·장소가 지체없이 통지되어야 한다. 32 | ⑥누구든지 체포 또는 구속을 당한 때에는 적부의 심사를 법원에 청구할 권리를 가진다. 33 | ⑦피고인의 자백이 고문·폭행·협박·구속의 부당한 장기화 또는 기망 기타의 방법에 의하여 자의로 진술된 것이 아니라고 인정될 때 또는 정식재판에 있어서 피고인의 자백이 그에게 불리한 유일한 증거일 때에는 이를 유죄의 증거로 삼거나 이를 이유로 처벌할 수 없다. 34 | 제13조 ① 모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며, 동일한 범죄에 대하여 거듭 처벌받지 아니한다. 35 | ②모든 국민은 소급입법에 의하여 참정권의 제한을 받거나 재산권을 박탈당하지 아니한다. 36 | ③모든 국민은 자기의 행위가 아닌 친족의 행위로 인하여 불이익한 처우를 받지 아니한다. 37 | 제14조 모든 국민은 거주·이전의 자유를 가진다. 38 | 제15조 모든 국민은 직업선택의 자유를 가진다. 39 | 제16조 모든 국민은 주거의 자유를 침해받지 아니한다. 주거에 대한 압수나 수색을 할 때에는 검사의 신청에 의하여 법관이 발부한 영장을 제시하여야 한다. 40 | 제17조 모든 국민은 사생활의 비밀과 자유를 침해받지 아니한다. 41 | 제18조 모든 국민은 통신의 비밀을 침해받지 아니한다. 42 | 제19조 모든 국민은 양심의 자유를 가진다. 43 | 제20조 ① 모든 국민은 종교의 자유를 가진다. 44 | ②국교는 인정되지 아니하며, 종교와 정치는 분리된다. 45 | 제21조 ① 모든 국민은 언론·출판의 자유와 집회·결사의 자유를 가진다. 46 | ②언론·출판에 대한 허가나 검열과 집회·결사에 대한 허가는 인정되지 아니한다. 47 | ③통신·방송의 시설기준과 신문의 기능을 보장하기 위하여 필요한 사항은 법률로 정한다. 48 | ④언론·출판은 타인의 명예나 권리 또는 공중도덕이나 사회윤리를 침해하여서는 아니된다. 언론·출판이 타인의 명예나 권리를 침해한 때에는 피해자는 이에 대한 피해의 배상을 청구할 수 있다. 49 | 제22조 ① 모든 국민은 학문과 예술의 자유를 가진다. 50 | ②저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 51 | 제23조 ① 모든 국민의 재산권은 보장된다. 그 내용과 한계는 법률로 정한다. 52 | ②재산권의 행사는 공공복리에 적합하도록 하여야 한다. 53 | ③공공필요에 의한 재산권의 수용·사용 또는 제한 및 그에 대한 보상은 법률로써 하되, 정당한 보상을 지급하여야 한다. 54 | 제24조 모든 국민은 법률이 정하는 바에 의하여 선거권을 가진다. 55 | 제25조 모든 국민은 법률이 정하는 바에 의하여 공무담임권을 가진다. 56 | 제26조 ① 모든 국민은 법률이 정하는 바에 의하여 국가기관에 문서로 청원할 권리를 가진다. 57 | ②국가는 청원에 대하여 심사할 의무를 진다. 58 | 제27조 ① 모든 국민은 헌법과 법률이 정한 법관에 의하여 법률에 의한 재판을 받을 권리를 가진다. 59 | ②군인 또는 군무원이 아닌 국민은 대한민국의 영역안에서는 중대한 군사상 기밀·초병·초소·유독음식물공급·포로·군용물에 관한 죄중 법률이 정한 경우와 비상계엄이 선포된 경우를 제외하고는 군사법원의 재판을 받지 아니한다. 60 | ③모든 국민은 신속한 재판을 받을 권리를 가진다. 형사피고인은 상당한 이유가 없는 한 지체없이 공개재판을 받을 권리를 가진다. 61 | ④형사피고인은 유죄의 판결이 확정될 때까지는 무죄로 추정된다. 62 | ⑤형사피해자는 법률이 정하는 바에 의하여 당해 사건의 재판절차에서 진술할 수 있다. 63 | 제28조 형사피의자 또는 형사피고인으로서 구금되었던 자가 법률이 정하는 불기소처분을 받거나 무죄판결을 받은 때에는 법률이 정하는 바에 의하여 국가에 정당한 보상을 청구할 수 있다. 64 | 제29조 ① 공무원의 직무상 불법행위로 손해를 받은 국민은 법률이 정하는 바에 의하여 국가 또는 공공단체에 정당한 배상을 청구할 수 있다. 이 경우 공무원 자신의 책임은 면제되지 아니한다. 65 | ②군인·군무원·경찰공무원 기타 법률이 정하는 자가 전투·훈련등 직무집행과 관련하여 받은 손해에 대하여는 법률이 정하는 보상외에 국가 또는 공공단체에 공무원의 직무상 불법행위로 인한 배상은 청구할 수 없다. 66 | 제30조 타인의 범죄행위로 인하여 생명·신체에 대한 피해를 받은 국민은 법률이 정하는 바에 의하여 국가로부터 구조를 받을 수 있다. 67 | 제31조 ① 모든 국민은 능력에 따라 균등하게 교육을 받을 권리를 가진다. 68 | ②모든 국민은 그 보호하는 자녀에게 적어도 초등교육과 법률이 정하는 교육을 받게 할 의무를 진다. 69 | ③의무교육은 무상으로 한다. 70 | ④교육의 자주성·전문성·정치적 중립성 및 대학의 자율성은 법률이 정하는 바에 의하여 보장된다. 71 | ⑤국가는 평생교육을 진흥하여야 한다. 72 | ⑥학교교육 및 평생교육을 포함한 교육제도와 그 운영, 교육재정 및 교원의 지위에 관한 기본적인 사항은 법률로 정한다. 73 | 제32조 ① 모든 국민은 근로의 권리를 가진다. 국가는 사회적·경제적 방법으로 근로자의 고용의 증진과 적정임금의 보장에 노력하여야 하며, 법률이 정하는 바에 의하여 최저임금제를 시행하여야 한다. 74 | ②모든 국민은 근로의 의무를 진다. 국가는 근로의 의무의 내용과 조건을 민주주의원칙에 따라 법률로 정한다. 75 | ③근로조건의 기준은 인간의 존엄성을 보장하도록 법률로 정한다. 76 | ④여자의 근로는 특별한 보호를 받으며, 고용·임금 및 근로조건에 있어서 부당한 차별을 받지 아니한다. 77 | ⑤연소자의 근로는 특별한 보호를 받는다. 78 | ⑥국가유공자·상이군경 및 전몰군경의 유가족은 법률이 정하는 바에 의하여 우선적으로 근로의 기회를 부여받는다. 79 | 제33조 ① 근로자는 근로조건의 향상을 위하여 자주적인 단결권·단체교섭권 및 단체행동권을 가진다. 80 | ②공무원인 근로자는 법률이 정하는 자에 한하여 단결권·단체교섭권 및 단체행동권을 가진다. 81 | ③법률이 정하는 주요방위산업체에 종사하는 근로자의 단체행동권은 법률이 정하는 바에 의하여 이를 제한하거나 인정하지 아니할 수 있다. 82 | 제34조 ① 모든 국민은 인간다운 생활을 할 권리를 가진다. 83 | ②국가는 사회보장·사회복지의 증진에 노력할 의무를 진다. 84 | ③국가는 여자의 복지와 권익의 향상을 위하여 노력하여야 한다. 85 | ④국가는 노인과 청소년의 복지향상을 위한 정책을 실시할 의무를 진다. 86 | ⑤신체장애자 및 질병·노령 기타의 사유로 생활능력이 없는 국민은 법률이 정하는 바에 의하여 국가의 보호를 받는다. 87 | ⑥국가는 재해를 예방하고 그 위험으로부터 국민을 보호하기 위하여 노력하여야 한다. 88 | 제35조 ① 모든 국민은 건강하고 쾌적한 환경에서 생활할 권리를 가지며, 국가와 국민은 환경보전을 위하여 노력하여야 한다. 89 | ②환경권의 내용과 행사에 관하여는 법률로 정한다. 90 | ③국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 91 | 제36조 ① 혼인과 가족생활은 개인의 존엄과 양성의 평등을 기초로 성립되고 유지되어야 하며, 국가는 이를 보장한다. 92 | ②국가는 모성의 보호를 위하여 노력하여야 한다. 93 | ③모든 국민은 보건에 관하여 국가의 보호를 받는다. 94 | 제37조 ① 국민의 자유와 권리는 헌법에 열거되지 아니한 이유로 경시되지 아니한다. 95 | ②국민의 모든 자유와 권리는 국가안전보장·질서유지 또는 공공복리를 위하여 필요한 경우에 한하여 법률로써 제한할 수 있으며, 제한하는 경우에도 자유와 권리의 본질적인 내용을 침해할 수 없다. 96 | 제38조 모든 국민은 법률이 정하는 바에 의하여 납세의 의무를 진다. 97 | 제39조 ① 모든 국민은 법률이 정하는 바에 의하여 국방의 의무를 진다. 98 | ②누구든지 병역의무의 이행으로 인하여 불이익한 처우를 받지 아니한다. 99 | 제3장 국회 100 | 제40조 입법권은 국회에 속한다. 101 | 제41조 ① 국회는 국민의 보통·평등·직접·비밀선거에 의하여 선출된 국회의원으로 구성한다. 102 | ②국회의원의 수는 법률로 정하되, 200인 이상으로 한다. 103 | ③국회의원의 선거구와 비례대표제 기타 선거에 관한 사항은 법률로 정한다. 104 | 제42조 국회의원의 임기는 4년으로 한다. 105 | 제43조 국회의원은 법률이 정하는 직을 겸할 수 없다. 106 | 제44조 ① 국회의원은 현행범인인 경우를 제외하고는 회기중 국회의 동의없이 체포 또는 구금되지 아니한다. 107 | ②국회의원이 회기전에 체포 또는 구금된 때에는 현행범인이 아닌 한 국회의 요구가 있으면 회기중 석방된다. 108 | 제45조 국회의원은 국회에서 직무상 행한 발언과 표결에 관하여 국회외에서 책임을 지지 아니한다. 109 | 제46조 ① 국회의원은 청렴의 의무가 있다. 110 | ②국회의원은 국가이익을 우선하여 양심에 따라 직무를 행한다. 111 | ③국회의원은 그 지위를 남용하여 국가·공공단체 또는 기업체와의 계약이나 그 처분에 의하여 재산상의 권리·이익 또는 직위를 취득하거나 타인을 위하여 그 취득을 알선할 수 없다. 112 | 제47조 ① 국회의 정기회는 법률이 정하는 바에 의하여 매년 1회 집회되며, 국회의 임시회는 대통령 또는 국회재적의원 4분의 1 이상의 요구에 의하여 집회된다. 113 | ②정기회의 회기는 100일을, 임시회의 회기는 30일을 초과할 수 없다. 114 | ③대통령이 임시회의 집회를 요구할 때에는 기간과 집회요구의 이유를 명시하여야 한다. 115 | 제48조 국회는 의장 1인과 부의장 2인을 선출한다. 116 | 제49조 국회는 헌법 또는 법률에 특별한 규정이 없는 한 재적의원 과반수의 출석과 출석의원 과반수의 찬성으로 의결한다. 가부동수인 때에는 부결된 것으로 본다. 117 | 제50조 ① 국회의 회의는 공개한다. 다만, 출석의원 과반수의 찬성이 있거나 의장이 국가의 안전보장을 위하여 필요하다고 인정할 때에는 공개하지 아니할 수 있다. 118 | ②공개하지 아니한 회의내용의 공표에 관하여는 법률이 정하는 바에 의한다. 119 | 제51조 국회에 제출된 법률안 기타의 의안은 회기중에 의결되지 못한 이유로 폐기되지 아니한다. 다만, 국회의원의 임기가 만료된 때에는 그러하지 아니하다. 120 | 제52조 국회의원과 정부는 법률안을 제출할 수 있다. 121 | 제53조 ① 국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 122 | ②법률안에 이의가 있을 때에는 대통령은 제1항의 기간내에 이의서를 붙여 국회로 환부하고, 그 재의를 요구할 수 있다. 국회의 폐회중에도 또한 같다. 123 | ③대통령은 법률안의 일부에 대하여 또는 법률안을 수정하여 재의를 요구할 수 없다. 124 | ④재의의 요구가 있을 때에는 국회는 재의에 붙이고, 재적의원과반수의 출석과 출석의원 3분의 2 이상의 찬성으로 전과 같은 의결을 하면 그 법률안은 법률로서 확정된다. 125 | ⑤대통령이 제1항의 기간내에 공포나 재의의 요구를 하지 아니한 때에도 그 법률안은 법률로서 확정된다. 126 | ⑥대통령은 제4항과 제5항의 규정에 의하여 확정된 법률을 지체없이 공포하여야 한다. 제5항에 의하여 법률이 확정된 후 또는 제4항에 의한 확정법률이 정부에 이송된 후 5일 이내에 대통령이 공포하지 아니할 때에는 국회의장이 이를 공포한다. 127 | ⑦법률은 특별한 규정이 없는 한 공포한 날로부터 20일을 경과함으로써 효력을 발생한다. 128 | 제54조 ① 국회는 국가의 예산안을 심의·확정한다. 129 | ②정부는 회계연도마다 예산안을 편성하여 회계연도 개시 90일전까지 국회에 제출하고, 국회는 회계연도 개시 30일전까지 이를 의결하여야 한다. 130 | ③새로운 회계연도가 개시될 때까지 예산안이 의결되지 못한 때에는 정부는 국회에서 예산안이 의결될 때까지 다음의 목적을 위한 경비는 전년도 예산에 준하여 집행할 수 있다. 131 | 1. 헌법이나 법률에 의하여 설치된 기관 또는 시설의 유지·운영 132 | 2. 법률상 지출의무의 이행 133 | 3. 이미 예산으로 승인된 사업의 계속 134 | 제55조 ① 한 회계연도를 넘어 계속하여 지출할 필요가 있을 때에는 정부는 연한을 정하여 계속비로서 국회의 의결을 얻어야 한다. 135 | ②예비비는 총액으로 국회의 의결을 얻어야 한다. 예비비의 지출은 차기국회의 승인을 얻어야 한다. 136 | 제56조 정부는 예산에 변경을 가할 필요가 있을 때에는 추가경정예산안을 편성하여 국회에 제출할 수 있다. 137 | 제57조 국회는 정부의 동의없이 정부가 제출한 지출예산 각항의 금액을 증가하거나 새 비목을 설치할 수 없다. 138 | 제58조 국채를 모집하거나 예산외에 국가의 부담이 될 계약을 체결하려 할 때에는 정부는 미리 국회의 의결을 얻어야 한다. 139 | 제59조 조세의 종목과 세율은 법률로 정한다. 140 | 제60조 ① 국회는 상호원조 또는 안전보장에 관한 조약, 중요한 국제조직에 관한 조약, 우호통상항해조약, 주권의 제약에 관한 조약, 강화조약, 국가나 국민에게 중대한 재정적 부담을 지우는 조약 또는 입법사항에 관한 조약의 체결·비준에 대한 동의권을 가진다. 141 | ②국회는 선전포고, 국군의 외국에의 파견 또는 외국군대의 대한민국 영역안에서의 주류에 대한 동의권을 가진다. 142 | 제61조 ① 국회는 국정을 감사하거나 특정한 국정사안에 대하여 조사할 수 있으며, 이에 필요한 서류의 제출 또는 증인의 출석과 증언이나 의견의 진술을 요구할 수 있다. 143 | ②국정감사 및 조사에 관한 절차 기타 필요한 사항은 법률로 정한다. 144 | 제62조 ① 국무총리·국무위원 또는 정부위원은 국회나 그 위원회에 출석하여 국정처리상황을 보고하거나 의견을 진술하고 질문에 응답할 수 있다. 145 | ②국회나 그 위원회의 요구가 있을 때에는 국무총리·국무위원 또는 정부위원은 출석·답변하여야 하며, 국무총리 또는 국무위원이 출석요구를 받은 때에는 국무위원 또는 정부위원으로 하여금 출석·답변하게 할 수 있다. 146 | 제63조 ① 국회는 국무총리 또는 국무위원의 해임을 대통령에게 건의할 수 있다. 147 | ②제1항의 해임건의는 국회재적의원 3분의 1 이상의 발의에 의하여 국회재적의원 과반수의 찬성이 있어야 한다. 148 | 제64조 ① 국회는 법률에 저촉되지 아니하는 범위안에서 의사와 내부규율에 관한 규칙을 제정할 수 있다. 149 | ②국회는 의원의 자격을 심사하며, 의원을 징계할 수 있다. 150 | ③의원을 제명하려면 국회재적의원 3분의 2 이상의 찬성이 있어야 한다. 151 | ④제2항과 제3항의 처분에 대하여는 법원에 제소할 수 없다. 152 | 제65조 ① 대통령·국무총리·국무위원·행정각부의 장·헌법재판소 재판관·법관·중앙선거관리위원회 위원·감사원장·감사위원 기타 법률이 정한 공무원이 그 직무집행에 있어서 헌법이나 법률을 위배한 때에는 국회는 탄핵의 소추를 의결할 수 있다. 153 | ②제1항의 탄핵소추는 국회재적의원 3분의 1 이상의 발의가 있어야 하며, 그 의결은 국회재적의원 과반수의 찬성이 있어야 한다. 다만, 대통령에 대한 탄핵소추는 국회재적의원 과반수의 발의와 국회재적의원 3분의 2 이상의 찬성이 있어야 한다. 154 | ③탄핵소추의 의결을 받은 자는 탄핵심판이 있을 때까지 그 권한행사가 정지된다. 155 | ④탄핵결정은 공직으로부터 파면함에 그친다. 그러나, 이에 의하여 민사상이나 형사상의 책임이 면제되지는 아니한다. 156 | 제4장 정부 157 | 제1절 대통령 158 | 제66조 ① 대통령은 국가의 원수이며, 외국에 대하여 국가를 대표한다. 159 | ②대통령은 국가의 독립·영토의 보전·국가의 계속성과 헌법을 수호할 책무를 진다. 160 | ③대통령은 조국의 평화적 통일을 위한 성실한 의무를 진다. 161 | ④행정권은 대통령을 수반으로 하는 정부에 속한다. 162 | 제67조 ① 대통령은 국민의 보통·평등·직접·비밀선거에 의하여 선출한다. 163 | ②제1항의 선거에 있어서 최고득표자가 2인 이상인 때에는 국회의 재적의원 과반수가 출석한 공개회의에서 다수표를 얻은 자를 당선자로 한다. 164 | ③대통령후보자가 1인일 때에는 그 득표수가 선거권자 총수의 3분의 1 이상이 아니면 대통령으로 당선될 수 없다. 165 | ④대통령으로 선거될 수 있는 자는 국회의원의 피선거권이 있고 선거일 현재 40세에 달하여야 한다. 166 | ⑤대통령의 선거에 관한 사항은 법률로 정한다. 167 | 제68조 ① 대통령의 임기가 만료되는 때에는 임기만료 70일 내지 40일전에 후임자를 선거한다. 168 | ②대통령이 궐위된 때 또는 대통령 당선자가 사망하거나 판결 기타의 사유로 그 자격을 상실한 때에는 60일 이내에 후임자를 선거한다. 169 | 제69조 대통령은 취임에 즈음하여 다음의 선서를 한다. 170 | "나는 헌법을 준수하고 국가를 보위하며 조국의 평화적 통일과 국민의 자유와 복리의 증진 및 민족문화의 창달에 노력하여 대통령으로서의 직책을 성실히 수행할 것을 국민 앞에 엄숙히 선서합니다." 171 | 제70조 대통령의 임기는 5년으로 하며, 중임할 수 없다. 172 | 제71조 대통령이 궐위되거나 사고로 인하여 직무를 수행할 수 없을 때에는 국무총리, 법률이 정한 국무위원의 순서로 그 권한을 대행한다. 173 | 제72조 대통령은 필요하다고 인정할 때에는 외교·국방·통일 기타 국가안위에 관한 중요정책을 국민투표에 붙일 수 있다. 174 | 제73조 대통령은 조약을 체결·비준하고, 외교사절을 신임·접수 또는 파견하며, 선전포고와 강화를 한다. 175 | 제74조 ① 대통령은 헌법과 법률이 정하는 바에 의하여 국군을 통수한다. 176 | ②국군의 조직과 편성은 법률로 정한다. 177 | 제75조 대통령은 법률에서 구체적으로 범위를 정하여 위임받은 사항과 법률을 집행하기 위하여 필요한 사항에 관하여 대통령령을 발할 수 있다. 178 | 제76조 ① 대통령은 내우·외환·천재·지변 또는 중대한 재정·경제상의 위기에 있어서 국가의 안전보장 또는 공공의 안녕질서를 유지하기 위하여 긴급한 조치가 필요하고 국회의 집회를 기다릴 여유가 없을 때에 한하여 최소한으로 필요한 재정·경제상의 처분을 하거나 이에 관하여 법률의 효력을 가지는 명령을 발할 수 있다. 179 | ②대통령은 국가의 안위에 관계되는 중대한 교전상태에 있어서 국가를 보위하기 위하여 긴급한 조치가 필요하고 국회의 집회가 불가능한 때에 한하여 법률의 효력을 가지는 명령을 발할 수 있다. 180 | ③대통령은 제1항과 제2항의 처분 또는 명령을 한 때에는 지체없이 국회에 보고하여 그 승인을 얻어야 한다. 181 | ④제3항의 승인을 얻지 못한 때에는 그 처분 또는 명령은 그때부터 효력을 상실한다. 이 경우 그 명령에 의하여 개정 또는 폐지되었던 법률은 그 명령이 승인을 얻지 못한 때부터 당연히 효력을 회복한다. 182 | ⑤대통령은 제3항과 제4항의 사유를 지체없이 공포하여야 한다. 183 | 제77조 ① 대통령은 전시·사변 또는 이에 준하는 국가비상사태에 있어서 병력으로써 군사상의 필요에 응하거나 공공의 안녕질서를 유지할 필요가 있을 때에는 법률이 정하는 바에 의하여 계엄을 선포할 수 있다. 184 | ②계엄은 비상계엄과 경비계엄으로 한다. 185 | ③비상계엄이 선포된 때에는 법률이 정하는 바에 의하여 영장제도, 언론·출판·집회·결사의 자유, 정부나 법원의 권한에 관하여 특별한 조치를 할 수 있다. 186 | ④계엄을 선포한 때에는 대통령은 지체없이 국회에 통고하여야 한다. 187 | ⑤국회가 재적의원 과반수의 찬성으로 계엄의 해제를 요구한 때에는 대통령은 이를 해제하여야 한다. 188 | 제78조 대통령은 헌법과 법률이 정하는 바에 의하여 공무원을 임면한다. 189 | 제79조 ① 대통령은 법률이 정하는 바에 의하여 사면·감형 또는 복권을 명할 수 있다. 190 | ②일반사면을 명하려면 국회의 동의를 얻어야 한다. 191 | ③사면·감형 및 복권에 관한 사항은 법률로 정한다. 192 | 제80조 대통령은 법률이 정하는 바에 의하여 훈장 기타의 영전을 수여한다. 193 | 제81조 대통령은 국회에 출석하여 발언하거나 서한으로 의견을 표시할 수 있다. 194 | 제82조 대통령의 국법상 행위는 문서로써 하며, 이 문서에는 국무총리와 관계 국무위원이 부서한다. 군사에 관한 것도 또한 같다. 195 | 제83조 대통령은 국무총리·국무위원·행정각부의 장 기타 법률이 정하는 공사의 직을 겸할 수 없다. 196 | 제84조 대통령은 내란 또는 외환의 죄를 범한 경우를 제외하고는 재직중 형사상의 소추를 받지 아니한다. 197 | 제85조 전직대통령의 신분과 예우에 관하여는 법률로 정한다. 198 | 제2절 행정부 199 | 제1관 국무총리와 국무위원 200 | 제86조 ① 국무총리는 국회의 동의를 얻어 대통령이 임명한다. 201 | ②국무총리는 대통령을 보좌하며, 행정에 관하여 대통령의 명을 받아 행정각부를 통할한다. 202 | ③군인은 현역을 면한 후가 아니면 국무총리로 임명될 수 없다. 203 | 제87조 ① 국무위원은 국무총리의 제청으로 대통령이 임명한다. 204 | ②국무위원은 국정에 관하여 대통령을 보좌하며, 국무회의의 구성원으로서 국정을 심의한다. 205 | ③국무총리는 국무위원의 해임을 대통령에게 건의할 수 있다. 206 | ④군인은 현역을 면한 후가 아니면 국무위원으로 임명될 수 없다. 207 | 제2관 국무회의 208 | 제88조 ① 국무회의는 정부의 권한에 속하는 중요한 정책을 심의한다. 209 | ②국무회의는 대통령·국무총리와 15인 이상 30인 이하의 국무위원으로 구성한다. 210 | ③대통령은 국무회의의 의장이 되고, 국무총리는 부의장이 된다. 211 | 제89조 다음 사항은 국무회의의 심의를 거쳐야 한다. 212 | 1. 국정의 기본계획과 정부의 일반정책 213 | 2. 선전·강화 기타 중요한 대외정책 214 | 3. 헌법개정안·국민투표안·조약안·법률안 및 대통령령안 215 | 4. 예산안·결산·국유재산처분의 기본계획·국가의 부담이 될 계약 기타 재정에 관한 중요사항 216 | 5. 대통령의 긴급명령·긴급재정경제처분 및 명령 또는 계엄과 그 해제 217 | 6. 군사에 관한 중요사항 218 | 7. 국회의 임시회 집회의 요구 219 | 8. 영전수여 220 | 9. 사면·감형과 복권 221 | 10. 행정각부간의 권한의 획정 222 | 11. 정부안의 권한의 위임 또는 배정에 관한 기본계획 223 | 12. 국정처리상황의 평가·분석 224 | 13. 행정각부의 중요한 정책의 수립과 조정 225 | 14. 정당해산의 제소 226 | 15. 정부에 제출 또는 회부된 정부의 정책에 관계되는 청원의 심사 227 | 16. 검찰총장·합동참모의장·각군참모총장·국립대학교총장·대사 기타 법률이 정한 공무원과 국영기업체관리자의 임명 228 | 17. 기타 대통령·국무총리 또는 국무위원이 제출한 사항 229 | 제90조 ① 국정의 중요한 사항에 관한 대통령의 자문에 응하기 위하여 국가원로로 구성되는 국가원로자문회의를 둘 수 있다. 230 | ②국가원로자문회의의 의장은 직전대통령이 된다. 다만, 직전대통령이 없을 때에는 대통령이 지명한다. 231 | ③국가원로자문회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 232 | 제91조 ① 국가안전보장에 관련되는 대외정책·군사정책과 국내정책의 수립에 관하여 국무회의의 심의에 앞서 대통령의 자문에 응하기 위하여 국가안전보장회의를 둔다. 233 | ②국가안전보장회의는 대통령이 주재한다. 234 | ③국가안전보장회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 235 | 제92조 ① 평화통일정책의 수립에 관한 대통령의 자문에 응하기 위하여 민주평화통일자문회의를 둘 수 있다. 236 | ②민주평화통일자문회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 237 | 제93조 ① 국민경제의 발전을 위한 중요정책의 수립에 관하여 대통령의 자문에 응하기 위하여 국민경제자문회의를 둘 수 있다. 238 | ②국민경제자문회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 239 | 제3관 행정각부 240 | 제94조 행정각부의 장은 국무위원 중에서 국무총리의 제청으로 대통령이 임명한다. 241 | 제95조 국무총리 또는 행정각부의 장은 소관사무에 관하여 법률이나 대통령령의 위임 또는 직권으로 총리령 또는 부령을 발할 수 있다. 242 | 제96조 행정각부의 설치·조직과 직무범위는 법률로 정한다. 243 | 제4관 감사원 244 | 제97조 국가의 세입·세출의 결산, 국가 및 법률이 정한 단체의 회계검사와 행정기관 및 공무원의 직무에 관한 감찰을 하기 위하여 대통령 소속하에 감사원을 둔다. 245 | 제98조 ① 감사원은 원장을 포함한 5인 이상 11인 이하의 감사위원으로 구성한다. 246 | ②원장은 국회의 동의를 얻어 대통령이 임명하고, 그 임기는 4년으로 하며, 1차에 한하여 중임할 수 있다. 247 | ③감사위원은 원장의 제청으로 대통령이 임명하고, 그 임기는 4년으로 하며, 1차에 한하여 중임할 수 있다. 248 | 제99조 감사원은 세입·세출의 결산을 매년 검사하여 대통령과 차년도국회에 그 결과를 보고하여야 한다. 249 | 제100조 감사원의 조직·직무범위·감사위원의 자격·감사대상공무원의 범위 기타 필요한 사항은 법률로 정한다. 250 | 제5장 법원 251 | 제101조 ① 사법권은 법관으로 구성된 법원에 속한다. 252 | ②법원은 최고법원인 대법원과 각급법원으로 조직된다. 253 | ③법관의 자격은 법률로 정한다. 254 | 제102조 ① 대법원에 부를 둘 수 있다. 255 | ②대법원에 대법관을 둔다. 다만, 법률이 정하는 바에 의하여 대법관이 아닌 법관을 둘 수 있다. 256 | ③대법원과 각급법원의 조직은 법률로 정한다. 257 | 제103조 법관은 헌법과 법률에 의하여 그 양심에 따라 독립하여 심판한다. 258 | 제104조 ① 대법원장은 국회의 동의를 얻어 대통령이 임명한다. 259 | ②대법관은 대법원장의 제청으로 국회의 동의를 얻어 대통령이 임명한다. 260 | ③대법원장과 대법관이 아닌 법관은 대법관회의의 동의를 얻어 대법원장이 임명한다. 261 | 제105조 ① 대법원장의 임기는 6년으로 하며, 중임할 수 없다. 262 | ②대법관의 임기는 6년으로 하며, 법률이 정하는 바에 의하여 연임할 수 있다. 263 | ③대법원장과 대법관이 아닌 법관의 임기는 10년으로 하며, 법률이 정하는 바에 의하여 연임할 수 있다. 264 | ④법관의 정년은 법률로 정한다. 265 | 제106조 ① 법관은 탄핵 또는 금고 이상의 형의 선고에 의하지 아니하고는 파면되지 아니하며, 징계처분에 의하지 아니하고는 정직·감봉 기타 불리한 처분을 받지 아니한다. 266 | ②법관이 중대한 심신상의 장해로 직무를 수행할 수 없을 때에는 법률이 정하는 바에 의하여 퇴직하게 할 수 있다. 267 | 제107조 ① 법률이 헌법에 위반되는 여부가 재판의 전제가 된 경우에는 법원은 헌법재판소에 제청하여 그 심판에 의하여 재판한다. 268 | ②명령·규칙 또는 처분이 헌법이나 법률에 위반되는 여부가 재판의 전제가 된 경우에는 대법원은 이를 최종적으로 심사할 권한을 가진다. 269 | ③재판의 전심절차로서 행정심판을 할 수 있다. 행정심판의 절차는 법률로 정하되, 사법절차가 준용되어야 한다. 270 | 제108조 대법원은 법률에 저촉되지 아니하는 범위안에서 소송에 관한 절차, 법원의 내부규율과 사무처리에 관한 규칙을 제정할 수 있다. 271 | 제109조 재판의 심리와 판결은 공개한다. 다만, 심리는 국가의 안전보장 또는 안녕질서를 방해하거나 선량한 풍속을 해할 염려가 있을 때에는 법원의 결정으로 공개하지 아니할 수 있다. 272 | 제110조 ① 군사재판을 관할하기 위하여 특별법원으로서 군사법원을 둘 수 있다. 273 | ②군사법원의 상고심은 대법원에서 관할한다. 274 | ③군사법원의 조직·권한 및 재판관의 자격은 법률로 정한다. 275 | ④비상계엄하의 군사재판은 군인·군무원의 범죄나 군사에 관한 간첩죄의 경우와 초병·초소·유독음식물공급·포로에 관한 죄중 법률이 정한 경우에 한하여 단심으로 할 수 있다. 다만, 사형을 선고한 경우에는 그러하지 아니하다. 276 | 제6장 헌법재판소 277 | 제111조 ① 헌법재판소는 다음 사항을 관장한다. 278 | 1. 법원의 제청에 의한 법률의 위헌여부 심판 279 | 2. 탄핵의 심판 280 | 3. 정당의 해산 심판 281 | 4. 국가기관 상호간, 국가기관과 지방자치단체간 및 지방자치단체 상호간의 권한쟁의에 관한 심판 282 | 5. 법률이 정하는 헌법소원에 관한 심판 283 | ②헌법재판소는 법관의 자격을 가진 9인의 재판관으로 구성하며, 재판관은 대통령이 임명한다. 284 | ③제2항의 재판관중 3인은 국회에서 선출하는 자를, 3인은 대법원장이 지명하는 자를 임명한다. 285 | ④헌법재판소의 장은 국회의 동의를 얻어 재판관중에서 대통령이 임명한다. 286 | 제112조 ① 헌법재판소 재판관의 임기는 6년으로 하며, 법률이 정하는 바에 의하여 연임할 수 있다. 287 | ②헌법재판소 재판관은 정당에 가입하거나 정치에 관여할 수 없다. 288 | ③헌법재판소 재판관은 탄핵 또는 금고 이상의 형의 선고에 의하지 아니하고는 파면되지 아니한다. 289 | 제113조 ① 헌법재판소에서 법률의 위헌결정, 탄핵의 결정, 정당해산의 결정 또는 헌법소원에 관한 인용결정을 할 때에는 재판관 6인 이상의 찬성이 있어야 한다. 290 | ②헌법재판소는 법률에 저촉되지 아니하는 범위안에서 심판에 관한 절차, 내부규율과 사무처리에 관한 규칙을 제정할 수 있다. 291 | ③헌법재판소의 조직과 운영 기타 필요한 사항은 법률로 정한다. 292 | 제7장 선거관리 293 | 제114조 ① 선거와 국민투표의 공정한 관리 및 정당에 관한 사무를 처리하기 위하여 선거관리위원회를 둔다. 294 | ②중앙선거관리위원회는 대통령이 임명하는 3인, 국회에서 선출하는 3인과 대법원장이 지명하는 3인의 위원으로 구성한다. 위원장은 위원중에서 호선한다. 295 | ③위원의 임기는 6년으로 한다. 296 | ④위원은 정당에 가입하거나 정치에 관여할 수 없다. 297 | ⑤위원은 탄핵 또는 금고 이상의 형의 선고에 의하지 아니하고는 파면되지 아니한다. 298 | ⑥중앙선거관리위원회는 법령의 범위안에서 선거관리·국민투표관리 또는 정당사무에 관한 규칙을 제정할 수 있으며, 법률에 저촉되지 아니하는 범위안에서 내부규율에 관한 규칙을 제정할 수 있다. 299 | ⑦각급 선거관리위원회의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 300 | 제115조 ① 각급 선거관리위원회는 선거인명부의 작성등 선거사무와 국민투표사무에 관하여 관계 행정기관에 필요한 지시를 할 수 있다. 301 | ②제1항의 지시를 받은 당해 행정기관은 이에 응하여야 한다. 302 | 제116조 ① 선거운동은 각급 선거관리위원회의 관리하에 법률이 정하는 범위안에서 하되, 균등한 기회가 보장되어야 한다. 303 | ②선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는 후보자에게 부담시킬 수 없다. 304 | 제8장 지방자치 305 | 제117조 ① 지방자치단체는 주민의 복리에 관한 사무를 처리하고 재산을 관리하며, 법령의 범위안에서 자치에 관한 규정을 제정할 수 있다. 306 | ②지방자치단체의 종류는 법률로 정한다. 307 | 제118조 ① 지방자치단체에 의회를 둔다. 308 | ②지방의회의 조직·권한·의원선거와 지방자치단체의 장의 선임방법 기타 지방자치단체의 조직과 운영에 관한 사항은 법률로 정한다. 309 | 제9장 경제 310 | 제119조 ① 대한민국의 경제질서는 개인과 기업의 경제상의 자유와 창의를 존중함을 기본으로 한다. 311 | ②국가는 균형있는 국민경제의 성장 및 안정과 적정한 소득의 분배를 유지하고, 시장의 지배와 경제력의 남용을 방지하며, 경제주체간의 조화를 통한 경제의 민주화를 위하여 경제에 관한 규제와 조정을 할 수 있다. 312 | 제120조 ① 광물 기타 중요한 지하자원·수산자원·수력과 경제상 이용할 수 있는 자연력은 법률이 정하는 바에 의하여 일정한 기간 그 채취·개발 또는 이용을 특허할 수 있다. 313 | ②국토와 자원은 국가의 보호를 받으며, 국가는 그 균형있는 개발과 이용을 위하여 필요한 계획을 수립한다. 314 | 제121조 ① 국가는 농지에 관하여 경자유전의 원칙이 달성될 수 있도록 노력하여야 하며, 농지의 소작제도는 금지된다. 315 | ②농업생산성의 제고와 농지의 합리적인 이용을 위하거나 불가피한 사정으로 발생하는 농지의 임대차와 위탁경영은 법률이 정하는 바에 의하여 인정된다. 316 | 제122조 국가는 국민 모두의 생산 및 생활의 기반이 되는 국토의 효율적이고 균형있는 이용·개발과 보전을 위하여 법률이 정하는 바에 의하여 그에 관한 필요한 제한과 의무를 과할 수 있다. 317 | 제123조 ① 국가는 농업 및 어업을 보호·육성하기 위하여 농·어촌종합개발과 그 지원등 필요한 계획을 수립·시행하여야 한다. 318 | ②국가는 지역간의 균형있는 발전을 위하여 지역경제를 육성할 의무를 진다. 319 | ③국가는 중소기업을 보호·육성하여야 한다. 320 | ④국가는 농수산물의 수급균형과 유통구조의 개선에 노력하여 가격안정을 도모함으로써 농·어민의 이익을 보호한다. 321 | ⑤국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다. 322 | 제124조 국가는 건전한 소비행위를 계도하고 생산품의 품질향상을 촉구하기 위한 소비자보호운동을 법률이 정하는 바에 의하여 보장한다. 323 | 제125조 국가는 대외무역을 육성하며, 이를 규제·조정할 수 있다. 324 | 제126조 국방상 또는 국민경제상 긴절한 필요로 인하여 법률이 정하는 경우를 제외하고는, 사영기업을 국유 또는 공유로 이전하거나 그 경영을 통제 또는 관리할 수 없다. 325 | 제127조 ① 국가는 과학기술의 혁신과 정보 및 인력의 개발을 통하여 국민경제의 발전에 노력하여야 한다. 326 | ②국가는 국가표준제도를 확립한다. 327 | ③대통령은 제1항의 목적을 달성하기 위하여 필요한 자문기구를 둘 수 있다. 328 | 제10장 헌법개정 329 | 제128조 ① 헌법개정은 국회재적의원 과반수 또는 대통령의 발의로 제안된다. 330 | ②대통령의 임기연장 또는 중임변경을 위한 헌법개정은 그 헌법개정 제안 당시의 대통령에 대하여는 효력이 없다. 331 | 제129조 제안된 헌법개정안은 대통령이 20일 이상의 기간 이를 공고하여야 한다. 332 | 제130조 ① 국회는 헌법개정안이 공고된 날로부터 60일 이내에 의결하여야 하며, 국회의 의결은 재적의원 3분의 2 이상의 찬성을 얻어야 한다. 333 | ②헌법개정안은 국회가 의결한 후 30일 이내에 국민투표에 붙여 국회의원선거권자 과반수의 투표와 투표자 과반수의 찬성을 얻어야 한다. 334 | ③헌법개정안이 제2항의 찬성을 얻은 때에는 헌법개정은 확정되며, 대통령은 즉시 이를 공포하여야 한다. 335 | 펼침 부칙 <헌법 제10호, 1987.10.29.> 부칙보기 336 | 제1조 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한 법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다. 337 | 제2조 ①이 헌법에 의한 최초의 대통령선거는 이 헌법시행일 40일 전까지 실시한다. 338 | ②이 헌법에 의한 최초의 대통령의 임기는 이 헌법시행일로부터 개시한다. 339 | 제3조 ①이 헌법에 의한 최초의 국회의원선거는 이 헌법공포일로부터 6월 이내에 실시하며, 이 헌법에 의하여 선출된 최초의 국회의원의 임기는 국회의원선거후 이 헌법에 의한 국회의 최초의 집회일로부터 개시한다. 340 | ②이 헌법공포 당시의 국회의원의 임기는 제1항에 의한 국회의 최초의 집회일 전일까지로 한다. 341 | 제4조 ①이 헌법시행 당시의 공무원과 정부가 임명한 기업체의 임원은 이 헌법에 의하여 임명된 것으로 본다. 다만, 이 헌법에 의하여 선임방법이나 임명권자가 변경된 공무원과 대법원장 및 감사원장은 이 헌법에 의하여 후임자가 선임될 때까지 그 직무를 행하며, 이 경우 전임자인 공무원의 임기는 후임자가 선임되는 전일까지로 한다. 342 | ②이 헌법시행 당시의 대법원장과 대법원판사가 아닌 법관은 제1항 단서의 규정에 불구하고 이 헌법에 의하여 임명된 것으로 본다. 343 | ③이 헌법중 공무원의 임기 또는 중임제한에 관한 규정은 이 헌법에 의하여 그 공무원이 최초로 선출 또는 임명된 때로부터 적용한다. 344 | 제5조 이 헌법시행 당시의 법령과 조약은 이 헌법에 위배되지 아니하는 한 그 효력을 지속한다. 345 | 제6조 이 헌법시행 당시에 이 헌법에 의하여 새로 설치될 기관의 권한에 속하는 직무를 행하고 있는 기관은 이 헌법에 의하여 새로운 기관이 설치될 때까지 존속하며 그 직무를 행한다. 346 | -------------------------------------------------------------------------------- /example/user_dict.tsv: -------------------------------------------------------------------------------- 1 | # https://github.com/bab2min/kiwipiepy#%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%82%AC%EC%A0%84-%EC%B6%94%EA%B0%80 2 | 3 | 아버지가 NNG 0 4 | -------------------------------------------------------------------------------- /example/user_dict2.tsv: -------------------------------------------------------------------------------- 1 | # https://github.com/bab2min/kiwipiepy#%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%82%AC%EC%A0%84-%EC%B6%94%EA%B0%80 2 | 3 | 아버지가 NNG 0 4 | 방에 NNG 0 5 | 들어가신다 NNG 0 -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/codingpot/kiwigo 2 | 3 | go 1.23 4 | 5 | require ( 6 | github.com/google/go-cmp v0.6.0 7 | github.com/stretchr/testify v1.7.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.0 // indirect 12 | github.com/pmezard/go-difflib v1.0.0 // indirect 13 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 4 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 8 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 9 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 11 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 12 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 13 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 14 | -------------------------------------------------------------------------------- /internal/rewindscanner.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | ) 7 | 8 | // RewindScanner is a scanner that rewinds the underlying reader. 9 | type RewindScanner struct { 10 | readSeeker io.ReadSeeker 11 | scanner *bufio.Scanner 12 | } 13 | 14 | // Rewind rewinds the underlying reader to the beginning. 15 | func (s *RewindScanner) Rewind() { 16 | s.readSeeker.Seek(0, io.SeekStart) 17 | s.scanner = bufio.NewScanner(s.readSeeker) 18 | } 19 | 20 | func (s *RewindScanner) Scan() bool { 21 | return s.scanner.Scan() 22 | } 23 | 24 | func (s *RewindScanner) Text() string { 25 | return s.scanner.Text() 26 | } 27 | 28 | func NewRewindScanner(seeker io.ReadSeeker) *RewindScanner { 29 | return &RewindScanner{ 30 | readSeeker: seeker, 31 | scanner: bufio.NewScanner(seeker), 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /internal/rewindscanner_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestRewindScanner_Rewind(t *testing.T) { 11 | reader := strings.NewReader(`안녕하세요 12 | 코딩 냄비입니다.`) 13 | scanner := NewRewindScanner(reader) 14 | 15 | scanner.Scan() 16 | assert.Equal(t, "안녕하세요", scanner.Text()) 17 | 18 | scanner.Rewind() 19 | scanner.Scan() 20 | assert.Equal(t, "안녕하세요", scanner.Text()) 21 | } 22 | -------------------------------------------------------------------------------- /kiwi.go: -------------------------------------------------------------------------------- 1 | // Package kiwi is a Go binding for Kiwi (https://github.com/bab2min/Kiwi) project. 2 | package kiwi 3 | 4 | /* 5 | #cgo CFLAGS: -I/usr/local/include 6 | #cgo LDFLAGS: -Wl,-rpath,/usr/local/lib 7 | 8 | #include 9 | #include 10 | #include // for uintptr_t 11 | 12 | #include 13 | 14 | extern int KiwiReaderBridge(int lineNumber, char *buffer, void *userData); 15 | */ 16 | import "C" 17 | 18 | import ( 19 | "fmt" 20 | "io" 21 | "runtime/cgo" 22 | "unsafe" 23 | 24 | "github.com/codingpot/kiwigo/internal" 25 | ) 26 | 27 | // BuildOption is a bitwise OR of the KiwiBuildOption values. 28 | type BuildOption int 29 | 30 | const ( 31 | KIWI_BUILD_LOAD_DEFAULT_DICT BuildOption = C.KIWI_BUILD_LOAD_DEFAULT_DICT 32 | KIWI_BUILD_INTEGRATE_ALLOMORPH BuildOption = C.KIWI_BUILD_INTEGRATE_ALLOMORPH 33 | KIWI_BUILD_DEFAULT BuildOption = C.KIWI_BUILD_DEFAULT 34 | ) 35 | 36 | // AnalyzeOption is a bitwise OR of the KiwiAnalyzeOption values. 37 | type AnalyzeOption int 38 | 39 | const ( 40 | KIWI_MATCH_URL AnalyzeOption = C.KIWI_MATCH_URL 41 | KIWI_MATCH_EMAIL AnalyzeOption = C.KIWI_MATCH_EMAIL 42 | KIWI_MATCH_HASHTAG AnalyzeOption = C.KIWI_MATCH_HASHTAG 43 | KIWI_MATCH_MENTION AnalyzeOption = C.KIWI_MATCH_MENTION 44 | KIWI_MATCH_ALL AnalyzeOption = C.KIWI_MATCH_ALL 45 | KIWI_MATCH_NORMALIZE_CODA AnalyzeOption = C.KIWI_MATCH_NORMALIZE_CODA 46 | KIWI_MATCH_ALL_WITH_NORMALIZING AnalyzeOption = C.KIWI_MATCH_ALL_WITH_NORMALIZING 47 | ) 48 | 49 | // KiwiVersion returns the version of the kiwi library. 50 | func KiwiVersion() string { 51 | return C.GoString(C.kiwi_version()) 52 | } 53 | 54 | // KiwiError returns the Error messages. 55 | func KiwiError() string { 56 | return C.GoString(C.kiwi_error()) 57 | } 58 | 59 | // KiwiClearError clear error. 60 | func KiwiClearError() { 61 | C.kiwi_clear_error() 62 | } 63 | 64 | // Kiwi is a wrapper for the kiwi C library. 65 | type Kiwi struct { 66 | handler C.kiwi_h 67 | } 68 | 69 | // New returns a new Kiwi instance. 70 | // Don't forget to call Close after this. 71 | func New(modelPath string, numThread int, options BuildOption) *Kiwi { 72 | return &Kiwi{ 73 | handler: C.kiwi_init(C.CString(modelPath), C.int(numThread), C.int(options)), 74 | } 75 | } 76 | 77 | // TokenInfo returns the token info for the given token(Str). 78 | type TokenInfo struct { 79 | // Position is the index of this token appears in the original text. 80 | Position int 81 | 82 | // Tag represents a type of this token (e.g. VV, NNG, ...). 83 | Tag POSType 84 | 85 | // Form is the actual string of this token. 86 | Form string 87 | } 88 | 89 | // TokenResult is a result for Analyze. 90 | type TokenResult struct { 91 | Tokens []TokenInfo 92 | Score float32 93 | } 94 | 95 | // Analyze returns the result of the analysis. 96 | func (k *Kiwi) Analyze(text string, topN int, options AnalyzeOption) ([]TokenResult, error) { 97 | var ( 98 | blocklist C.kiwi_morphset_h 99 | pretokenized C.kiwi_pretokenized_h 100 | cText = C.CString(text) 101 | ) 102 | 103 | defer C.free(unsafe.Pointer(cText)) 104 | 105 | kiwiResH := C.kiwi_analyze(k.handler, cText, C.int(topN), C.int(options), blocklist, pretokenized) 106 | if kiwiResH == nil { 107 | return nil, fmt.Errorf("failed to analyze text") 108 | } 109 | defer C.kiwi_res_close(kiwiResH) 110 | 111 | resSize := int(C.kiwi_res_size(kiwiResH)) 112 | if resSize < 0 { 113 | return nil, fmt.Errorf("invalid result size: %d", resSize) 114 | } 115 | 116 | res := make([]TokenResult, resSize) 117 | 118 | for i := 0; i < resSize; i++ { 119 | wordNum := int(C.kiwi_res_word_num(kiwiResH, C.int(i))) 120 | if wordNum < 0 { 121 | return nil, fmt.Errorf("invalid word number: %d", wordNum) 122 | } 123 | 124 | tokens := make([]TokenInfo, wordNum) 125 | 126 | for j := 0; j < wordNum; j++ { 127 | pos, err := ParsePOSType(C.GoString(C.kiwi_res_tag(kiwiResH, C.int(i), C.int(j)))) 128 | if err != nil { 129 | return nil, err 130 | } 131 | tokens[j] = TokenInfo{ 132 | Form: C.GoString(C.kiwi_res_form(kiwiResH, C.int(i), C.int(j))), 133 | Tag: pos, 134 | Position: int(C.kiwi_res_position(kiwiResH, C.int(i), C.int(j))), 135 | } 136 | } 137 | 138 | res[i] = TokenResult{ 139 | Tokens: tokens, 140 | Score: float32(C.kiwi_res_prob(kiwiResH, C.int(i))), 141 | } 142 | } 143 | 144 | return res, nil 145 | } 146 | 147 | // SplitResult returns the Sentences. 148 | type SplitResult struct { 149 | Text string 150 | Begin int 151 | End int 152 | } 153 | 154 | // SplitSentence returns the line of sentences. 155 | func (k *Kiwi) SplitSentence(text string, options AnalyzeOption) ([]SplitResult, error) { 156 | cText := C.CString(text) 157 | defer C.free(unsafe.Pointer(cText)) 158 | 159 | kiwiSsH := C.kiwi_split_into_sents(k.handler, cText, C.int(options), nil) 160 | if kiwiSsH == nil { 161 | return nil, fmt.Errorf("failed to split sentences") 162 | } 163 | defer C.kiwi_ss_close(kiwiSsH) 164 | 165 | resSize := int(C.kiwi_ss_size(kiwiSsH)) 166 | if resSize < 0 { 167 | return nil, fmt.Errorf("invalid result size: %d", resSize) 168 | } 169 | 170 | res := make([]SplitResult, resSize) 171 | 172 | for i := 0; i < resSize; i++ { 173 | begin := int(C.kiwi_ss_begin_position(kiwiSsH, C.int(i))) 174 | end := int(C.kiwi_ss_end_position(kiwiSsH, C.int(i))) 175 | 176 | if begin < 0 || end < begin || end > len(text) { 177 | return nil, fmt.Errorf("invalid position range: begin=%d, end=%d", begin, end) 178 | } 179 | 180 | res[i] = SplitResult{ 181 | Text: text[begin:end], 182 | Begin: begin, 183 | End: end, 184 | } 185 | } 186 | 187 | return res, nil 188 | } 189 | 190 | // Close frees the resource allocated for Kiwi and returns the exit status. 191 | // This must be called after New. 192 | // Returns 0 if successful. 193 | // Safe to call multiple times. 194 | func (k *Kiwi) Close() int { 195 | if k.handler != nil { 196 | out := int(C.kiwi_close(k.handler)) 197 | k.handler = nil 198 | return out 199 | } 200 | return 0 201 | } 202 | 203 | // KiwiBuilder is a wrapper for the kiwi C library. 204 | type KiwiBuilder struct { 205 | handler C.kiwi_builder_h 206 | } 207 | 208 | // NewBuilder returns a new KiwiBuilder instance. 209 | // Don't forget to call Close after this. 210 | func NewBuilder(modelPath string, numThread int, options BuildOption) *KiwiBuilder { 211 | return &KiwiBuilder{ 212 | handler: C.kiwi_builder_init(C.CString(modelPath), C.int(numThread), C.int(options)), 213 | } 214 | } 215 | 216 | // AddWord set custom word with word, pos, score. 217 | func (kb *KiwiBuilder) AddWord(word string, pos POSType, score float32) int { 218 | return int(C.kiwi_builder_add_word(kb.handler, C.CString(word), C.CString(string(pos)), C.float(score))) 219 | } 220 | 221 | // LoadDict loads user dict with dict file path. 222 | func (kb *KiwiBuilder) LoadDict(dictPath string) int { 223 | return int(C.kiwi_builder_load_dict(kb.handler, C.CString(dictPath))) 224 | } 225 | 226 | // Build creates kiwi instance with user word etc. 227 | func (kb *KiwiBuilder) Build() *Kiwi { 228 | var ( 229 | typos C.kiwi_typo_h 230 | typoCostThreshold = C.float(1.0) 231 | ) 232 | 233 | h := C.kiwi_builder_build(kb.handler, typos, typoCostThreshold) 234 | defer kb.Close() 235 | return &Kiwi{ 236 | handler: h, 237 | } 238 | } 239 | 240 | // Close frees the resource allocated for KiwiBuilder and returns the exit status. 241 | // This must be called after New but not need to called after Build. 242 | // Returns 0 if successful. 243 | // Safe to call multiple times. 244 | func (kb *KiwiBuilder) Close() int { 245 | if kb.handler != nil { 246 | out := int(C.kiwi_builder_close(kb.handler)) 247 | kb.handler = nil 248 | return out 249 | } 250 | return 0 251 | } 252 | 253 | // WordInfo returns the token info for the given token(Str). 254 | type WordInfo struct { 255 | Form string 256 | Freq int 257 | POSScore float32 258 | Score float32 259 | } 260 | 261 | //export KiwiReaderImpl 262 | func KiwiReaderImpl(lineNumber C.int, buffer *C.char, userData unsafe.Pointer) C.int { 263 | scanner := cgo.Handle(userData).Value().(*internal.RewindScanner) 264 | 265 | if buffer == nil { 266 | if lineNumber == 0 { 267 | scanner.Rewind() 268 | } 269 | 270 | if !scanner.Scan() { 271 | return C.int(0) 272 | } 273 | 274 | text := scanner.Text() 275 | return C.int(len([]byte(text)) + 1) 276 | } 277 | 278 | textCString := C.CString(scanner.Text()) 279 | defer C.free(unsafe.Pointer(textCString)) 280 | 281 | C.strcpy(buffer, textCString) 282 | return C.int(0) 283 | } 284 | 285 | // ExtractWords returns the result of extract word. 286 | func (kb *KiwiBuilder) ExtractWords(readSeeker io.ReadSeeker, minCnt int, maxWordLen int, minScore float32, posThreshold float32) ([]WordInfo, error) { 287 | scanner := internal.NewRewindScanner(readSeeker) 288 | h := cgo.NewHandle(scanner) 289 | defer h.Delete() 290 | 291 | kiwiWsH := C.kiwi_builder_extract_words( 292 | kb.handler, 293 | C.kiwi_reader_t(C.KiwiReaderBridge), 294 | unsafe.Pointer(h), 295 | C.int(minCnt), C.int(maxWordLen), C.float(minScore), C.float(posThreshold)) 296 | defer C.kiwi_ws_close(kiwiWsH) 297 | 298 | resSize := int(C.kiwi_ws_size(kiwiWsH)) 299 | 300 | if resSize < 0 { 301 | resSize = 0 302 | } 303 | 304 | res := make([]WordInfo, resSize) 305 | 306 | for i := 0; i < resSize; i++ { 307 | res[i] = WordInfo{ 308 | Form: C.GoString(C.kiwi_ws_form(kiwiWsH, C.int(i))), 309 | Freq: int(C.kiwi_ws_freq(kiwiWsH, C.int(i))), 310 | POSScore: float32(C.kiwi_ws_pos_score(kiwiWsH, C.int(i))), 311 | Score: float32(C.kiwi_ws_score(kiwiWsH, C.int(i))), 312 | } 313 | } 314 | 315 | return res, nil 316 | } 317 | -------------------------------------------------------------------------------- /kiwi_example_test.go: -------------------------------------------------------------------------------- 1 | package kiwi_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | kiwi "github.com/codingpot/kiwigo" 7 | ) 8 | 9 | func Example() { 10 | kb := kiwi.NewBuilder("./base", 1 /*=numThread*/, kiwi.KIWI_BUILD_INTEGRATE_ALLOMORPH /*=options*/) 11 | kb.AddWord("코딩냄비", "NNP", 0) 12 | 13 | k := kb.Build() 14 | defer k.Close() // don't forget to Close()! 15 | 16 | results, _ := k.Analyze("안녕하세요 코딩냄비입니다. 부글부글.", 1 /*=topN*/, kiwi.KIWI_MATCH_ALL) 17 | 18 | // Print tokens without the score to avoid floating-point output issues 19 | if len(results) > 0 { 20 | fmt.Printf("Tokens: %v\n", results[0].Tokens) 21 | } 22 | // Output: 23 | // Tokens: [{0 NNG 안녕} {2 XSA 하} {3 EF 세요} {6 NNP 코딩냄비} {10 VCP 이} {10 EF ᆸ니다} {13 SF .} {15 MAG 부글부글} {19 SF .}] 24 | } 25 | -------------------------------------------------------------------------------- /kiwi_test.go: -------------------------------------------------------------------------------- 1 | package kiwi 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/google/go-cmp/cmp" 9 | "github.com/google/go-cmp/cmp/cmpopts" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | // floatComparer returns a cmp.Option for floating-point comparisons with tolerance. 14 | func floatComparer() cmp.Option { 15 | return cmpopts.EquateApprox(0, 1e-5) 16 | } 17 | 18 | func TestKiwiVersion(t *testing.T) { 19 | assert.Equal(t, KiwiVersion(), "0.21.0") 20 | } 21 | 22 | func TestAnalyze(t *testing.T) { 23 | kiwi := New("./base", 1, KIWI_BUILD_DEFAULT) 24 | res, _ := kiwi.Analyze("아버지가 방에 들어가신다", 1, KIWI_MATCH_ALL) 25 | 26 | expected := []TokenResult{ 27 | { 28 | Tokens: []TokenInfo{ 29 | { 30 | Position: 0, 31 | Tag: POS_NNG, 32 | Form: "아버지", 33 | }, 34 | { 35 | Position: 3, 36 | Tag: POS_JKS, 37 | Form: "가", 38 | }, 39 | { 40 | Position: 5, 41 | Tag: POS_NNG, 42 | Form: "방", 43 | }, 44 | { 45 | Position: 6, 46 | Tag: POS_JKB, 47 | Form: "에", 48 | }, 49 | { 50 | Position: 8, 51 | Tag: POS_VV, 52 | Form: "들어가", 53 | }, 54 | { 55 | Position: 11, 56 | Tag: POS_EP, 57 | Form: "시", 58 | }, 59 | { 60 | Position: 11, 61 | Tag: POS_EF, 62 | Form: "ᆫ다", 63 | }, 64 | }, 65 | Score: -34.55623, 66 | }, 67 | } 68 | 69 | if diff := cmp.Diff(expected, res, floatComparer()); diff != "" { 70 | t.Errorf("Analyze result mismatch (-want +got):\n%s", diff) 71 | } 72 | assert.Equal(t, 0, kiwi.Close()) 73 | } 74 | 75 | func TestSplitSentence(t *testing.T) { 76 | kiwi := New("./base", 1, KIWI_BUILD_DEFAULT) 77 | res, _ := kiwi.SplitSentence("여러 문장으로 구성된 텍스트네 이걸 분리해줘", KIWI_MATCH_ALL) 78 | 79 | expected := []SplitResult{ 80 | { 81 | Text: "여러 문장으로 구성된 텍스트네", 82 | Begin: 0, 83 | End: 42, 84 | }, 85 | { 86 | Text: "이걸 분리해줘", 87 | Begin: 43, 88 | End: 62, 89 | }, 90 | } 91 | 92 | assert.Equal(t, expected, res) 93 | assert.Equal(t, 0, kiwi.Close()) 94 | } 95 | 96 | func TestAddWordFail(t *testing.T) { 97 | kb := NewBuilder("./base", 1, KIWI_BUILD_INTEGRATE_ALLOMORPH) 98 | add := kb.AddWord("아버지가", "SKO", 0) 99 | assert.Equal(t, -1, add) 100 | assert.Equal(t, 0, kb.Close()) 101 | 102 | KiwiClearError() 103 | } 104 | 105 | func TestAddWord(t *testing.T) { 106 | kb := NewBuilder("./base", 1, KIWI_BUILD_INTEGRATE_ALLOMORPH) 107 | add := kb.AddWord("아버지가", "NNG", 0) 108 | 109 | assert.Equal(t, 0, add) 110 | 111 | kiwi := kb.Build() 112 | res, _ := kiwi.Analyze("아버지가 방에 들어가신다", 1, KIWI_MATCH_ALL) 113 | 114 | // kb should have been closed. 115 | assert.Equal(t, 0, kb.Close()) 116 | 117 | expected := []TokenResult{ 118 | { 119 | Tokens: []TokenInfo{ 120 | { 121 | Position: 0, 122 | Tag: "NNG", 123 | Form: "아버지가", 124 | }, 125 | { 126 | Position: 5, 127 | Tag: "NNG", 128 | Form: "방", 129 | }, 130 | { 131 | Position: 6, 132 | Tag: "JKB", 133 | Form: "에", 134 | }, 135 | { 136 | Position: 8, 137 | Tag: "VV", 138 | Form: "들어가", 139 | }, 140 | { 141 | Position: 11, 142 | Tag: "EP", 143 | Form: "시", 144 | }, 145 | { 146 | Position: 11, 147 | Tag: "EF", 148 | Form: "ᆫ다", 149 | }, 150 | }, 151 | Score: -32.80881, 152 | }, 153 | } 154 | 155 | if diff := cmp.Diff(expected, res, floatComparer()); diff != "" { 156 | t.Errorf("AddWord result mismatch (-want +got):\n%s", diff) 157 | } 158 | assert.Equal(t, 0, kiwi.Close()) 159 | } 160 | 161 | func TestLoadDict(t *testing.T) { 162 | kb := NewBuilder("./base", 1, KIWI_BUILD_INTEGRATE_ALLOMORPH) 163 | add := kb.LoadDict("./example/user_dict.tsv") 164 | 165 | assert.Equal(t, 1, add) 166 | 167 | err := KiwiError() 168 | 169 | assert.Equal(t, "", err) 170 | 171 | kiwi := kb.Build() 172 | 173 | // kb should have been closed already. 174 | assert.Equal(t, 0, kb.Close()) 175 | 176 | res, _ := kiwi.Analyze("아버지가 방에 들어가신다", 1, KIWI_MATCH_ALL) 177 | 178 | expected := []TokenResult{ 179 | { 180 | Tokens: []TokenInfo{ 181 | { 182 | Position: 0, 183 | Tag: "NNG", 184 | Form: "아버지가", 185 | }, 186 | { 187 | Position: 5, 188 | Tag: "NNG", 189 | Form: "방", 190 | }, 191 | { 192 | Position: 6, 193 | Tag: "JKB", 194 | Form: "에", 195 | }, 196 | { 197 | Position: 8, 198 | Tag: "VV", 199 | Form: "들어가", 200 | }, 201 | { 202 | Position: 11, 203 | Tag: "EP", 204 | Form: "시", 205 | }, 206 | { 207 | Position: 11, 208 | Tag: "EF", 209 | Form: "ᆫ다", 210 | }, 211 | }, 212 | Score: -32.80881, 213 | }, 214 | } 215 | 216 | if diff := cmp.Diff(expected, res, floatComparer()); diff != "" { 217 | t.Errorf("LoadDict result mismatch (-want +got):\n%s", diff) 218 | } 219 | assert.Equal(t, 0, kiwi.Close()) 220 | } 221 | 222 | func TestLoadDict2(t *testing.T) { 223 | kb := NewBuilder("./base", 1, KIWI_BUILD_INTEGRATE_ALLOMORPH) 224 | add := kb.LoadDict("./example/user_dict2.tsv") 225 | 226 | assert.Equal(t, 3, add) 227 | 228 | err := KiwiError() 229 | 230 | assert.Equal(t, "", err) 231 | 232 | kiwi := kb.Build() 233 | res, _ := kiwi.Analyze("아버지가 방에 들어가신다", 1, KIWI_MATCH_ALL) 234 | 235 | expected := []TokenResult{ 236 | { 237 | Tokens: []TokenInfo{ 238 | { 239 | Position: 0, 240 | Tag: "NNG", 241 | Form: "아버지가", 242 | }, 243 | { 244 | Position: 5, 245 | Tag: "NNG", 246 | Form: "방에", 247 | }, 248 | { 249 | Position: 8, 250 | Tag: "NNG", 251 | Form: "들어가신다", 252 | }, 253 | }, 254 | Score: -12.538677, 255 | }, 256 | } 257 | 258 | if diff := cmp.Diff(expected, res, floatComparer()); diff != "" { 259 | t.Errorf("LoadDict2 result mismatch (-want +got):\n%s", diff) 260 | } 261 | assert.Equal(t, 0, kiwi.Close()) 262 | } 263 | 264 | func TestExtractWord(t *testing.T) { 265 | kb := NewBuilder("./base", 1, KIWI_BUILD_DEFAULT) 266 | rs := strings.NewReader(`2008년에는 애국가의 작곡자 안익태가 1930년대에 독일 유학 기간 중 친일 활동을 했다는 사실이 밝혀졌다. 이후 안익태가 나치 독일 하의 267 | 베를린에서 만주국 10주년 건국 기념음악회를 지휘하는 동영상까지 발굴되어 관련 학계나 사회에 큰 충격을 주었다. 안익태가 친일 행적을 한 바 268 | 있다는 빼도박도 못할 증거가 나왔으니까. 영상물의 '만주환상곡'에는 우리가 현재 알고있는 '한국환상곡'의 두 선율("무궁화 삼천리 나의 사랑아, 269 | 영광의 태극기 길이 빛나라", "화려한 강산 한반도, 나의 사랑 한반도 너희 뿐일세")에 거의 그 모습 그대로 나타난다. # 이로 인해 애국가의 270 | 본이 되는 한국환상곡은 사실 만주국 창립 기념을 위한 만주환상곡에서 따왔다는 주장이 제기되었고, 일각에서는 현재의 애국가는 가사(공식적으론 작사 271 | 미상이나 가장 유력한 윤치호 작사를 인정 못해서 그렇다는게 중론), 곡(안익태 작곡) 모두 친일파의 산물이라고 주장하며 국가 재제정 운동을 272 | 벌이기도 하였다. 만약 애국가 악곡의 일부를 만주환상곡에서 가져왔다는 주장이 사실이라면 이 문제가 언젠가 공론화가 된다면 국가 교체가 이루어질 273 | 가능성이 크다. 다만 가사의 경우 만약 윤치호가 실제 작사한 것이 사실이라고 하더라도 일제시대가 되기도 이전인 대한제국 시절 작사된 것이기 274 | 때문에 친일의 산물은 아니다.`) 275 | wordInfos, _ := kb.ExtractWords(rs, 3 /*=minCnt*/, 3 /*=maxWordLen*/, 0.0 /*=minScore*/, -3.0 /*=posThreshold*/) 276 | expected := []WordInfo{ 277 | { 278 | Form: "안익", 279 | Freq: 3, 280 | POSScore: -1.92593, 281 | Score: 0, 282 | }, 283 | { 284 | Form: "익태", 285 | Freq: 4, 286 | POSScore: -0.23702252, 287 | Score: 0, 288 | }, 289 | } 290 | if diff := cmp.Diff(expected, wordInfos, floatComparer()); diff != "" { 291 | t.Errorf("ExtractWord result mismatch (-want +got):\n%s", diff) 292 | } 293 | assert.Equal(t, 0, kb.Close()) 294 | } 295 | 296 | func TestExtractWordwithFile(t *testing.T) { 297 | kb := NewBuilder("./base", 1, KIWI_BUILD_DEFAULT) // Use single thread for deterministic results 298 | file, _ := os.Open("./example/test.txt") 299 | 300 | wordInfos, _ := kb.ExtractWords(file, 10 /*=minCnt*/, 5 /*=maxWordLen*/, 0.0 /*=minScore*/, -25.0 /*=posThreshold*/) 301 | expectedWordInfo := WordInfo{ 302 | Form: "무위원", Freq: 17, POSScore: -1.7342134, Score: 0.69981515, 303 | } 304 | if diff := cmp.Diff(expectedWordInfo, wordInfos[0], floatComparer()); diff != "" { 305 | t.Errorf("ExtractWordwithFile result mismatch (-want +got):\n%s", diff) 306 | } 307 | assert.Equal(t, 0, kb.Close()) 308 | } 309 | -------------------------------------------------------------------------------- /postype.go: -------------------------------------------------------------------------------- 1 | package kiwi 2 | 3 | import "fmt" 4 | 5 | type POSType string 6 | 7 | // NOTE: update isValid function when adding a new POSType. 8 | // POS type definitions from Kiwi C++ library: 9 | // - Type https://github.com/bab2min/Kiwi/blob/18b4062f98cf3beaedac149fc511a2708891f71d/include/kiwi/Types.h#L188-L219 10 | // - String https://github.com/bab2min/Kiwi/blob/18b4062f98cf3beaedac149fc511a2708891f71d/src/Utils.cpp#L300 11 | const ( 12 | POS_UNKNOWN POSType = "UN" 13 | 14 | POS_NNG POSType = "NNG" 15 | POS_NNP POSType = "NNP" 16 | POS_NNB POSType = "NNB" 17 | POS_NR POSType = "NR" 18 | POS_NP POSType = "NP" 19 | 20 | POS_VV POSType = "VV" 21 | POS_VA POSType = "VA" 22 | POS_VX POSType = "VX" 23 | POS_VCP POSType = "VCP" 24 | POS_VCN POSType = "VCN" 25 | 26 | POS_MM POSType = "MM" 27 | 28 | POS_MAG POSType = "MAG" 29 | POS_MAJ POSType = "MAJ" 30 | 31 | POS_IC POSType = "IC" 32 | 33 | POS_JKS POSType = "JKS" 34 | POS_JKC POSType = "JKC" 35 | POS_JKG POSType = "JKG" 36 | POS_JKO POSType = "JKO" 37 | POS_JKB POSType = "JKB" 38 | POS_JKV POSType = "JKV" 39 | POS_JKQ POSType = "JKQ" 40 | POS_JX POSType = "JX" 41 | POS_JC POSType = "JC" 42 | 43 | POS_EP POSType = "EP" 44 | POS_EF POSType = "EF" 45 | POS_EC POSType = "EC" 46 | POS_ETN POSType = "ETN" 47 | POS_ETM POSType = "ETM" 48 | 49 | POS_XPN POSType = "XPN" 50 | 51 | POS_XSN POSType = "XSN" 52 | POS_XSV POSType = "XSV" 53 | POS_XSA POSType = "XSA" 54 | POS_XSM POSType = "XSM" 55 | 56 | POS_XR POSType = "XR" 57 | 58 | POS_SF POSType = "SF" 59 | POS_SP POSType = "SP" 60 | POS_SS POSType = "SS" 61 | POS_SSO POSType = "SSO" 62 | POS_SSC POSType = "SSC" 63 | POS_SE POSType = "SE" 64 | POS_SO POSType = "SO" 65 | POS_SW POSType = "SW" 66 | POS_SL POSType = "SL" 67 | POS_SH POSType = "SH" 68 | POS_SN POSType = "SN" 69 | POS_SB POSType = "SB" 70 | 71 | POS_W_URL POSType = "W_URL" 72 | POS_W_EMAIL POSType = "W_EMAIL" 73 | POS_W_HASHTAG POSType = "W_HASHTAG" 74 | POS_W_MENTION POSType = "W_MENTION" 75 | POS_W_SERIAL POSType = "W_SERIAL" 76 | POS_W_EMOJI POSType = "W_EMOJI" 77 | 78 | POS_Z_CODA POSType = "Z_CODA" 79 | POS_Z_SIOT POSType = "Z_SIOT" 80 | 81 | POS_USER_0 POSType = "USER0" 82 | POS_USER_1 POSType = "USER1" 83 | POS_USER_2 POSType = "USER2" 84 | POS_USER_3 POSType = "USER3" 85 | POS_USER_4 POSType = "USER4" 86 | 87 | POS_VV_I POSType = "VV-I" 88 | POS_VA_I POSType = "VA-I" 89 | POS_VX_I POSType = "VX-I" 90 | POS_XSA_I POSType = "XSA-I" 91 | 92 | POS_VV_R POSType = "VV-R" 93 | POS_VA_R POSType = "VA-R" 94 | POS_VX_R POSType = "VX-R" 95 | POS_XSA_R POSType = "XSA-R" 96 | 97 | POS_V POSType = "V" 98 | ) 99 | 100 | func (p POSType) isValid() bool { 101 | switch p { 102 | case 103 | POS_UNKNOWN, 104 | POS_NNG, 105 | POS_NNP, 106 | POS_NNB, 107 | POS_NR, 108 | POS_NP, 109 | POS_VV, 110 | POS_VA, 111 | POS_VX, 112 | POS_VCP, 113 | POS_VCN, 114 | POS_MM, 115 | POS_MAG, 116 | POS_MAJ, 117 | POS_IC, 118 | POS_JKS, 119 | POS_JKC, 120 | POS_JKG, 121 | POS_JKO, 122 | POS_JKB, 123 | POS_JKV, 124 | POS_JKQ, 125 | POS_JX, 126 | POS_JC, 127 | POS_EP, 128 | POS_EF, 129 | POS_EC, 130 | POS_ETN, 131 | POS_ETM, 132 | POS_XPN, 133 | POS_XSN, 134 | POS_XSV, 135 | POS_XSA, 136 | POS_XSM, 137 | POS_XR, 138 | POS_SF, 139 | POS_SP, 140 | POS_SS, 141 | POS_SSO, 142 | POS_SSC, 143 | POS_SE, 144 | POS_SO, 145 | POS_SW, 146 | POS_SL, 147 | POS_SH, 148 | POS_SN, 149 | POS_SB, 150 | POS_W_URL, 151 | POS_W_EMAIL, 152 | POS_W_HASHTAG, 153 | POS_W_MENTION, 154 | POS_W_SERIAL, 155 | POS_W_EMOJI, 156 | POS_Z_CODA, 157 | POS_Z_SIOT, 158 | POS_USER_0, 159 | POS_USER_1, 160 | POS_USER_2, 161 | POS_USER_3, 162 | POS_USER_4, 163 | POS_VV_I, 164 | POS_VA_I, 165 | POS_VX_I, 166 | POS_XSA_I, 167 | POS_VV_R, 168 | POS_VA_R, 169 | POS_VX_R, 170 | POS_XSA_R, 171 | POS_V: 172 | return true 173 | default: 174 | return false 175 | } 176 | } 177 | 178 | // ParsePOSType return POS Tag for resault 179 | func ParsePOSType(t string) (POSType, error) { 180 | pos := POSType(t) 181 | if !pos.isValid() { 182 | return POS_UNKNOWN, fmt.Errorf("POS type parse err. input type: %s", t) 183 | } 184 | return pos, nil 185 | } 186 | -------------------------------------------------------------------------------- /postype_test.go: -------------------------------------------------------------------------------- 1 | package kiwi 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestParsePOSType(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | arg string 13 | want POSType 14 | wantErr bool 15 | }{ 16 | { 17 | name: "NNG is a POSType", 18 | arg: "NNG", 19 | want: POS_NNG, 20 | wantErr: false, 21 | }, 22 | { 23 | name: "WHATEVER is not a valid POSType", 24 | arg: "WHATEVER", 25 | want: POS_UNKNOWN, 26 | wantErr: true, 27 | }, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | got, err := ParsePOSType(tt.arg) 32 | 33 | if tt.wantErr { 34 | assert.Error(t, err) 35 | } else { 36 | assert.NoError(t, err) 37 | } 38 | assert.Equal(t, tt.want, got) 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/install_kiwi.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # e.g. v0.10.2 4 | KIWI_VERSION="$1" 5 | 6 | if [ "$(uname)" == "Linux" ]; then 7 | OS='lnx' 8 | elif [ "$(uname)" == "Darwin" ]; then 9 | OS='mac' 10 | elif [ "$(uname)" == "Windows" ]; then 11 | OS='win' 12 | fi 13 | 14 | if [ "$(uname -m)" == "arm64" ]; then 15 | ARCH="arm64" 16 | else 17 | ARCH="x86_64" 18 | fi 19 | 20 | echo "set OS env to ${OS:?}" 21 | echo "installing Kiwi version ${KIWI_VERSION:?}" 22 | 23 | wget -O kiwi.tgz "https://github.com/bab2min/Kiwi/releases/download/${KIWI_VERSION}/kiwi_${OS}_${ARCH}_${KIWI_VERSION}.tgz" && 24 | sudo tar xzvf kiwi.tgz -C /usr/local && 25 | [[ "$(uname)" == "Linux" ]] && sudo ldconfig || echo 'skip' && 26 | rm -f kiwi.tgz 27 | --------------------------------------------------------------------------------