| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
| <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <!-- -*- xhtml -*- --> | |
| <title>NetBeans Platform Schliemann Tutorial for NetBeans Platform 6.0</title> | |
| <link rel="stylesheet" type="text/css" href="../../../netbeans.css"> | |
| <meta name="AUDIENCE" content="NBUSER"> | |
| <meta name="TYPE" content="ARTICLE"> | |
| <meta name="EXPIRES" content="N"> | |
| <meta name="developer" content="gwielenga@netbeans.org"> | |
| <meta name="indexed" content="y"> | |
| <meta name="description" | |
| content="A short guide to using the Nodes API."> | |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | |
| <!-- Use is subject to license terms.--> | |
| </head> | |
| <body> | |
| <h1> | |
| NetBeans Platform Schliemann Tutorial | |
| </h1> | |
| <p> | |
| Welcome to the NetBeans Platform Schliemann tutorial. Schliemann is a | |
| project that allows you to define a programming language and integrate it to | |
| NetBeans IDE. | |
| </p> | |
| <p> | |
| This tutorial shows how to add Prolog support to the NetBeans Editor. At the | |
| end of it, your prolog files in NetBeans IDE will look like that: | |
| </p> | |
| <p><img border="1" src="../../images/tutorials/prolog/60-finish.png" alt="60-finish.png"> | |
| <h3>Contents</h3> | |
| <table border="0" cellpadding="0" cellspacing="0" width="100%"> | |
| <tbody><tr> | |
| <td align="left" valign="top"> | |
| <ul> | |
| <li><a HREF="#knowledge" CLASS="XRef">Prerequisite Knowledge</a></li> | |
| <li><a HREF="#software" CLASS="XRef">Required Software</a></li> | |
| <li><a HREF="#setting" CLASS="XRef">Setting Up the Environment</a></li> | |
| <li><a HREF="#adding" CLASS="XRef">Adding Prolog support</a></li> | |
| <ul> | |
| <li><a HREF="#tokens" CLASS="XRef">Tokens definition</a></li> | |
| <li><a HREF="#grammar" CLASS="XRef">Grammar definition</a></li> | |
| <li><a HREF="#support" CLASS="XRef">Folding, navigation and other features</a></li> | |
| </ul> | |
| <li><a HREF="#resources" CLASS="XRef">Further reading</a></li> | |
| </ul></td> | |
| <td width="20"> </td> | |
| <td align="right" valign="top"> | |
| <img src="../../images/articles/60/netbeans-stamp60-61.gif" | |
| alt="Content on this page applies to NetBeans IDE 6.0" title="Content on this page applies to the NetBeans | |
| IDE 6.0" border="0"> | |
| </td> | |
| </tr> | |
| </tbody></table> | |
| <h2><a name="knowledge"></a>Prerequisite Knowledge</h2> | |
| <p>You are neither required to know anything about NetBeans Platform | |
| develop ment nor Prolog to work on this tutorial. We have choose Prolog as | |
| example for Schliemann because of the relative simplicity of its syntax. </p> | |
| <h2><a name="software"></a>Required Software</h2> | |
| <p>Since the version 6.0, the Generic Language Framework Studio is part of the | |
| distribution of NetBeans IDE. Therefore, the only software needed to | |
| go through this tutorial is: | |
| </p> | |
| <ul> | |
| <li>The J2SE(TM) Development Kit (JDK), version 5.0 or compatible | |
| (<a href="http://java.sun.com/javase/downloads/index.jsp">download the | |
| most recent JDK</a>).</li> | |
| <li>NetBeans IDE 6.0 (<a href="http://download.netbeans.org/netbeans/6.0/final/">download</a>). | |
| </ul> | |
| <br /> | |
| <h2><a name="setting"></a>Setting up the environment</h2> | |
| <p> | |
| Take the following steps to set up the environment, before to begin to add | |
| Prolog support: | |
| </p> | |
| <ol> | |
| <li>In the IDE, create a New Project and choose the type Module, in the | |
| category NetBeans Modules. | |
| </li> | |
| <li> | |
| Name the project whatever you like (we use the name Prolog, in this | |
| tutorial) and finish. | |
| </li> | |
| <li> | |
| Add a new file to your project of type Language Support. You can find | |
| this type in the category Module Development. We name this file "prolog", | |
| and the extesion is "nbs" (NetBeans Scripting). You will be also asked to | |
| provide a Mime Type and a list of extensions. In this tutorial we use | |
| <tt>text/x-prolog</tt> as Mime Type and <tt>pro</tt> as extension. | |
| <p>After those steps you should see the following files and NBS Template in | |
| your NetBeans IDE | |
| </p> | |
| <p><img border="1" src="../../images/tutorials/prolog/60-setting.png" alt="60-finish.png"> | |
| <br /> | |
| <br /> | |
| The file <tt>MIMEResolver.xml</tt> maps the "pro" file extension to the MIME | |
| type <tt>text/x-prolog</tt>. | |
| </li> | |
| </ol> | |
| <h2><a name="adding"></a>Adding Prolog support to NetBeans Editor</h2> | |
| The NBS default template contains code for an example language definition. | |
| If you compile and install the module now (right click on the project and | |
| select "Install/Reload in Development IDE"), after restarting the IDE you can | |
| try to create a new file with "pro" extension and paste the following code | |
| in it: | |
| <pre class="examplecode"> | |
| while (one) { | |
| two | |
| if (three) { | |
| four | |
| } | |
| } | |
| while (five) { | |
| six | |
| } | |
| </pre> | |
| You will notice syntax coloring, navigator window support, code folding and | |
| indentation. | |
| Now we begin to add Prolog support, so, the first step is deleting all the | |
| content of the file <tt>prolog.nbs</tt>. | |
| <h3><a name="tokens"></a>Tokens definition</h3> | |
| The lexical analyser is the first part of any language definition. In | |
| Schliemann tokens are defined by regular expressions and the keyword | |
| <tt>TOKEN</tt> is used. In the case of Prolog, the tokens that we define are | |
| the following: | |
| <pre class="examplecode"> | |
| ######################## | |
| # Definition of tokens # | |
| ######################## | |
| # Keywords | |
| TOKEN:keyword:( | |
| "true" | "fail" | "!" | "at_end_of_stream" | | |
| "nl" | "repeat" | "halt" | "is" | "mod" | "rem" | |
| ) | |
| TOKEN:special:( "." | ":-" | ",") | |
| # Predefined predicates | |
| TOKEN:function:( | |
| "abolish" | "abort" | "absolute_file_name" | "absolute_file_name" | "access_file" | | |
| "append" | "append" | "apply" | "apropos" | "arg" | "arithmetic_function" | "assert" | | |
| "assert" | "asserta" | "asserta" | "assertz" | "assertz" | "at_halt" | "at_initialization" | | |
| "atom" | "atom_char" | "atom_chars" | "atom_length" | "atom_to_term" | "atomic" | | |
| "autoload" | "bagof" | "between" | "block" | "break" | "call" | "call" | "call_dll_function" | | |
| "call_shared_object_function" | "character_count" | "chdir" | "checklist" | "clause" | "clause" | | |
| "clause_property" | "close" | "close_dde_conversation" | "close_dll" | "close_shared_object" | | |
| "compare" | "compiling" | "compound" | "concat" | "concat_atom" | "consult" | "context_module" | | |
| "convert_time" | "copy_term" | "current_arithmetic_function" | "current_atom" | "current_flag" | | |
| "current_foreign_library" | "current_functor" | "current_input" | "current_key" | "current_module" | | |
| "current_module" | "current_op" | "current_output" | "current_predicate" | "current_stream" | | |
| "dde_current_connection" | "dde_current_service" | "dde_execute" | "dde_register_service" | | |
| "dde_request" | "dde_unregister_service" | "debug" | "debugging" | "default_module" | "delete" | | |
| "delete_file" | "discontiguous" | "display" | "displayq" | "dwim_match" | | |
| "dwim_predicate" | "dynamic" | "ed" | "ed" | "edit" | "edit" | "edit_source" | "ensure_loaded" | "erase" | | |
| "exception" | "exists_directory" | "exists_file" | "exit" | "expand_file_name" | | |
| "expand_file_search_path" | "expand_term" | "explain" | "explain" | "export" | "export_list" | | |
| "feature" | "file_base_name" | "file_directory_name" | "file_search_path" | "fileerrors" | | |
| "findall" | "flag" | "flatten" | "float" | "flush" | "flush_output" | "forall" | "foreign_file" | "format" | | |
| "free_variables" | "functor" | "garbage_collect" | "gensym" | "get" | "get" | "get0" | "get_single_char" | | |
| "get_time" | "getenv" | "ground" | "hash_term" | "help" | "history_depth" | "ignore" | "import" | | |
| "index" | "initialization" | "int_to_atom" | "integer" | "intersection" | "is_absolute_file_name" | | |
| "is_list" | "is_set" | "keysort" | "last" | "leash" | "length" | "library_directory" | "limit_stack" | | |
| "line_count" | "line_position" | "list_to_set" | "listing" | "load_foreign" | "load_foreign_library" | | |
| "make" | "make_fat_filemap" | "make_library_index" | "maplist" | "member" | "merge" | "merge_set" | | |
| "module" | "module_transparent" | "msort" | "multifile" | "name" | "nodebug" | "nonvar" | "noprotocol" | | |
| "nospy" | "nospyall" | "not" | "notrace" | "nth0" | "nth1" | "nth_clause" | "number" | "number_chars" | | |
| "numbervars" | "once" | "op" | "open" | "open_dde_conversation" | "open_null_stream" | | |
| "open_shared_object" | "phrase" | "please" | "plus" | "portray" | "portray_clause" | "predicate_property" | | |
| "predsort" | "preprocessor" | "print" | "profile" | "profile_count" | "profiler" | "prolog" | | |
| "prolog_current_frame" | "prolog_frame_attribute" | "prolog_load_context" | "prolog_skip_level" | | |
| "prolog_to_os_filename" | "prolog_trace_interception" | "prompt1" | "prompt" | "proper_list" | "protocol" | | |
| "protocola" | "protocolling" | "put" | "qcompile" | "qload" | "qsave_program" | "qsave_program" | | |
| "read" | "read_clause" | "read_history" | "read_link" | "read_variables" | "recorda" | "recorded" | "recordz" | | |
| "redefine_system_predicate" | "rename_file" | "require" | "reset_profiler" | "restore" | "retract" | | |
| "retractall" | "reverse" | "same_file" | "save" | "save_program" | "save_program" | "see" | "seeing" | "seen" | | |
| "select" | "set_feature" | "set_input" | "set_output" | "set_tty" | "setarg" | "setenv" | "setof" | "sformat" | | |
| "shell" | "show_profile" | "sleep" | "sort" | "source_file" | "source_location" |"spy" | "stack_parameter" | | |
| "statistics" | "stream_position" | "string" | "string_length" | "string_to_atom" | "string_to_list" | | |
| "style_check" | "sublist" | "subset" | "substring" | "subtract" | "succ" | "swritef" | "tab" | "tell" | "telling" | | |
| "term_expansion" | "term_to_atom" | "time" | "time_file" | "tmp_file" | "told" | "trace" | "tracing" | | |
| "trim_stacks" | "tty_get_capability" | "tty_goto" | "tty_put" | "ttyflush" | "union" | "unknown" | | |
| "unload_foreign_library" | "unsetenv" | "use_module" | "use_module" | "var" | "visible" | "volatile" | |
| "wait_for_input" | "wildcard_match" | "write" | "write_ln" | "writef" | "writeq" | | |
| "abs" | "acos" | "asin" | "atan" | "atan" | "ceil" | "ceiling" | "cos" | | |
| "cputime" | "e" | "exp" | "float" | "float_fractional_part" | "float_integer_part" | | |
| "floor" | "integer" | "log" | "log10" | "max" | "min" | "random" | | |
| "round" | "truncate" | "pi" | "sign" | "sin" | "sqrt" | "tan" | "xor" | |
| ) | |
| TOKEN:string:( "\"" [^ "\""]* "\"" ) | |
| TOKEN:string:( "\'" [^ "\'"]* "\'" ) | |
| TOKEN:list:( "[" - "]" ) | |
| TOKEN:operator: ( | |
| [ "?" "/" "*" "-" "+" "@" "#" "$" "%" "^" "\\" | |
| ] | |
| ) | |
| TOKEN:boolean: ( | |
| [ "<" ">" "=" "," ";" "&" "~" "|" | |
| ] | |
| ) | |
| TOKEN:separator: ( ["(" ")" "[" "]" "{" "}"] ) | |
| TOKEN:variable:( ["A"-"Z" "_"] ["a"-"z" "A"-"Z" "0"-"9" "_"]* ) | |
| TOKEN:identifier:( ["a"-"z"] ["a"-"z" "A"-"Z" "0"-"9" "_"]* ) | |
| TOKEN:number:( ["0"-"9"]+ ("." ["0"-"9"]+)? ("E" ("+" | "-" )? ["0"-"9"]+)? ) | |
| TOKEN:whitespace: ( [" " "\t" "\n" "\r"]* ) | |
| TOKEN:comment:( "/*" - "*/" ) | |
| TOKEN:line_comment:( "%" [^ "\n" "\r"]* ["\n" "\r"]+ ) | |
| </pre> | |
| <p> | |
| Notice that it is possible to define different tokens with | |
| the same name, like <tt>string</tt>. In this way we can apply the same | |
| processing to two different kinds of string but that semantically are | |
| identical. | |
| </p> | |
| <p> | |
| For more detailed info on the syntax of tokens definition, take a look on | |
| the official Schliemann Language Definition, <a | |
| href="http://wiki.netbeans.org/wiki/view/SchliemannNBSLanguageDescription#section-SchliemannNBSLanguageDescription-TokensDefinition.">here</a>. | |
| </p> | |
| <p> | |
| For Prolog we have defined one token <tt>keyword</tt>, that obviously | |
| represents the keywords of the language, one token <tt>function</tt>, | |
| representing the predefined functions that exist in Prolog and the usual | |
| tokens <tt>string</tt>, <tt>operator</tt>, <tt>number</tt>, | |
| <tt>identifier</tt> or <tt>variable</tt> (all the variables in Prolog must | |
| begin with capital letter or _). Also you can find tokens describing comments (line | |
| and block) and whitespaces. This kind of tokens should receive a special | |
| treatment. | |
| </p> | |
| <p> | |
| With the definition of tokens it is possible now to add syntax coloring. We | |
| can do that with this small piece of code: | |
| </p> | |
| <pre class="examplecode"> | |
| # Syntax Coloring | |
| COLOR:function: { | |
| default_coloring:"default"; | |
| font_type:"bold"; | |
| } | |
| COLOR:line_comment: { | |
| default_coloring:"comment"; | |
| } | |
| COLOR:list: { | |
| default_coloring:"string"; | |
| } | |
| </pre> | |
| <p> | |
| It is not necessary to specify a color for <tt>keyword</tt>, | |
| <tt>function</tt>, etc, because there exists a default color for the tokens | |
| defined as keywords, or comments, or operator. Of course, it is possible to | |
| override the default syntax coloring. It is also possible to change other | |
| properties, like the font or the background color. For more info, take a | |
| look <a | |
| href="http://wiki.netbeans.org/wiki/view/SchliemannNBSLanguageDescription#section-SchliemannNBSLanguageDescription-SyntaxColoringDefinition.">here</a>. | |
| </p> | |
| <p> | |
| Copy and paste all the code above in your NBS file. If you install now the | |
| module in you Development IDE and restart NetBeans, you can see syntax | |
| coloring in a Prolog example file. | |
| </p> | |
| <p><img border="1" src="../../images/tutorials/prolog/60-tokens.png" alt="60-finish.png"> | |
| <h3><a name="syntax"></a>Grammar definition</h3> | |
| First, comments and whitespaces should be ignored by the syntax analyser. This is | |
| achieved by using the keyword <tt>skip</tt>. | |
| <pre class="examplecode"> | |
| SKIP:comment | |
| SKIP:line_comment | |
| SKIP:whitespace | |
| </pre> | |
| <p> | |
| At this point, it is important to speak about the AST View and the Tokens | |
| View. These two views provided by the IDE are really useful when you are | |
| using Schliemann, actually, they are essential if you want to debug your | |
| grammar or your tokens definition. | |
| </p> | |
| <p> | |
| To activate them, right-click the file <tt>prolog.nbs</tt> in the Project | |
| window and select "AST View" and "Tokens View". Now, you should see the | |
| AST and the Tokens browser window. If you select now your prolog example | |
| file, while leaving the Tokens view open, you should see the tokens of this | |
| file. These two views always show the AST and tokens of the currently | |
| selected file. | |
| </p> | |
| <p> | |
| An example of the Tokens View and AST View in action: | |
| </p> | |
| <p><img border="1" src="../../images/tutorials/prolog/60-tokensview.png" alt="60-finish.png"> | |
| <br /> | |
| <br /> | |
| <br /> | |
| <p> | |
| In Schliemann, grammar is described in form similar to JavaCC (extended | |
| <a href="http://en.wikipedia.org/wiki/Backus�Naur_form">BNF</a>). The grammar must be <a | |
| href="http://en.wikipedia.org/wiki/LL_parser">LL</a>, since <a | |
| href="http://en.wikipedia.org/wiki/LR_parser">LR</a> and <a | |
| href="http://en.wikipedia.org/wiki/LALR">LALR</a> grammar are not accepted. | |
| </p> | |
| <p> | |
| There are some things that you should have into account when you are writing | |
| a grammar for Schliemann. First of all, the grammar should be LL(1) (that | |
| means that the parser can only look ahead one symbol when analyzing text). | |
| So if you have rules whose right hand sides start with the same element, you | |
| should transform these rules. For example, instead of writing: | |
| </p> | |
| <pre> | |
| Statement = Fact | Clause; | |
| Fact = Structure "."; | |
| Clause = Structure ":-" ListOfStructures "."; | |
| </pre> | |
| <p> | |
| which will not work properly, you should write something like that: | |
| </p> | |
| <pre> | |
| Statement = Structure ("." | ":-" ListOfStructures "."); | |
| </pre> | |
| <p> | |
| Also, you must remove left recursion in your grammar, which implies that | |
| you cannot have rules like that: | |
| </p> | |
| <pre> | |
| ListOfStructures = ListOfStructures BooleanOperation Structure; | |
| ListOfStructures = Structure; | |
| </pre> | |
| <p> | |
| but you should re-write the above as follows: | |
| </p> | |
| <pre> | |
| ListOfStructures = Structure (BooleanOperation Structure)* ; | |
| </pre> | |
| <p> | |
| As a result of those transformations, the grammar you write is less strict | |
| than the original syntax definition of the language, don't worry. You are | |
| not writing a compiler, so, if your grammar is not powerful enough to detect | |
| all the possible syntax errors, it is also OK. | |
| </p> | |
| <p> | |
| Last, but not least, be patient. Schliemann is not a tool to write | |
| compilers, like ANTLR or yacc. It has some limitations and sometimes, if you | |
| have some errors in your tokens definition or in your grammar, you will not | |
| get any information about it. The error messages provide not really useful | |
| information and you should work out by inspection of your .nbs file or by | |
| trial and error. | |
| </p> | |
| <p> | |
| After these remarks, we can go on to the grammar for Prolog. The syntax of | |
| prolog is deceptively simple. A logic program is made up of clauses and | |
| facts. A simplified definition of the grammar: | |
| </p> | |
| <pre> | |
| clause := predicate ":-" (predicate)+ "." | |
| fact := predicate "." | |
| </pre> | |
| <p> | |
| Predicates can be function symbols with or without arguments or infix binary operators like | |
| "=". Aritmetic expressions can also appear. For more detail on Prolog | |
| there are several resources like <a | |
| href="http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/contents.html">this</a> | |
| or <a href="http://kti.mff.cuni.cz/~bartak/prolog.old/index.html">this</a>, but for the purpose of | |
| this tutorial it is not important to understand deeply the Prolog syntax. | |
| </p> | |
| <p> | |
| The complete Schliemann code that defines the prolog syntax is the | |
| following: | |
| <pre class="examplecode"> | |
| # Grammar definition | |
| S = (Statement)*; | |
| Statement = Structure ("." | ":-" ListOfStructures "."); | |
| ListOfStructures = Structure (BooleanOperation Structure)* ; | |
| Structure = Expression | | |
| <keyword>; | |
| Functor = <function> | <identifier>; | |
| Expression = BaseExpression ((Operation|"is"|"mod"|"rem") Expression)* | | |
| "(" BaseExpression ((Operation|"is"|"mod"|"rem") Expression)* ")" ; | |
| Operation = (<operator>)+; | |
| BooleanOperation = (<boolean>)+ | "=.." | ","; | |
| BaseExpression = <variable> | | |
| <list> | | |
| <string> | | |
| Function | | |
| <number> ; | |
| Function = Functor ["(" ListOfStructures ")"]; | |
| </pre> | |
| Copy and paste the code above. | |
| <h3><a name="support"></a>Folding, navigation and other features</h3> | |
| The tokens and grammar definition is the core of our Prolog support. Now, we can | |
| go on to more interesting and easy stuff. Copy and paste all the code below | |
| in your NBS file: | |
| <pre class="examplecode"> | |
| # error highlighting | |
| MARK:ERROR: { | |
| type:"Error"; | |
| message:"Syntax error."; | |
| } | |
| MARK:error: { | |
| type:"Error"; | |
| message:"Unexpected character."; | |
| } | |
| # brace completion | |
| COMPLETE "{:}" | |
| COMPLETE "(:)" | |
| COMPLETE "[:]" | |
| COMPLETE "\":\"" | |
| COMPLETE "\':\'" | |
| # brace matching | |
| BRACE "{:}" | |
| BRACE "(:)" | |
| BRACE "[:]" | |
| BRACE "\":\"" | |
| BRACE "\':\'" | |
| # indentation | |
| INDENT ".*(((:-)\\s*)[^.]*)" | |
| # code folding | |
| FOLD:ListOfStructures: { | |
| expand_type_action_name:"Expand clause body"; | |
| collapse_type_action_name:"Collapse clause body"; | |
| } | |
| FOLD:comment: { | |
| expand_type_action_name:"Expand Comments"; | |
| collapse_type_action_name:"Collapse Comments"; | |
| } | |
| # navigator support | |
| NAVIGATOR:Statement: { | |
| display_name: "$Structure$"; | |
| icon: org.yourorghere.prolog.Prolog.statementIcon; | |
| } | |
| </pre> | |
| <p> | |
| Thanks to our definition of the language, we can detect both lexical and | |
| syntactic errors and we can get these error marked. Also, add code folding | |
| is quite easy. In our case, we just add code folding | |
| for block comments and clauses. Any grammar rule can be folded. | |
| </p> | |
| <p> | |
| As you can see, brace completion and brace matching are pretty intuitive. To | |
| add indentation is enough to write some regular expression after | |
| which the code should be automatically indented. The most interesting thing | |
| in this code is the navigator support. For every prolog statement, we | |
| display the text corresponding to the structure and the icon used depends on | |
| the kind of statement we are dealing with (fact or clause). To do that, the | |
| <tt>icon</tt> declaration refers to a method called <tt>statementIcon</tt>, | |
| which is in the file <tt>Prolog.java</tt>. Here is the content of that file: | |
| </p> | |
| <pre class="examplecode"> | |
| package org.yourorghere.prolog; | |
| import org.netbeans.api.languages.ASTNode; | |
| import org.netbeans.api.languages.ASTPath; | |
| import org.netbeans.api.languages.SyntaxContext; | |
| public class Prolog { | |
| public static String statementIcon (SyntaxContext context) { | |
| ASTPath path = context.getASTPath (); | |
| ASTNode node = (ASTNode) path.getLeaf (); | |
| node = node.getNode ("ListOfStructures"); | |
| if (node != null) { | |
| return "/org/netbeans/modules/languages/resources/variable.gif"; | |
| } | |
| return "/org/netbeans/modules/languages/resources/method.gif"; | |
| } | |
| } | |
| </pre> | |
| <p> | |
| To get this file working, you have to add a module dependency with the | |
| Generic Languages Framework. To do this, in the Projects Window, right click | |
| on "Libraries" and select "Add Module Dependency..." and then look for the | |
| Generic Languages Framework. | |
| That method makes use of the AST generated by Schliemann. Basically, we | |
| search in the path whose root is a Statement node, another node of type | |
| <tt>ListOfStructures</tt>. If this node is found, that means that the | |
| statement is a clause. Otherwise, it is a fact. This procedure can be also | |
| applied to the <tt>display_name</tt> declaration and so on. | |
| </p> | |
| <h2><a name="files">Files</a></h2> | |
| Here you can download the code used in this tutorial: | |
| <ul> | |
| <li><a href="prolog.nbs">prolog.nbs</a></li> | |
| <li><a href="Prolog.java">Prolog.java</a></li> | |
| </ul> | |
| <h2><a name="resources">Further reading</a></h2> | |
| This tutorial shows only an introductory example of using Schliemann. You | |
| can find more information in the following links: | |
| <ul> | |
| <li><a href="https://netbeans.org/source/browse/scripting/">NetBeans | |
| Scripting Module</a></li> | |
| <li><a href="https://netbeans.org/source/browse/languages/">NetBeans | |
| Languages Module</a></li> | |
| <li><a | |
| href="http://wiki.netbeans.org/wiki/view/SchliemannNBSLanguageDescription">NBS | |
| Language Description</a></li> | |
| <li><a href="http://blogs.oracle.com/geertjan/entry/interview_author_of_d_programming">Interview with the author of new D programming language | |
| editor</li> | |
| <li><a | |
| href="https://platform.netbeans.org/articles/nbm_interview_caoyuan.html">Meet | |
| a NetBeans Module Writer: Caoyuan Deng</a></li> | |
| </ul> | |
| <p> | |
| <br> | |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback: NetBeans Platform Schliemann Tutorial">Send Us Your Feedback</a></div> | |
| <br style="clear:both;" /> | |
| <hr> | |
| </body> | |
| </html> | |