{"id":12006,"date":"2023-02-04T13:00:04","date_gmt":"2023-02-04T12:00:04","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=12006"},"modified":"2023-11-08T18:13:43","modified_gmt":"2023-11-08T17:13:43","slug":"islandsql-episode-1-select-statement","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/","title":{"rendered":"IslandSQL Episode 1:  Select Statement"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>An island grammar focuses only on a small part of a grammar. The island represents the small, interesting part and the sea the rest. In this blog post, I explain the components of an island grammar for SQL scripts named IslandSQL. In the first iteration, we focus on the <code>select<\/code>&nbsp;statement. Everything else is not of interest for the time being.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use Case<\/h2>\n\n\n\n<p>Let&#8217;s assume we want to write an extension for Visual Studio Code that can find text in <code>select<\/code> statements within SQL files of a workspace. So what is the difference to VSCode&#8217;s integrated text search? Well, the text search does not know what a <code>select<\/code> statement is. It finds occurrences of the search text in all kinds of places. In fact, identifying a <code>select<\/code> statement is not as easy as one might think.<\/p>\n\n\n\n<p>Let&#8217;s look at an example.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">demo1.sql: No select statements<\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/* select * from t1; *\/\n-- select * from t2;\nremark select * from t3;\nprompt select * from t4;\nbegin\n    sys.dbms_output.put_line('irrelevant: select * from t5;');\nend;\n\/\ncreate or replace procedure p is\nbegin\n   $if false $then irrelevant: select * from t6; $end\n   null;\nend;\n\/\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/* select * from t1; *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- select * from t2;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">remark <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t3;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">prompt <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t4;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    sys.dbms_output.put_line(<\/span><span style=\"color: #CE9178\">&#39;irrelevant: select * from t5;&#39;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">or<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">replace<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">procedure<\/span><span style=\"color: #D4D4D4\"> p <\/span><span style=\"color: #569CD6\">is<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   $<\/span><span style=\"color: #569CD6\">if<\/span><span style=\"color: #D4D4D4\"> false $<\/span><span style=\"color: #569CD6\">then<\/span><span style=\"color: #D4D4D4\"> irrelevant: <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> t6; $<\/span><span style=\"color: #569CD6\">end<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This SQL script does not contain relevant <code>select<\/code> statements. A <code>select<\/code> statement within a comment is hardly relevant. The same is true for <code>select<\/code> statements in remark and prompt commands. And I consider <code>select<\/code> statements within string literals and conditional compilation text also as irrelevant, at least in this example.<\/p>\n\n\n\n<p>So let&#8217;s look at another example:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">demo2.sql: Variants of select statements<\/span><span role=\"button\" tabindex=\"0\" data-code=\"-- simple\nselect * from dept;\n-- subquery_factoring_clause\nwith\n   d as (\n      select * from dept\n   )\nselect * from d;\n-- plsql_declarations\nwith\n   function e_count (in_deptno in dept.deptno%type) return integer is\n      l_count integer;\n   begin\n      select count(*)\n        into l_count\n        from emp;\n      return l_count;\n   end e_count;\nselect deptno, e_count(deptno)\n  from dept\n\/\n-- unterminated\nselect * from dept\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">-- simple<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> dept;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- subquery_factoring_clause<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">with<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   d <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> dept<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> d;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- plsql_declarations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">with<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> e_count (in_deptno <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> dept.deptno%<\/span><span style=\"color: #569CD6\">type<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">integer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">is<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      l_count <\/span><span style=\"color: #569CD6\">integer<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">begin<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(*)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">into<\/span><span style=\"color: #D4D4D4\"> l_count<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">return<\/span><span style=\"color: #D4D4D4\"> l_count;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">end<\/span><span style=\"color: #D4D4D4\"> e_count;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> deptno, e_count(deptno)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> dept<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- unterminated<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> dept<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This example script contains four <code>select<\/code> statements. As you can see, a <code>select<\/code> statement does not necessarily need to start with the <code>select<\/code> keyword. Furthermore a <code>select<\/code> statement can end on semicolon or slash or EOF (end-of-file). In fact, when using <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-28DA0E1D-87BF-462E-BCB8-8F77921022F9\">plsql_declarations<\/a> the statement must end on a slash (or EOF).<\/p>\n\n\n\n<p>Here&#8217;s a screenshot of the VSCode extension after searching for the regular expression <code>.+<\/code> in the demo workspace, highlighting the third search result.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1752\" height=\"1108\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2.png\" alt=\"IslandSQL VSCode extension: search result\" class=\"wp-image-12010\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2.png 1752w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-300x190.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-1024x648.png 1024w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-768x486.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-1536x971.png 1536w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-231x146.png 231w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-50x32.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-119x75.png 119w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/islandsql-vscode-demo2-1x1.png 1w\" sizes=\"auto, (max-width:767px) 480px, (max-width:1752px) 100vw, 1752px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Lexer Grammar<\/h2>\n\n\n\n<p>The responsibility of the lexer is to convert a stream of characters to a stream of tokens. We use <a href=\"https:\/\/www.antlr.org\/\">ANTLR 4<\/a> to generate our lexer with Java as the target language.<\/p>\n\n\n\n<p>Here&#8217;s the grammar definition for our lexer.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">IslandSqlLexer.g4: based on https:\/\/github.com\/IslandSQL\/IslandSQL\/tree\/v0.1.0\/<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lexer grammar IslandSqlLexer;\n\noptions {\n    superClass=IslandSqlLexerBase;\n    caseInsensitive = true;\n}\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Comments and alike to be ignored\n\/*----------------------------------------------------------------------------*\/\n\nML_COMMENT: '\/*' .*? '*\/' -&gt; channel(HIDDEN);\nSL_COMMENT: '--' .*? (EOF|SINGLE_NL) -&gt; channel(HIDDEN);\nREMARK_COMMAND:\n    {isBeginOfCommand()}? 'rem' ('a' ('r' 'k'?)?)?\n        (WS SQLPLUS_TEXT*)? SQLPLUS_END -&gt; channel(HIDDEN)\n;\nPROMPT_COMMAND:\n    {isBeginOfCommand()}? 'pro' ('m' ('p' 't'?)?)?\n       (WS SQLPLUS_TEXT*)? SQLPLUS_END -&gt; channel(HIDDEN)\n;\nSTRING:\n    'n'?\n    (\n          (['] .*? ['])+\n        | ('q' ['] '[' .*? ']' ['])\n        | ('q' ['] '(' .*? ')' ['])\n        | ('q' ['] '{' .*? '}' ['])\n        | ('q' ['] '<' .*? '&gt;' ['])\n        | ('q' ['] . {saveQuoteDelimiter1()}? .+? . ['] {checkQuoteDelimiter2()}?)\n    ) -&gt; channel(HIDDEN)\n;\nCONDITIONAL_COMPILATION_DIRECTIVE: '$if' .*? '$end' -&gt; channel(HIDDEN);\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Islands of interest on DEFAULT_CHANNEL\n\/*----------------------------------------------------------------------------*\/\n\nPLSQL_DECLARATION:\n    {isBeginOfStatement()}? 'with' WS\n        ('function'|'procedure') SQL_TEXT*?  PLSQL_DECLARATION_END\n;\nSELECT:\n    {isBeginOfStatement()}? ('with'|('(' WS?)* 'select') SQL_TEXT*? SQL_END\n;\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Whitespace\n\/*----------------------------------------------------------------------------*\/\n\nWS: [ \\t\\r\\n]+ -&gt; channel(HIDDEN);\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Any other token\n\/*----------------------------------------------------------------------------*\/\n\nANY_OTHER: . -&gt; channel(HIDDEN);\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Fragments to name expressions and reduce code duplication\n\/*----------------------------------------------------------------------------*\/\n\nfragment SINGLE_NL: '\\r'? '\\n';\nfragment CONTINUE_LINE: '-' [ \\t]* SINGLE_NL;\nfragment SQLPLUS_TEXT: (~[\\r\\n]|CONTINUE_LINE);\nfragment SQL_TEXT: (ML_COMMENT|SL_COMMENT|STRING|.);\nfragment SLASH_END: SINGLE_NL WS* '\/' [ \\t]* (EOF|SINGLE_NL);\nfragment PLSQL_DECLARATION_END: ';'? [ \\t]* (EOF|SLASH_END);\nfragment SQL_END:\n      EOF\n    | (';' [ \\t]* SINGLE_NL?)\n    | SLASH_END\n;\nfragment SQLPLUS_END: EOF|SINGLE_NL;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #9CDCFE\">lexer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">grammar<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">IslandSqlLexer<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">options<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">superClass<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">IslandSqlLexerBase<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">caseInsensitive<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">true<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Comments and alike to be ignored<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">ML_COMMENT<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;\/*&#39;<\/span><span style=\"color: #D4D4D4\"> .*? <\/span><span style=\"color: #CE9178\">&#39;*\/&#39;<\/span><span style=\"color: #D4D4D4\"> -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">SL_COMMENT<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;--&#39;<\/span><span style=\"color: #D4D4D4\"> .*? (<\/span><span style=\"color: #4FC1FF\">EOF<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">) -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">REMARK_COMMAND<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><span style=\"color: #DCDCAA\">isBeginOfCommand<\/span><span style=\"color: #D4D4D4\">()}? <\/span><span style=\"color: #CE9178\">&#39;rem&#39;<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;a&#39;<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;r&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;k&#39;<\/span><span style=\"color: #D4D4D4\">?)?)?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        (<\/span><span style=\"color: #4FC1FF\">WS<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQLPLUS_TEXT<\/span><span style=\"color: #D4D4D4\">*)? <\/span><span style=\"color: #4FC1FF\">SQLPLUS_END<\/span><span style=\"color: #D4D4D4\"> -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">PROMPT_COMMAND<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><span style=\"color: #DCDCAA\">isBeginOfCommand<\/span><span style=\"color: #D4D4D4\">()}? <\/span><span style=\"color: #CE9178\">&#39;pro&#39;<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;m&#39;<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;p&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;t&#39;<\/span><span style=\"color: #D4D4D4\">?)?)?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       (<\/span><span style=\"color: #4FC1FF\">WS<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQLPLUS_TEXT<\/span><span style=\"color: #D4D4D4\">*)? <\/span><span style=\"color: #4FC1FF\">SQLPLUS_END<\/span><span style=\"color: #D4D4D4\"> -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">STRING<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&#39;n&#39;<\/span><span style=\"color: #D4D4D4\">?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          ([<\/span><span style=\"color: #CE9178\">&#39;] .*? [&#39;<\/span><span style=\"color: #D4D4D4\">])+<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        | (<\/span><span style=\"color: #CE9178\">&#39;q&#39;<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #CE9178\">&#39;] &#39;<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #CE9178\">&#39; .*? &#39;<\/span><span style=\"color: #D4D4D4\">]<\/span><span style=\"color: #CE9178\">&#39; [&#39;<\/span><span style=\"color: #D4D4D4\">])<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        | (<\/span><span style=\"color: #CE9178\">&#39;q&#39;<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #CE9178\">&#39;] &#39;<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39; .*? &#39;<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #CE9178\">&#39; [&#39;<\/span><span style=\"color: #D4D4D4\">])<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        | (<\/span><span style=\"color: #CE9178\">&#39;q&#39;<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #CE9178\">&#39;] &#39;<\/span><span style=\"color: #D4D4D4\">{<\/span><span style=\"color: #CE9178\">&#39; .*? &#39;<\/span><span style=\"color: #D4D4D4\">}<\/span><span style=\"color: #CE9178\">&#39; [&#39;<\/span><span style=\"color: #D4D4D4\">])<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        | (<\/span><span style=\"color: #CE9178\">&#39;q&#39;<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #CE9178\">&#39;] &#39;<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #CE9178\">&#39; .*? &#39;<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><span style=\"color: #CE9178\">&#39; [&#39;<\/span><span style=\"color: #D4D4D4\">])<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        | (<\/span><span style=\"color: #CE9178\">&#39;q&#39;<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #CE9178\">&#39;] . {saveQuoteDelimiter1()}? .+? . [&#39;<\/span><span style=\"color: #D4D4D4\">] {<\/span><span style=\"color: #DCDCAA\">checkQuoteDelimiter2<\/span><span style=\"color: #D4D4D4\">()}?)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ) -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">CONDITIONAL_COMPILATION_DIRECTIVE<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;$if&#39;<\/span><span style=\"color: #D4D4D4\"> .*? <\/span><span style=\"color: #CE9178\">&#39;$end&#39;<\/span><span style=\"color: #D4D4D4\"> -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Islands of interest on DEFAULT_CHANNEL<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">PLSQL_DECLARATION<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><span style=\"color: #DCDCAA\">isBeginOfStatement<\/span><span style=\"color: #D4D4D4\">()}? <\/span><span style=\"color: #CE9178\">&#39;with&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">WS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        (<\/span><span style=\"color: #CE9178\">&#39;function&#39;<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #CE9178\">&#39;procedure&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #4FC1FF\">SQL_TEXT<\/span><span style=\"color: #D4D4D4\">*?  <\/span><span style=\"color: #4FC1FF\">PLSQL_DECLARATION_END<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">SELECT<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><span style=\"color: #DCDCAA\">isBeginOfStatement<\/span><span style=\"color: #D4D4D4\">()}? (<\/span><span style=\"color: #CE9178\">&#39;with&#39;<\/span><span style=\"color: #D4D4D4\">|(<\/span><span style=\"color: #CE9178\">&#39;(&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">WS<\/span><span style=\"color: #D4D4D4\">?)* <\/span><span style=\"color: #CE9178\">&#39;select&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #4FC1FF\">SQL_TEXT<\/span><span style=\"color: #D4D4D4\">*? <\/span><span style=\"color: #4FC1FF\">SQL_END<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Whitespace<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">WS<\/span><span style=\"color: #D4D4D4\">: [ \\<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">\\<\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">\\<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">]+ -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Any other token<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #4FC1FF\">ANY_OTHER<\/span><span style=\"color: #D4D4D4\">: . -&gt; <\/span><span style=\"color: #DCDCAA\">channel<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4FC1FF\">HIDDEN<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Fragments to name expressions and reduce code duplication<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;<\/span><span style=\"color: #D7BA7D\">\\r<\/span><span style=\"color: #CE9178\">&#39;<\/span><span style=\"color: #D4D4D4\">? <\/span><span style=\"color: #CE9178\">&#39;<\/span><span style=\"color: #D7BA7D\">\\n<\/span><span style=\"color: #CE9178\">&#39;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">CONTINUE_LINE<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;-&#39;<\/span><span style=\"color: #D4D4D4\"> [ \\<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">]* <\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQLPLUS_TEXT<\/span><span style=\"color: #D4D4D4\">: (~[\\<\/span><span style=\"color: #9CDCFE\">r<\/span><span style=\"color: #D4D4D4\">\\<\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">]|<\/span><span style=\"color: #4FC1FF\">CONTINUE_LINE<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQL_TEXT<\/span><span style=\"color: #D4D4D4\">: (<\/span><span style=\"color: #4FC1FF\">ML_COMMENT<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SL_COMMENT<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">STRING<\/span><span style=\"color: #D4D4D4\">|.);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SLASH_END<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">WS<\/span><span style=\"color: #D4D4D4\">* <\/span><span style=\"color: #CE9178\">&#39;\/&#39;<\/span><span style=\"color: #D4D4D4\"> [ \\<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">]* (<\/span><span style=\"color: #4FC1FF\">EOF<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">PLSQL_DECLARATION_END<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&#39;;&#39;<\/span><span style=\"color: #D4D4D4\">? [ \\<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">]* (<\/span><span style=\"color: #4FC1FF\">EOF<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SLASH_END<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQL_END<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #4FC1FF\">EOF<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | (<\/span><span style=\"color: #CE9178\">&#39;;&#39;<\/span><span style=\"color: #D4D4D4\"> [ \\<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">]* <\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">?)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #4FC1FF\">SLASH_END<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">fragment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">SQLPLUS_END<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4FC1FF\">EOF<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SINGLE_NL<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Lexer Options<\/h3>\n\n\n\n<p>On lines 3-6 we define the grammar <a href=\"https:\/\/github.com\/antlr\/antlr4\/blob\/master\/doc\/options.md\">options<\/a>.<\/p>\n\n\n\n<p>The first option defines the superclass that the generated lexer class should extend from. We use this class to define semantic predicates that can be used in the lexer grammar. Semantic predicates are very powerful. However, they bind a grammar to a target language. Of course, you can implement a superclass in different target languages. But would you want to do that for every supported <a href=\"https:\/\/github.com\/antlr\/antlr4\/blob\/master\/doc\/targets.md\">target language<\/a>?<\/p>\n\n\n\n<p>The second option defines the grammar as case-insensitive. This simplifies the grammar. We can simply write <code>select<\/code> instead of <code>S E L E C T<\/code> where every letter is a fragment (e.g.&nbsp;<code>fragment S: [sS];<\/code>).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Channels<\/h3>\n\n\n\n<p>A token can be either ignored (skipped) or placed on a channel. ANTLR provides by default the following two channels:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DEFAULT_CHANNEL<\/code>: for visible tokens that are relevant to the parser grammar<\/li>\n\n\n\n<li><code>HIDDEN<\/code>: for tokens that are not relevant to the parser grammar<\/li>\n<\/ul>\n\n\n\n<p>We do not skip tokens in this grammar. This has the advantage that we can access hidden tokens when we need to. For example, for accessing hints or for lossless serialisation of chosen parts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Comments and Alike<\/h3>\n\n\n\n<p>On lines 8-33, we define hidden tokens using <a href=\"https:\/\/github.com\/antlr\/antlr4\/blob\/master\/doc\/lexer-rules.md\">lexer rules<\/a>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The notation for the token definitions should be familiar to those with regular expression experience.<br \/>&#8212; Terence Parr, The Definitive ANTLR 4 Reference, 2nd edition, page 36<\/p>\n<\/blockquote>\n\n\n\n<p>The tokens defined in this section are similar to comments and therefore should be ignored and placed on the hidden channel.<\/p>\n\n\n\n<p>The order of the rules is important in case of conflicting definitions. The first rule wins.&nbsp;<code>ML_COMMENT<\/code> defines a multiline comment starting with <code>\/*<\/code>&nbsp; and ending with <code>*\/<\/code>. The rules defined afterwards&nbsp;cannot define tokens that are a subset of <code>ML_COMMENT<\/code>. For example,&nbsp; a <code>select<\/code> statement within a <code>ML_COMMENT<\/code> is not visible for subsequent rules. This is the reason for the rules in this section. We want to hide <code>select<\/code> statements within comments and alike.<\/p>\n\n\n\n<p>However, it is possible to define a token that contains a <code>ML_COMMENT<\/code>, e.g. in a <code>select<\/code> statement.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Islands of Interest<\/h3>\n\n\n\n<p>You find the islands of interest on lines 35-45. The rule <code>PLSQL_DECLARATION<\/code> covers the\u00a0<code>select<\/code> statement with a <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-28DA0E1D-87BF-462E-BCB8-8F77921022F9\">plsql_declarations<\/a> clause. And the rule <code>SELECT<\/code> covers the <code>select<\/code> statement without a <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-28DA0E1D-87BF-462E-BCB8-8F77921022F9\">plsql_declarations<\/a> clause. Identifying the end of the <code>select<\/code> statement is a bit tricky.<\/p>\n\n\n\n<p>This definition works in many cases, but it will falsely match subqueries in other statements such as <code>insert<\/code>, <code>update<\/code>, <code>delete<\/code>, <code>merge<\/code>, etc. In such cases, everything up to the next semicolon is considered part of the <code>select<\/code> statement. We will address this flaw in a future version of the grammar.<\/p>\n\n\n\n<p>How do we ignore semicolons in comments and strings? By using the fragment <code>SQL_TEXT<\/code>. A <code>SQL_TEXT<\/code> is either a <code>ML_COMMENT<\/code>, a <code>SL_COMMENT<\/code>, a <code>STRING<\/code> or any other character (<code>.<\/code>). Again, the order is important. The lexer considers comments and strings as single tokens. A semicolon in comments or strings is not visible. As a result, a semicolon in comments or strings will not be interpreted as the end of a <code>select<\/code> statement.<\/p>\n\n\n\n<p>Did you wonder why I use ANTLR instead of regular expressions? Well, it&#8217;s simply not possible to write a regular expression that can match a complete <code>select<\/code> statement ending on a semicolon while ignoring the semicolons in comments and strings. Simply put, ANTLR is more powerful.<\/p>\n\n\n\n<p>These two rules produce a single token for the whole <code>select<\/code> statement. This is simple and enough for our current use case. However, in the coming versions of the grammar, we will rewrite this section to parse a <code>select<\/code> statement completely and address the issues with subqueries in other statements.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Whitespace<\/h3>\n\n\n\n<p>The <code>WS<\/code> rule on line 51 defines whitespace characters. They are not relevant for the parser, hence we put them on the <code>HIDDEN<\/code> channel.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Other Tokens<\/h3>\n\n\n\n<p>The <code>ANY_OTHER<\/code> rule on line 57 covers any other character. They are not relevant for the parser and we put them also on the <code>HIDDEN<\/code> channel.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Fragments<\/h3>\n\n\n\n<p>And finally, on lines 59-74 we have fragments. A fragment allows one to name an expression and use the fragment name instead of the expression in other fragments or rules. This makes the grammar more readable without introducing additional token types.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parser Grammar<\/h2>\n\n\n\n<p>We use the output of the lexer &#8211; the token stream &#8211; in the parser. By default, only the tokens on the <code>DEFAULT_CHANNEL<\/code> are visible in the parser grammar. This makes the grammar quite simple.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">IslandSqlParser.g4: based on https:\/\/github.com\/IslandSQL\/IslandSQL\/tree\/v0.1.0\/<\/span><span role=\"button\" tabindex=\"0\" data-code=\"parser grammar IslandSqlParser;\n\noptions {\n    tokenVocab=IslandSqlLexer;\n}\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Start rule\n\/*----------------------------------------------------------------------------*\/\n\nfile: selectStatement* EOF;\n\n\/*----------------------------------------------------------------------------*\/\n\/\/ Rules for reduced SQL grammar (islands of interest)\n\/*----------------------------------------------------------------------------*\/\n\nselectStatement: PLSQL_DECLARATION | SELECT;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #9CDCFE\">parser<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">grammar<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">IslandSqlParser<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">options<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">tokenVocab<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">IslandSqlLexer<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Start rule<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">file<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #9CDCFE\">selectStatement<\/span><span style=\"color: #D4D4D4\">* <\/span><span style=\"color: #4FC1FF\">EOF<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Rules for reduced SQL grammar (islands of interest)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/*----------------------------------------------------------------------------*\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">selectStatement<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4FC1FF\">PLSQL_DECLARATION<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #4FC1FF\">SELECT<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Parser Options<\/h3>\n\n\n\n<p>On line 4 we include the token vocabulary based on the lexer grammar. The vocabulary defines integer values for each token type, e.g. <code>PLSQL_DECLARATION=7<\/code> or <code>SELECT=8<\/code>. The token stream uses these integer values to identify token types. Integers are shorter than their string counterparts and therefore use fewer resources.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Start Rule<\/h3>\n\n\n\n<p>You find the <a href=\"https:\/\/github.com\/antlr\/antlr4\/blob\/master\/doc\/parser-rules.md#start-rules-and-eof\">start rule<\/a> <code>file<\/code> on line 11. This is the entry point for the parser. The root node of the parse tree.<\/p>\n\n\n\n<p>A <code>file<\/code>&nbsp;may contain an unbounded number of <code>selectStatement<\/code> rules. And a file ends on the pseudo token<code>EOF<\/code> (end-of-file). This way we ensure that the parser reads the complete file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Select Statement<\/h3>\n\n\n\n<p>On line 17 the <code>selectStatement<\/code>&nbsp;is defined either as a <code>PLSQL_DECLARATION<\/code> or <code>SELECT<\/code> token.<\/p>\n\n\n\n<p>That&#8217;s it. All other tokens are hidden and invisible to the parser.<\/p>\n\n\n\n<p>Furthermore, it&#8217;s not possible to produce a parse error with this grammar. Everything that is not a <code>selectStatement<\/code>&nbsp;is on the hidden channel and irrelevant.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Interpreter<\/h2>\n\n\n\n<p>ANTLR is a parser generator. It takes the lexer and parser grammar as input and produces a lexer and parser in a chosen target language as output.<\/p>\n\n\n\n<p>However, there are also ANTLR interpreters. As a plugin in IDEs such as IntelliJ, as a standalone application or as a web application. After pasting the grammers into the UI you can play with it. Here&#8217;s a screenshot of the web variant of <a href=\"http:\/\/lab.antlr.org\/\">ANTLR lab<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab.png\"><img loading=\"lazy\" decoding=\"async\" width=\"2334\" height=\"1358\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab.png\" alt=\"\" class=\"wp-image-12047\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab.png 2334w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-300x175.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-1024x596.png 1024w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-768x447.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-1536x894.png 1536w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-2048x1192.png 2048w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-251x146.png 251w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-50x29.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-129x75.png 129w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/antlr_lab-1x1.png 1w\" sizes=\"auto, (max-width:767px) 480px, (max-width:2334px) 100vw, 2334px\" \/><\/a><\/figure>\n\n\n\n<p>What about semantic predicates? &#8211; The interpreter acts as the call returned true. As a result, for example, <code>xselect * from dual;<\/code> is falsely recognized as a <code>select<\/code> statement. Nevertheless, this is usually good enough to explore most parts of an ANTLR grammar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">IslandSQL on GitHub<\/h2>\n\n\n\n<p>The source code of the IslandSQL parser is available on <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\">GitHub<\/a>, licensed under the Apache License, Version 2.0.<\/p>\n\n\n\n<p>However, you will not find any test cases in this repo. I have written 92 test cases for the initial version 0.1.0. They are stored in a private repository. I do not plan to release them. It&#8217;s a way to make an unfriendly fork harder. Not right now. But once the grammar has evolved to cover a significant subset of SQL of the relevant database management systems, the situation might be different.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">IslandSQL on Maven Central<\/h2>\n\n\n\n<p>The IslandSQL parser is available on <a href=\"https:\/\/central.sonatype.com\/artifact\/ch.islandsql\/islandsql\/0.1.0\">Maven Central<\/a>. This makes integration into your preferred build system easy.<\/p>\n\n\n\n<p>And using the parser is also easy. Here is an example:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Demo.java<\/span><span role=\"button\" tabindex=\"0\" data-code=\"import ch.islandsql.grammar.IslandSqlDocument;\nimport ch.islandsql.grammar.IslandSqlParser;\n\nclass Demo {\n    public static void main(String[] args) {\n        var doc = IslandSqlDocument.parse(&quot;&quot;&quot;\n                \/* select * from t1; *\/\n                -- select * from t2;\n                rem select * from t3;\n                prompt select * from t4;\n                -- simple\n                select * from dept;\n                -- subquery_factoring_clause\n                with d as (select * from dept) select * from d;\n                -- other statements\n                delete from t5;\n                update t6 set c1 = null;\n                commit;\n                &quot;&quot;&quot;);\n        System.out.println(doc.getFile().getText());\n        System.out.println(&quot;----------&quot;);\n        doc.getFile().children.forEach(child -&gt; System.out.print(child.getText()));\n        System.out.println(&quot;\\n----------&quot;);\n        doc.getAllContentsOfType(IslandSqlParser.SelectStatementContext.class)\n                .forEach(stmt -&gt; System.out.print(stmt.getText()));\n    }\n}\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">import<\/span><span style=\"color: #D4D4D4\"> ch.islandsql.grammar.IslandSqlDocument;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">import<\/span><span style=\"color: #D4D4D4\"> ch.islandsql.grammar.IslandSqlParser;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Demo<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">main<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">[] <\/span><span style=\"color: #9CDCFE\">args<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">IslandSqlDocument<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">parse<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                \/* select * from t1; *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                -- select * from t2;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                rem select * from t3;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                prompt select * from t4;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                -- simple<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                select * from dept;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                -- subquery_factoring_clause<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                with d as (select * from dept) select * from d;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                -- other statements<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                delete from t5;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                update t6 set c1 = null;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                commit;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">                &quot;&quot;&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">out<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">println<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getFile<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">getText<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">out<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">println<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;----------&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getFile<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #9CDCFE\">children<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">forEach<\/span><span style=\"color: #D4D4D4\">(child <\/span><span style=\"color: #569CD6\">-&gt;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">out<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">child<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getText<\/span><span style=\"color: #D4D4D4\">()));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">out<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">println<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D7BA7D\">\\n<\/span><span style=\"color: #CE9178\">----------&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getAllContentsOfType<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">IslandSqlParser<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">SelectStatementContext<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">class<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                .<\/span><span style=\"color: #DCDCAA\">forEach<\/span><span style=\"color: #D4D4D4\">(stmt <\/span><span style=\"color: #569CD6\">-&gt;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">out<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">stmt<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getText<\/span><span style=\"color: #D4D4D4\">()));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The output of the main method is:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Output of Demo.java<\/span><span role=\"button\" tabindex=\"0\" data-code=\"select * from dept;\nwith d as (select * from dept) select * from d;\n<EOF&gt;\n----------\nselect * from dept;\nwith d as (select * from dept) select * from d;\n<EOF&gt;\n----------\nselect * from dept;\nwith d as (select * from dept) select * from d;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">select * from dept;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">with d as (select * from dept) select * from d;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;EOF&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">select * from dept;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">with d as (select * from dept) select * from d;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">&lt;EOF&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">----------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">select * from dept;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">with d as (select * from dept) select * from d;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">IslandSQL on Visual Studio Code Marketplace<\/h2>\n\n\n\n<p>The extension for IslandSQL is available in the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=phsalvisberg.islandsql\">Visual Studio Code Marketplace<\/a>. You can install it directly from any VS Code installation.<\/p>\n\n\n\n<p>Agreed, this extension is currently of limited value. However, it was a good opportunity to learn about VSCode extension development and how to use the tooling around Microsoft&#8217;s Language Server Protocol (LSP) to integrate a grammar that is written in Java.<\/p>\n\n\n\n<p>I am sure I can use this knowledge for other projects like utPLSQL once <a href=\"https:\/\/www.thatjeffsmith.com\/archive\/2022\/10\/whats-next-for-oracle-sql-developer-a-quick-sneek-peek\/\">SQL Developer for VScode<\/a> is available.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Outlook<\/h2>\n\n\n\n<p>I plan to extend the IslandSQL grammar step by step and blog about the progress. At some point, it will be necessary to move the logic from the lexer to the parser. Before that, I&#8217;ll be working on the lexer side a bit longer.<\/p>\n\n\n\n<p>Adding the missing DML statements to the grammar will be the next item on my to-do list.<\/p>\n\n\n\n<p>Another topic is utPLSQL. The utPLSQL annotations in package specifications could be easily parsed with a dedicated island grammar. We could visualise test suite hierarchies in the IDE and also consider tags. Of course, we would duplicate some of utPLSQL&#8217;s code in the database. The advantage of such an approach is that we know where a test package is located in the file system. This helps in navigating to the right place, e.g. after test execution failures and could greatly improve the experience of file-based development (compared to SQL Developer). I am looking forward to the next generation of SQL Developer based on VS Codium, where such an extension would bring the most value.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction An island grammar focuses only on a small part of a grammar. The island represents the small, interesting part and the sea the rest. In this blog post, I explain the components of an island grammar for SQL scripts named IslandSQL. In the first iteration, we focus on the select&nbsp;statement. Everything<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":12095,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[139,86,137,107,85,105,138],"class_list":["post-12006","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-antlr","tag-code-analysis","tag-islandsql","tag-java","tag-sql","tag-utplsql","tag-vscode"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"description\" content=\"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-02-04T12:00:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-08T17:13:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"500\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"IslandSQL Episode 1: Select Statement\",\"datePublished\":\"2023-02-04T12:00:04+00:00\",\"dateModified\":\"2023-11-08T17:13:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/\"},\"wordCount\":1712,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/02\\\/IslandSQL1.png\",\"keywords\":[\"ANTLR\",\"Code Analysis\",\"IslandSQL\",\"Java\",\"SQL\",\"utPLSQL\",\"VSCode\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/\",\"name\":\"IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/02\\\/IslandSQL1.png\",\"datePublished\":\"2023-02-04T12:00:04+00:00\",\"dateModified\":\"2023-11-08T17:13:43+00:00\",\"description\":\"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/02\\\/IslandSQL1.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/02\\\/IslandSQL1.png\",\"width\":500,\"height\":500},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/02\\\/04\\\/islandsql-episode-1-select-statement\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"IslandSQL Episode 1: Select Statement\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog","description":"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/","og_locale":"en_US","og_type":"article","og_title":"IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog","og_description":"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.","og_url":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2023-02-04T12:00:04+00:00","article_modified_time":"2023-11-08T17:13:43+00:00","og_image":[{"width":500,"height":500,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"IslandSQL Episode 1: Select Statement","datePublished":"2023-02-04T12:00:04+00:00","dateModified":"2023-11-08T17:13:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/"},"wordCount":1712,"commentCount":1,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png","keywords":["ANTLR","Code Analysis","IslandSQL","Java","SQL","utPLSQL","VSCode"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/","url":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/","name":"IslandSQL Episode 1: Select Statement - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png","datePublished":"2023-02-04T12:00:04+00:00","dateModified":"2023-11-08T17:13:43+00:00","description":"An island grammar focuses only on a small part of a grammar. The island represents the interesting part and the sea the rest.","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/02\/IslandSQL1.png","width":500,"height":500},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2023\/02\/04\/islandsql-episode-1-select-statement\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"IslandSQL Episode 1: Select Statement"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/12006","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=12006"}],"version-history":[{"count":82,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/12006\/revisions"}],"predecessor-version":[{"id":12730,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/12006\/revisions\/12730"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/12095"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=12006"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=12006"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=12006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}