{"id":22685145,"url":"https://github.com/lpapailiou/fac","last_synced_at":"2026-05-04T02:31:22.403Z","repository":{"id":138641972,"uuid":"350435648","full_name":"lpapailiou/fac","owner":"lpapailiou","description":"A toy programming language including jflex scanner, cup parser and semantic validation. Executably by console and by gui (a toy-IDE).","archived":false,"fork":false,"pushed_at":"2021-07-17T14:05:31.000Z","size":2584,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T15:14:49.513Z","etag":null,"topics":["automaton","bnf","compiler-construction","cup","flex","flex-cup","formal-language","interpreter","java","java-8","javafx","javafx-application","jflex","parser","programming-language","regex","theoretical-computer-science","toy-language"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lpapailiou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-22T17:43:13.000Z","updated_at":"2023-12-20T16:19:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"ae4198a5-bcc4-41e7-918c-8af8e4f6aa83","html_url":"https://github.com/lpapailiou/fac","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/lpapailiou/fac","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpapailiou%2Ffac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpapailiou%2Ffac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpapailiou%2Ffac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpapailiou%2Ffac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lpapailiou","download_url":"https://codeload.github.com/lpapailiou/fac/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpapailiou%2Ffac/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32592312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["automaton","bnf","compiler-construction","cup","flex","flex-cup","formal-language","interpreter","java","java-8","javafx","javafx-application","jflex","parser","programming-language","regex","theoretical-computer-science","toy-language"],"created_at":"2024-12-09T22:13:20.889Z","updated_at":"2026-05-04T02:31:22.374Z","avatar_url":"https://github.com/lpapailiou.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FAC\nThis repository connects the two theoretical computer science disciplines ``formal languages`` and ``automatons`` with\nthe rather technical discipline of ``compiler construction`` (\u003cb\u003eF.A.C.\u003c/b\u003e).  \nThe goal is to specify a new programming language, which is deterministic and executable.  \n  \nIt contains the language specification, as well as possibilities to execute the toy-language from\nthe terminal or from a mini-IDE (implemented with ``javafx``).\n\n![jlang](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_gui.png)\n\n## Table of Contents\n1. [Language design](#language-design)  \n\t1.1 [Scope](#scope)  \n\t1.2 [Lexical rules](#lexical-rules)  \n\t1.3 [Syntactical rules](#syntactical-rules)  \n\t1.4 [Semantic rules](#semantic-rules)  \t  \n\t1.5 [Execution](#execution)    \n2. [Repository handling](#repository-handling)  \n\t2.1 [Clone](#clone)   \n\t2.2 [Package structure](#package-structure)   \n\t2.3 [Run with console](#run-with-console)    \n\t2.4 [Run with gui](#run-with-gui)  \t  \n\t2.5 [Generate](#generate)  \t  \n\n## Language design\nIn this section, the language design will be documented with its rules and a few examples. \n### Scope\nOur new toy language design has roughly following scope:  \n- variable declarations and assignments\n- string concatenation\n- arithmetic expressions\n- conditional expressions\n- conditional statements\n- loops\n- function calls\n- function definitions\n- built-in print function\n\nIt is a type safe programming language with three available data types: strings, numbers and booleans, while\n``null`` will never be an acceptable value.  \nClasses and other complex concepts are not supported.  \n  \nThe look-and-feel will be Java-like. Here's a small code sample:  \n\n    number one = 1;\n    while (one \u003c 5) {\n        one += 1;\n        print('hello world');\n    }\n\n### Lexical rules\nLexical rules are applied when the toy code is scanned by the ``Scanner``. During this process, one or multiple \ncharacters will be transformed to so-called tokens (i.e. words of the code). There is a limited set of allowed tokens, \nmeaning that unknown tokens will result in an error automatically.  \n  \nThe scanner used in this repository was generated with [jflex](https://jflex.de/). It can be found in the\npackage ``src\\main\\java\\scanner``.  \nThe token identification is implemented with regular expressions. \n\n    // sample section of .flex file\n    ==                                { return collectToken(EQ, \"EQ\"); }\n    \\!=                               { return collectToken(NEQ, \"NEQ\"); }\n    \u003e=                                { return collectToken(GREQ, \"GREQ\"); }\n    \\\u003c=                               { return collectToken(LEQ, \"LEQ\"); }\n\n#### Comments\nJava-like comments are allowed. They will be ignored in further processing of the code.  \nPattern: ``\\/*[^\\*]~\\*\\/ | \\/\\*(\\*)+\\/ | \\/\\/[^\\r\\n]*(\\r|\\n|\\r\\n)? | \\/(\\*)+[^\\*]*(\\*)+\\/``  \n#### Whitespace\nWhitespace may consist of spaces and newlines. It will be ignored in further processing steps, but\nis initially useful to separate tokens from each other.  \nPattern: ``[ \\t\\f\\r\\n]+`` \n#### Reserved words\nReserved words are: ``string``, ``number``, ``boolean`` (for data types), ``while``, ``break``,\n``if``, ``else``, ``def``, ``return`` (for statements) and ``print`` (for printing to the console).  \n#### Boolean values\nBoolean values may be either ``true`` or ``false``.  \n#### Numeric values\nNumeric values will be interpreted as Double. The length will not be checked.  \nPattern: ``-?[0-9]\\d*(\\.\\d+)?``  \n#### String values\nStrings may contain lowercase letters, digits and a few special characters. They must be enclosed\nin apostrophes.  \nPattern: ``'[a-z0-9_\\,\\.\\(\\)\\;\\:\\/\\+\\-\\*\\/ \\s\\t\\f\\r\\n]*'``  \n#### Variable identifiers\nVariable identifiers may consist of lowercase letters, underscores and optional digits at the end.  \nPattern: ``[a-z_]+([0-9])*``. \n#### Operators\nAdditionally, there is a set of basic operators.  \n- Arithmetic operators: ``+``, ``-``, ``*``, ``/``, ``%``.  \n- Conditional operators: ``==``, ``!=``, ``\u003c``, ``\u003e``, ``\u003c=``, ``\u003e=``.  \n- Assignment operators: ``=``, ``+=``, ``-=``, ``*=``, ``/=``, ``%=``.  \n- Evaluation operators: ``\u0026\u0026``, ``||``.  \n- Unary operators: ``-``, ``++``, ``--``, ``!``.\n#### Special characters\nFinally, there are two types of brackets: ``(``, ``)``, ``{``, ``}``, as well as the comma ``,`` \nand the infamous semicolon ``;``. \n\n### Syntactical rules\nSyntactical rules are applied by the ``Parser``. During the processing of the code, it will receive token by token\nfrom the scanner. The parser then validates if the sequence of tokens follows the defined grammatical rules (e.g. \na statement must stop always with a semicolon). If the code is valid, the parser will organize the identified components\n in a so called 'parse tree', which will be handy for further processing.   \n  \nThe parser used in this repository was generated with [cup](http://www2.cs.tum.edu/projects/cup/). It can be found in the\npackage ``src\\main\\java\\parser``.  \nThe syntactical rules are designed in the form of the Backus-Naur-notation, which allows context-free validation only. \n\n    // sample section of .cup file\n    ASSIGN \t        ::= VAR:e1 ASSIGN_OP:op EXPR:e2 STOP            {: RESULT = Statement.assgn(op, e1, e2); :}\n                        ;\n    \n    ASSIGN_OP       ::= EQUAL:op                                    {: RESULT = op; :}\n                        | PLUSEQ:op                                 {: RESULT = op; :}\n                        | MINEQ:op                                  {: RESULT = op; :}\n                        | DIVEQ:op                                  {: RESULT = op; :}\n                        | MULEQ:op                                  {: RESULT = op; :}\n                        ;\n\n#### Variable declarations\n- Variable declarations must start with a data type (``string``, ``number`` or ``boolean``).\n- The data type is followed by an identifier and an equal character.\n- Then, a value is assigned. The value can be:\n    - a string, number or boolean value according to lexical definition.\n    - another variable identifier.\n    - an arithmetic or conditional expression.\n    - a string concatenation.\n    - a function call.\n    - omitted. in this case, the equal character is omitted as well and the variable would get its default value (``''``, ``0.0`` or ``false``).\n- The variable declaration must end with a semicolon.\n- As the parser is context free, the data types of variable and assigned value cannot be evaluated further at this step.     \n    \nSample code:    \n        \n    string x1 = 1;                      // valid (no type safety yet)\n    number y;                           // valid (variable will get default value)\n    number y7 = (true \u0026\u0026 false);        // valid (conditional expressions can be assigned)\n    boolean 1z7 = (true \u0026\u0026 false);      // scanner fails, as variable identifier starts with a digit\n    string x8 = fun1();                 // valid (function calls can be assigned)\n    number y8 = print();                // parser fails, as print is a reserved word\n\n#### Variable assignments\n- Variable assignments share the rules of variable declarations, except:\n- the preceding data type must be omitted.\n- a value must be assigned.\n- arithmetic assignment operators are additionally allowed.\n- incrementing or decrementing (``++`` or ``--``) is allowed at this place only.        \n\nSample code:    \n\n    x1 = 1 + true;                  // valid (no type safety yet)\n    y;                              // parser fails, as a value must be assigned\n    x1++;                           // valid \n    y7 = (true \u0026\u0026 false);           // valid (conditional expressions can be assigned)\n    x8 = fun1()                     // parser fails, as semicolon is missing\n\n#### Expressions\n- Expressions in general cannot exist as isolated statement. They need to be part of a declaration or be assigned.\n- Arithmetic expressions are meant to perform numeric calculations. Therefore, they use specific operators (``+``, ``-``, ``*``, ``/``, ``%``).\n- For string concatenation, the ``+`` operator is allowed.\n- By default, their components can be either 'raw' values, expressions or function calls.\n- Precedence is handled as follows:\n    - unary expressions have highest precedence.\n    - multiplications, divisions and modulo operations follow.\n    - then, addition, subtraction follow.\n    - conditional expressions will always be in brackets, thus precedence must not be handled specifically.\n    - assignments have least precedence.\n    - if not handled otherwise, precedence applies left to right.\n- Expressions must never have brackets, except they are conditional expressions.\n- As expressions can be potentially assigned anywhere.\n- Also here, data types are not evaluated any further.   \n\nSample code:    \n\n    1 + 2                               // parser fails as expression cannot be isolated\n    x = 1 + 2 - 3;                      // valid, interpreted as ((1 + 2) - 3)\n    x = 2 * 4 + 2 / 3;                  // valid, interpreted as ((2 * 4) + (2 / 3))\n    x = fun();                          // valid (function calls can be assigned)\n    x = 'x' + 'abc';                    // valid (will result in string concatenation)\n    x = 123 + true;                     // valid (no type safety in parser)\n    x = (1 + 2);                        // parser fails, as brackets are not allowed\n\n\n#### Conditional expressions\n- Conditional expressions are quite similar to generic expressions, except they must be enclosed in (round) brackets.\n- Conditional expressions use comparing (``\u003c``, ``\u003c=``, ``==``, ...) or evaluating (``\u0026\u0026``, ``||``) operators.\n- Strings can be compared with ``==``.\n- Conditional expressions or boolean values can be switched by exclamation marks. The exclamation marks\ncannot be placed before the outer brackets if a conditional expression is used in a if-then or while statement.\n\nSample code:    \n\n    x = (true || false);                // valid\n    x = (1 \u003c 2);                        // valid\n    x = true \u0026\u0026 true;                   // parser fails, as brackets are missing\n    x = (true \u0026\u0026 true \u0026\u0026 false);        // parser fails, as round brackets must always enclose two components\n\n#### Function calls\n- Function calls consist of an identifier, followed by an opening round bracket, arguments, a closing bracket and a semicolon.\n- Arguments can be zero, one or multiple (comma separated) expressions.\n- Without the semicolon, a function call can be used as value within an expression, as it is expected to always have a return value.\n     \nSample code:    \n     \n    fun1();                             // valid (no parameter)\n    //fun()                             // parser fails, as semicolon is missing\n    fun2(1 + 2 + 4);                    // valid (expression as one parameter)    \n    fun3(true \u0026\u0026 false);                // valid (condition as parameter - in this case, one set of brackets is enough)\n    fun3((true \u0026\u0026 false), 1, 'abc');    // valid (multiple parameters)\n    fun(fun());                         // valid (but probably not nice)\n\n#### Print calls\nPrint calls work the same way as function calls, except:\n- they cannot have multiple parameters.\n- they do not have any return value. Therefore, they cannot be assigned to variables or be used in expressions.\n\nSample code:    \n\n    print();                            // valid (no parameter)\n    print(1 + 2 + 4);                   // valid (expression as one parameter)    \n    print(1 + 2 + 4, 'x');              // parser fails, as multiple parameters are not allowed\n    print(fun());                       // valid\n    x = print();                        // parser fails, as print calls cannot be used in assignments\n\n#### Function definitions\n- Function definitions must start with the ``def`` keyword, a data type and an identifier.\n- After the identifier, a parameter declaration list (which must be enclosed in round brackets) follows.\n- This declaration list can be empty or consist of one or multiple declarations.\n- A parameter declaration consists of a data type and an identifier.\n- After the parameter declarations, curly brackets open and close.\n- The function body may contain zero, one or multiple nested statements.\n- Just before the curly brackets are closed, a return statement must be placed. \n- The return statement consists of the return keyword, a return value (an expression) and a semicolon.\n\nSample code:    \n\n    def number fun() { return 1; }      // valid (minimal example)\n    boolean fun() { return x; }         // parser fails, as def keyword is missing\n    def fun() { return 1 + 1; }         // parser fails, as data type is missing\n    def string fun() { }                // parser fails, as return keyword is missing\n    def boolean f1(string x) {          // valid\n        print(x);\n        return x;\n    }\n\n#### Conditional statements\n- Conditional statements must start with the ``if`` keyword and a conditional expression (in round brackets).\n- Then, a body in curly brackets follows, which can contain zero, one or more statements.\n- Optionally, an ``else`` keyword may follow, with another body as above.\n\nSample code:    \n\n    if (true) {}                        // valid\n    if (1 \u003c 2) {};                      // parser fails, as no semicolon is allowed at end\n    if (false) {                        // valid\n        print('x');\n    } else {}\n\n#### While loops\n- while loops must start with the while keyword and a conditional expression (in round brackets).\n- Then, a body in curly braces follows, which can contain zero, one or more statements.\n\nSample code:    \n\n    while (true) {}                     // valid (but maybe not smart)\n    while false {}                      // parser fails, as conditional brackets are missing\n    while (false) {                     // parser fails, as body is not closed\n    while (false) {                     // valid\n        print('x');\n    }\n\n#### Statements\n- Statements are basically all grammatical structures, which do not require another surrounding construct to be valid.\nThey always must end with a semicolon (if they do not end with a body in curly brackets). Implemented statements are:\n    - variable declarations\n    - variable assignments\n    - function calls (including print calls)\n    - function definitions\n    - conditional statements\n    - while loops\n- Additionally, break statements do also count as statements. They are meant to be used within while loop bodies.\nAs they cannot be strictly at the end of a while body (they could be nested deeper within if-then-structures), the parser\nwill not perform any further syntactical validations in this case.\n- Nested statements are a list of statements. This is a helper structure to fill bodies of conditional statements, while loops\n and function definitions.\n- Function definitions must be 'top level' components (e.g. it is not possible to nest them in a while loop).\n- ll 'top level' statements and function definitions will finally be added to the program statements list.\n\nSample code:\n    \n    x;                                  // parser fails, as this is not a statement\n    number x = 1                        // parser fails, as semicolon is missing\n    if (true) {\n        def number x() {                // parser fails, as function definitions may not be nested\n            return 0;\n        }\n    }\n\n#### Program\n- The program is a container for the 'top level' list of program statements.\n- If the parser finishes without error, the program will be the root of the generated parse tree.\n\n### Semantic rules\nSo far, our toy language is defined and we have the tools to validate if a code belongs to our language or not. But at \nthis point, there is no type safety, variables can be assigned before they are declared and break statements\nare a mere decoration.  \n  \nThe required semantic validation must now be performed by a ``Validator`` (see ``src\\main\\java\\validator``).  \nThe validator will receive the parse tree from the parser and traverse it depth-first.\n\n#### Identifier scope\n- A variable must be declared before it can be referenced.\n- he same rule applies to function definitions and function calls.\n- Identifiers are valid within the same and lower levels of the parse tree, starting from the location where they are declared.\nWithin nested scope, they can be overwritten by local variables.\n- Identifiers must be unique within their scope, except for function identifiers, which can be overloaded.\n\nSample code:    \n\n    number x = 1;                       // valid\n    y = x;                              // validator fails as y was not instantiated\n    def string fun(string z) {          // valid\n        return z;\n    }\n    x = z;                              // validator fails, as z is out of scope\n \n#### Type safety\n- A variable can only assign values of the declared type.\n- A function must return the same type as it defines as return value.\n- If expressions are nested, the types are evaluated for every segment (assignment has least precedence).\n- If a segment of an expression is a string, the resulting type will be cast to a string, if possible.\n- String casting will not work within subtractions, multiplications, divisions and conditional expressions.\n\nSample code:    \n\n    string x = 1 + 2 + 'a';             // valid (nesting \u0026 string casting)\n    number y = true;                    // validator fails, as boolean is assigned to number type\n    x += true;                          // valid (string casting)\n    x = true;                           // validator fails, string casting can only occur in binary expression\n    x = 1 * 2;                          // validator fails, string casting can only occur in binary expression\n    def number fun() {                  // validator fails, as returned string is not a number\n        return 'x'; }\n\n#### Operator validation\n- In assignments, the operator ``=`` can be used for all data types, ``+=`` for numeric and string values, other operators (``-=``, ``*=``, ``/=``, ``%=``) for numeric values only.\n- In conditional expressions, ``==`` and != may be used for all types, ``!``, ``\u0026\u0026`` and ``||`` may used for boolean values only, comparing operators (``\u003c``, ``\u003c=``, ``\u003e=``, ``\u003e``) can be used for numeric values only.\n- In expressions, ``+`` is valid for numeric values or if at least one of the components is a string. All other available operators (``-``, ``*``, ``/``, ``%``) are for numeric values only.\n\nSample code:    \n\n    string x = 'x' + 'b';               // valid\n    x = 'x' - 'b';                      // validator fails, as minus cannot be used for string concatenation\n    boolean y = (true \u0026\u0026 1);            // validator fails, as the binaryOperator \u0026\u0026 can be used for booleans only\n    boolean z = (1 \u003c 2);                // valid\n    x = 1 * 'x';                        // validator fails, multiplication binaryOperator is not valid for strings\n\n#### Expressions\n- In general, both operands of a binary expression must have the same type.\n- The only exception is string casting.\n- The resulting value of a conditional expression must always be a boolean, generic expressions can evaluate to all data types.\n\nSample code:\n    \n    string a = '1' + 'abc' + '2';       // valid\n    string b = a + true;                // valid (string casting)\n    number c = 1 + true;                // validator fails, as not both operands are of type numeric\n    number d = 1 + 2 * 3 % 5;           // valid\n    boolean e = (true \u0026\u0026 !false);       // valid\n    boolean f = (true || 2);            // validator fails, as second operand is numeric\n    \n#### Function calls and function definitions\n- The declared return type must match the effective return type.\n- A function is identified by its identifier, return type, parameter count and parameter types. This means, overloading is possible.\n- Overloading may occur only, if the identifier matches, the return type matches and parameter count differs.\n- If a caller calls a function, the callee must have according parameter count, parameter types and return type.\n- A function can call itself, thus, recursion is allowed.\n\nSample code:    \n\n    def number x() {                // validator fails, as 'seven' is a string\n        return 'seven'; }\n    def number y() {                // valid\n        return 0; }\n    def number y() {                // validator fails, as function y() is already defined with 0 params and same return type\n        return 1; }\n\n#### Conditional statements and while loops\n- part from the break statement validation, no additional semantic validation is required in this case, as the syntactical checks are sufficient.\n\n#### Break statements\n- Break statements are only allowed within while loops, and never as top-level-statement.\n- Per while loop and nesting level, one break statement is allowed.\n- Exception: if a break loop contains an if-then-else statement, two breaks are allowed.\n- A break must be the last statement of a statement list, but can be nested within other statement lists. Thus, a simple validation for\nunreachable code occurs at this place.\n\nSample code:    \n\n    break;                              // validator fails, as break statement is dangling outside loop\n    while(true) {                       // validator fails, as there is unreachable code\n        break; number x = 1; }\n    while(false) {                      // valid\n        break; }        \n\n### Execution\n#### Concept\nThe 'execution' is handled by the ``Interpreter`` during runtime (i.e. no compilation occurs). It can be found in the \npackage ``src\\main\\java\\execution``. It is built on a validator, which means that it will automatically also\nvalidate code semantically before execution - even if the code itself will never run (e.g. in a dead if-then-else branch). \n  \nPlease note that global variables and function definitions must be declared always before being referenced. Thus, declarations must be \nplaced always before callers (not like Java, where global variables and functions may be defined anywhere in a file).  \n  \n#### Behavior\nIn the ``execute mode``, code will be processed character by character, in one go.  \n  \nIn the ``console mode``, entered code will be validated after pressing ``ENTER`` on a blank input line. This means, multiple lines\ncan be entered before validating (e.g. line breaks are allowed in between complex statements).  \nIf an entry is not valid, it will be rejected, the user may then try again (so far valid code will remain in memory). \nAfter every ``ENTER``, the whole so-far-valid code is validated, which means the parse tree may be built multiple times.  \nAlso, only the last print statement may be actually printed, to give the user a scripting-like experience. \n  \nIn the ``gui mode``, code can be executed at once by pressing on the button ``go``, or by editing the input, if the input ends with two newline characters.  \nIf the ``go`` button is used, the mini-IDE may open the execution or validation tab, and - in case of errors - select the faulty input section (if possible).  \n\n#### Exception and error handling\nIn general, exceptions and errors are supposed to be catched by the application. The purpose is to allow the user to apply\ncorrections for the next run. In case an exception or error occurs, an according message (if possible) and the stack trace\nwill be visualized. Following incidents are taken to account:\n- Unknown tokens will throw errors during scanning.\n- The parser may throw an exception if the parse tree cannot be build.\n- Semantic validation may throw more specific exceptions.\n- During runtime, arithmetic exceptions and stack overflow exceptions may occur.\n\nOne edge case is an infinite while loop. If discovered, a stack overflow error will be thrown to avoid \nthe program to hang.  \n\n## Repository handling\nThis section contains a few technical notes about this repository.\n### Clone\nClone the repository with following command.\n\n    git clone https://github.com/lpapailiou/fac \u003ctarget path\u003e\n\nThe code is written in ``java 8``.\nOnce the repository is cloned, ``maven`` may take care about the build, plugins and the dependencies. The ``javafx`` dependency will\nnot be handled by maven. \n  \nYou may also just download the jar file from [latest release](https://github.com/lpapailiou/fac/releases/latest).  \n\n### Package structure\nBelow, the structure of the package tree is listed for better overview.\n\n    + src\n        + main\n            + java\n                + exceptions                // custom exceptions\n                + execution                 // code execution handling by interpreter    \n                + main                      // --\u003e starts program\n                + parser                    // syntactical analysis              \n                    + parsetree                 // parse tree components\n                + scanner                   // lexical analysis \u0026 token generation\n                + validator                 // semantic validation                \n            + resources                  \n                + lib                       // external dependecies (jflex \u0026 cup)\n                + samples                   // code sample files\n\n### Run with console\nBy default, a start within the IDE or by a double click on the jar file, the [graphic user interface](#run-with-gui) will be launched.  \nThe console mode can be started, if the jar file is started from within the command line of your os.\nThe restriction is, that an additional argument must be used.  \n  \nBuild the jar file yourself or [download](https://github.com/lpapailiou/fac/releases/latest) directly.\nThen run it with following command:\n\n    java -jar fac.jar \u003cargument\u003e\n\n#### Launching\nThe main class ``Main`` has to be run with options to use the terminal. If ambiguous options (i.e. 'press any key') are given, \nthe [interactive console mode](#console-mode) will be launched.  \nThere's also a small menu available which provides some orientation:\n\n    // output of help menu (accessed with -h)\n    Following options are available:\n        -o scan\n        -o parse\n        -o validate \n        -o execute\n        -o gui          // with this method, the javafx gui is launched        \n    \n    Optionally you may enter a file path after the mode.\n\nIf a file path follows the mode, this specific file will be processed. Otherwise, a sample file will be run.  \nSeveral sample files are available in the directory ``src\\main\\resources\\samples``.\n\n##### Scan mode\nThe scanner will take a file and tokenize its content. The output is verbose, every processed token will be\nprinted accordingly to the console.\n\n    // sample output\n    scanning token {NUMTYPE}: found match \u003cnumber\u003e at line 1, column 0.\n    scanning token {VAR}: found match \u003cone\u003e at line 1, column 7.\n    scanning token {EQUAL}: found match \u003c=\u003e at line 1, column 11.\n    scanning token {NUM}: found match \u003c1\u003e at line 1, column 13.\n    scanning token {STOP}: found match \u003c;\u003e at line 1, column 14.\n    [...]\n    ...end of file reached at line 1, column 1.\n\n##### Parse mode\nThe parser will initialize a scanner. During processing, the parser will take token by token and validate if\nthe sequence follows the syntactical definition of the grammar. If no error occurs, the parser will generate\na parse tree. This means, that the syntax of the scanned code is valid.  \nAdditionally to the parse tree, it will print the parsed code to the console.\n\n    // sample output\n    [...]\n    ***** PARSE TREE *****\n    $ Program\n        $ StatementList\n            $ ProgramStatement\n                $ Statement\n                    $ VariableDeclaration\n                        $ Type\n                            $ number\n     [...]\n    \n    ***** PARSER RESULT *****\n    \n    number one = 1;\n    \n    while (one \u003c 5) {\n        one += 1;\n        print('hello world');\n    }\n    \n##### Validation mode\nThis mode will run a parser as above.\nAs soon as the parse tree is ready, the validator will traverse the tree and validate semantic rules.  \n\n    // sample output\n    [...]   \n    ***** SEMANTIC CHECK SUCCEEDED *****\n\n##### Execution mode\nThe interpreter is built on an validator. The process is similar to the validator mode, but the interpreter\nwill similarly validate and execute the interpreted code.\n\n    // sample output\n    ***** EXECUTION RESULT *****\n  \n    \u003e\u003e\u003e\u003e  hello world\n    \u003e\u003e\u003e\u003e  hello world\n    \u003e\u003e\u003e\u003e  hello world\n    \u003e\u003e\u003e\u003e  hello world\n\n##### Console mode\nThe console mode starts an interpreter in the console. This version is interactive. For every entered code block, the\nwhole so-far valid code will be scanned, parsed, interpreted and directly be executed.  \n\nIn case of an error, the last entry will be ignored. New code can be added to the so-far valid code.  \nThe console mode can be escaped with -h or -q.\n\n    // sample output\n    (press -h for help or -q to quit)\n    **************************************************************\n    *                      WELCOME TO JLANG                      *\n    **************************************************************\n    \u003e  ... initialized \u0026 ready to code!                                 // from here on, user input is accepted\n    \u003e  number one = 1;\n    \u003e  while (one \u003c 2) {one += 1; print('hello world'); }\n    \u003e                                                                   // empty line triggering execution\n    \u003e\u003e\u003e\u003e  hello world\n    \u003e  \n\n### Run with gui\nTo run the gui, you may do so directly from the IDE or from the [jar file](https://github.com/lpapailiou/fac/releases/latest).\nThe jar file must be started by double click or without arguments within the terminal:\n\n    java -jar fac.jar\n\nThe mini-IDE is implemented with javafx, which may be a restriction depending on the java version you use.\n\n![jlang](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_gui.png)\n\n#### Code input\nThere are multiple options to input code.  \nYou may enter code directly to the primary text area. Alternatively, you may upload\na file or choose a demo file provided by the according combobox. The available demo files are the ones from the directory ``src\\main\\resources\\samples``.  \n  \n![input](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_input.png)  \n  \nIf the input is validated and turns out to be invalid, the invalid section will be highlighted.  \n  \n![text highlight](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_highlight.png)   \n  \nIf code is edited manually and the code ends with two newlines, the code will be processed dynamically while\nyou are typing.  \nIn this case, the tabs won't switch automatically, so you can observe the tab of your choice.  \n\n#### Execution\nThe secondary area is split up in multiple tabs. It will show the results of the processing of your code in\nthe order of processing.   \n  \n![tabs](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_tabs.png)  \n  \n##### Scanned tokens tab\nIn this tab, the scanned tokens are listed in the order of scanning.  \nAll tokens appearing are valid. If an error occurs, the according token is hinted specifically.\n    \n![scanned tokens](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_scan.png)  \n  \n##### Parse tree tab\nThis tab shows a visualization of the parse tree. The format does whether completely match the parse tree of the parser,\nnor the structure of the classes generated while parsing. The result is basically a close-as-possible reconstruction.\nImportant is: if the parse tree could be generated, the syntax of the code is valid.\n    \n![parse tree](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_parsetree.png)  \n \n##### Parsed code tab\nThis tab shows the code as pretty-printed interpretation of the input by the parser. \nIt should match the input, except the comments and excess whitespaces / line breaks are gone.  \nAlso here: if the code is visible, the syntax of the code is valid.  \n \n![parsed code](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_parsedcode.png)  \n\n##### Execution result tab\nThis is probably the most interesting tab, as it shows the result of the execution of the code.  \nIf it appears, it means that all validations (lexical, syntax, semantics) were successful. At this point,\nit is still possible that runtime errors occur (e.g. stack overflow, division by zero, etc.).\n    \n![execution result](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_executionresult.png)  \n\n##### Validation tab\nThis is the 'annoying' tab, as it will open as soon as something went wrong. It will show a short error message\nand reveal further details about the problem. The stack trace is printed additionally. \nWith this tab, the toy code can be debugged if needed.\n    \n![validation](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_validation.png)  \n  \n#### Action area\nThe mini-IDE has also a little 'action area', which should improve usability.  \n\n![action area](https://raw.githubusercontent.com/lpapailiou/fac/master/src/main/resources/img/jlang_actionarea.png) \n\nThe code processing can be triggered at once by pushing the button ``go``. As soon as the input is\nvalidated, check marks will indicate if the processing was successful, or - if not - at which step the problem occurred.  \nAdditionally, a tab switch is triggered by the ``go`` button. If the code is valid, it will show the execution result, otherwise\nthe validation tab.\n\nFurthermore, there are additional minor features:\n- The theme can be switched between dark mode and light mode.\n- The orientation of the split pane an be switched (vertical vs. horizontal).\n- The help button will open this very page for easy access to additional information.\n\n### Generate\nIn case you may want to modify the language rules, the scanner and parser can be generated easily with following commands.\n#### Scanner generation\nTo generate a new scanner from the flex file, run following command (java path must be set).  \n\n    java -jar src/main/resources/lib/jflex-full-1.8.2.jar src/main/java/scanner/jscanner.flex\n    \nOr use following maven command:\n\n    mvn jflex:generate    \n    \nHere's the [link to the external jflex documentation](https://jflex.de/).    \n\n#### Parser generation\nTo generate a new parser from the cup file, run following command (java path must be set).  \n\n    java -jar src/main/resources/lib/java-cup-11b.jar -interface -destdir src/main/java/parser/ -symbols JSymbol -parser JParser src/main/java/parser/jparser.cup\n\nOr use following maven command:\n\n    mvn cup:generate    \n        \nHere's the [link to the external cup documentation](http://www2.cs.tum.edu/projects/cup/).    ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpapailiou%2Ffac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flpapailiou%2Ffac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpapailiou%2Ffac/lists"}