{"id":20367507,"url":"https://github.com/regb/scala-smtlib","last_synced_at":"2025-04-12T05:29:00.880Z","repository":{"id":13423983,"uuid":"16112694","full_name":"regb/scala-smtlib","owner":"regb","description":"Scala library for parsing and printing the SMT-LIB format","archived":false,"fork":false,"pushed_at":"2022-12-30T11:07:14.000Z","size":971,"stargazers_count":44,"open_issues_count":4,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-26T00:51:23.474Z","etag":null,"topics":["scala","scala-library","smtlib","smtlibv2"],"latest_commit_sha":null,"homepage":"","language":"SMT","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/regb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-21T18:05:56.000Z","updated_at":"2024-08-07T21:05:13.000Z","dependencies_parsed_at":"2023-01-11T20:20:49.678Z","dependency_job_id":null,"html_url":"https://github.com/regb/scala-smtlib","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regb%2Fscala-smtlib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regb%2Fscala-smtlib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regb%2Fscala-smtlib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regb%2Fscala-smtlib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/regb","download_url":"https://codeload.github.com/regb/scala-smtlib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248522276,"owners_count":21118245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["scala","scala-library","smtlib","smtlibv2"],"created_at":"2024-11-15T00:32:39.211Z","updated_at":"2025-04-12T05:29:00.849Z","avatar_url":"https://github.com/regb.png","language":"SMT","funding_links":[],"categories":[],"sub_categories":[],"readme":"Scala SMT-LIB [![Build Status](http://laraquad4.epfl.ch:9000/regb/scala-smtlib/status/master)](http://laraquad4.epfl.ch:9000/regb/scala-smtlib)\n=============\n\nScala SMT-LIB is a lightweight, no dependency, abstraction over the\n[SMT-LIB](http://www.smtlib.org/) standard for Satisfiability Modulo Theory\n(SMT) solvers. It lets you use a type safe Scala API to build SMT-LIB scripts\nand ship them to any SMT-LIB complient solver over a process interface.\n\nScala SMT-LIB provides the tools for parsing and printing the SMT-LIB syntax.\nIt can help you if you need to communicate with a native SMT solver process via its\ntext interface. You can also write a Scala wrapper around an SMT solver and use\nit with a friendlier API. You could even get crazier and use a [pure Scala SMT\nsolver](https://github.com/regb/cafesat) that happens to implement the SMT-LIB\napi.\n\nThe library is still under active development and is evolving along with the\nneeds of the projects using it. Essentially it means the API is going to change\nquite frequently until we are satisfied with how it feels. However, the code is\nactually quite robust, and comes with an extensive test suite. You should not fear\nrelying on a current snapshot.\n\nApplications\n------------\n\nScala SMT-LIB deals with the messy details of parsing and writing SMT-LIB. It\nprovides a programmer friendly interface to simplify the development of tools\nthat rely on SMT-LIB.\n\nYou may want to use Scala SMT-LIB if:\n* You plan to write a tool that will use SMT-LIB as its input format, but do\n  not wish to spend too much time figuring out the SMT-LIB standard. Then you can\n  plug-in the parser component of Scala SMT-LIB in your tool and only deal with\n  the Scala representation of the few SMT-LIB commands of your interest.\n* You need to output a complex SMT-LIB encoding of some mathematical problems. We got\n  you covered: You can programatically build a set of expressions using the\n  Scala SMT-LIB abstract syntax tree, and use the printer components to get\n  a valid SMT-LIB representation to pass along to another tool.\n* You need to query an external black-box SMT solver, but the task of setting\n  up a proper communication with this strange beast seems a bit too daunting?\n  Scala SMT-LIB offers a module that abstracts SMTLIB-compliant solvers. You\n  can program your tool against this simple high-level API. Scala SMT-LIB\n  provides integration with [Z3](https://github.com/Z3Prover/z3) and\n  [CVC4](http://cvc4.cs.nyu.edu/web/) out of the box, and you can add support\n  for any other solver by implementing a relatively thin interface.\n   \n\nSetup\n-----\n\nThe latest stable release for Scala 2.13 is available on Sonatype, simply add\nthe following to your `build.sbt`:\n\n    libraryDependencies += \"com.regblanc\" %% \"scala-smtlib\" % \"0.2.1-42-gc68dbaa\"\n\nGetting Started with Examples\n-----------------------------\n\nTo construct a parser, you will need a java.io.Reader and a lexer:\n\n    val is = new java.io.FileReader(\"INPUT\")\n    val lexer = new smtlib.lexer.Lexer(is)\n    val parser = new smtlib.parser.Parser(lexer)\n\nThe parser then provides a `parseCommand` functions that will consume the input\nuntil the end of command:\n\n    val script: List[Command] = {\n      var cmds = new ListBuffer[Command]\n      var cmd:Command = null\n      while({cmd = parser.parseCommand; cmd != null})\n        cmds.append(cmd)\n      cmds.toList\n    }\n\n`parseCommand` returns `null` when the end of file is reached.\n\nYou can decompose a command using pattern matching:\n\n    import smtlib.parser.Commands._\n    cmd match {\n      case Assert(term) =\u003e ???\n      case CheckSat() =\u003e ???\n      case Pop(1) =\u003e ???\n    }\n\nIf you want to generate a script to feed to a solver, you can build the AST\nexplicitly, and use the pretty printers:\n\n    import smtlib.parser.Commands._\n    import smtlib.parser.theories.Ints._\n    val x = QualifiedIdentifier(SimpleIdentifier(SSymbol(\"x\")))\n    val y = QualifiedIdentifier(SimpleIdentifier(SSymbol(\"y\")))\n    val formula = Assert(LessThan(NumeralLit(0), Plus(x, y)))\n    smtlib.printer.RecursivePrinter.toString(formula) //(assert (\u003c 0 (+ x y)))\n    \nThe above is a little bit verbose due to the objective of supporting all of\nSMT-LIB. We are hoping to provide a nicer API in the future to build SMT-LIB\nscripts, at least in the common cases, but the AST will probably remain at the\ncore of the library.\n\nLow Level API\n-------------\n\nThis section introduces the low level API of Scala SMT-LIB. In the future, it is\nexpected to be wrapped by a higher-level API to perform most common operations.\nHowever, that API is expected to remain relatively stable and at the core of the\nlibrary, so if that fits your needs you should be able to safely use it. It comes\nwith a relatively extensive test suite to make sure it is working as expected.\n\n\n### Lexing\n\nThe [`lexer`](/src/main/scala/smtlib/lexer) package implements low level\nparsing of [`Tokens`](/src/main/scala/smtlib/lexer/Tokens.scala), The \n[`Lexer`](/src/main/scala/smtlib/lexer/Lexer.scala) lexes the input into\ntokens. It reads lazily from a `java.io.Reader`, on invocation of the `nextToken`\nmethod:\n\n    class Lexer(reader: java.io.Reader) { \n      def nextToken: Token = { ... }\n    }\n\nOne call to `nextToken` will only consume the input until the end of the\ncurrent token. It will read one character at a time from the input `Reader`\nuntil it was able to unambiguously identify the end of the token. You can\nprovide a buffered input as a way to improve performance on some use cases.\n\n`nextToken` either returns a valid `Token`, or `null` if EOF is reached in the\ninput `Reader`. It will signal errors with exceptions: a value of `null` is not\nan error and is expected to be eventually reached (unless the input never ends,\nsuch as `stdin`). The following two exceptions can be thrown by the lexer:\n\n* `UnexpectedCharException` signals that an error in the input. It corresponds\n  to a malformed token --- for example, a `#ffff` (instead of `#xffff`) would\n  throw the exception on the first `f`. The exception indicates the position\n  in the input.\n* `UnexpectedEOFException` occurs when the EOF is reached in the middle of an\n  un-completed token. For example, a string literal which is not closed before\n  the EOF.\n\n\n### Parsing\n\nUsually one does not need to work on a token by token basis, and is only\ninterested in fully formated SMT-LIB expressions. The\n[`parser`](/src/main/scala/smtlib/parser) provides the extraction of SMT-LIB\nexpressions. The [`Parser`](/src/main/scala/smtlib/parser/Parser.scala) consumes\ntokens generated by the above lexer:\n\n    class Parser(lexer: smtlib.lexer.Lexer) { \n      def nextCommand: Command = { ... }\n      def nextTerm: Term = { ... }\n    }\n\nIt provides many `nextX` methods (more than shown above) to parse any expressions\ndefined by the SMT-LIB standard grammar. The more common are the `nextCommand`\nand the `nextTerm` to parse respectively a command and a term-formula expression.\n\nA `Parser` uses exceptions to signal parsing error, they are defined in the\n[`Parser` companion object](/src/main/scala/smtlib/parser/Parser.scala). They\nprovide a bunch of information, including the token on which the parsing\nfailed, the expected tokens, and the position in the input (the position is an\nattribute of the token and can be accessed through it).\n\nA `Command` is the root of a complex abstract syntax tree (AST) representing\nthe corresponding SMT-LIB command. A few commands take as\nparameter a `Term`. Their ASTs are defined\n[here](/src/main/scala/smtlib/trees/Trees.scala).\n\n### Printing\n\nThe [`printer`](/src/main/scala/smtlib/printer) helps with printing out SMT-LIB\ncomplient commands. This means that the output of a printer can be send\ndirectly to an SMT solver.\n\n### Standard Theories\n\nFinally the [`theories`](/src/main/scala/smtlib/theories) module provides tree\nbuilders to create theory-specific formulas. Each theory module provides\n`apply` and `unapply` methods on various object to manipulate the `Term`\nrepresenting the actual theory expression.\n\nDevelopment\n-----------\n\nThe library is still under development and the API will likely go through quite a few\nchanges. It was originally part of [CafeSat](https://github.com/regb/scabolic)\nand has been made standalone in order for the\n[Leon](https://github.com/epfl-lara/leon) project to rely on it.\nHopefully, it can be useful to other people as well.\n\n### Testing\n\nIn order to attain a decent level of quality, there is a relatively strict policy for testing.\nTesting is separated in two levels of testing: unit tests and integration tests. Unit test\nare dependency free and run entirely in memory. While integration tests will rely on things\nlike file system and external solvers. Unit test are very fast and should be easy to run as part\nof a regular build cycle (you can run them after each compile), while integration tests are a bit\nslower and are meant to pass on each commit.\n\nIn SBT, the command `sbt test` will run the unit test suite, while the command\n`sbt it:test` will run the integration test suite. During developement, it\nshould be fine to run in mode `~testQuick`.\n\n### Building the Sources\n\nThe project is built with [sbt](http://www.scala-sbt.org/). To build the\nlibrary, just type:\n\n    sbt package\n\nIt will produce a jar that you can add to the classpath of your own project.\n\nIf you are building your project using sbt, it is possible to setup a reference\nto this github repository in the build system to automatically get the most\nrecent build. [Here](https://github.com/regb/cafesat/blob/master/build.sbt) is\nan example of how to do it, you can pick any commit. If you are interested in\nthis route, you should check the sbt official documentation.\n\nOptionally, you can test Scala SMT-LIB in your environment by running the test\nsuite. The tests are organized in unit and functional tests. Tu run the unit\ntests (very fast) you can type:\n\n    sbt test\n\nAll tests should pass. Please open an issue if any test is failing. The\nfunctional tests are testing end-to-end flows of Scala SMT-LIB. They do take a\nbit more time and require some setup in your environment. In particular, they\nwill try to use the SMT solvers `z3` and/or `cvc4` if they are available in\nyour PATH (the commands tried are exactly `z3` and `cvc4`). If present in the\nPATH, Scala SMT-LIB will test its interpreter module directly against these SMT\nsolvers. You can run those tests with:\n\n    sbt it:test\n\nChangelog\n---------\n\nSee [Changelog](/CHANGELOG.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregb%2Fscala-smtlib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fregb%2Fscala-smtlib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregb%2Fscala-smtlib/lists"}