From c1980ee7b1bfc89e41ee4fc1ae33468ddbb009f3 Mon Sep 17 00:00:00 2001 From: Markus Rudolph Date: Fri, 23 Aug 2024 09:58:45 +0200 Subject: [PATCH] Make most of the links relative --- hugo/config.toml | 2 +- hugo/content/docs/_index.md | 2 +- hugo/content/docs/introduction/_index.md | 10 +++---- hugo/content/docs/introduction/features.md | 19 ++++++------ hugo/content/docs/introduction/playground.md | 2 +- hugo/content/docs/learn/_index.md | 1 - hugo/content/docs/learn/minilogo/_index.md | 2 +- .../minilogo/building_an_extension/_index.md | 6 ++-- .../docs/learn/minilogo/customizing_cli.md | 6 ++-- .../content/docs/learn/minilogo/generation.md | 4 +-- .../learn/minilogo/generation_in_the_web.md | 4 +-- .../docs/learn/minilogo/langium_and_monaco.md | 2 +- .../content/docs/learn/minilogo/validation.md | 4 +-- .../docs/learn/minilogo/writing_a_grammar.md | 4 +-- hugo/content/docs/learn/workflow/_index.md | 21 +++++++------- .../docs/learn/workflow/create_validations.md | 1 - .../docs/learn/workflow/generate_ast.md | 1 - .../learn/workflow/generate_everything.md | 1 - hugo/content/docs/learn/workflow/install.md | 1 - .../workflow/resolve_cross_references.md | 1 - hugo/content/docs/learn/workflow/scaffold.md | 1 - .../docs/learn/workflow/write_grammar.md | 3 +- hugo/content/docs/recipes/_index.md | 1 - hugo/content/docs/recipes/builtin-library.md | 2 +- hugo/content/docs/recipes/code-bundling.md | 2 +- .../recipes/keywords-as-identifiers/_index.md | 6 ++-- .../docs/recipes/multiple-languages.md | 2 +- hugo/content/docs/recipes/scoping/_index.md | 12 ++++---- .../docs/recipes/scoping/qualified-name.md | 2 +- hugo/content/docs/reference/_index.md | 10 +++---- .../docs/reference/grammar-language.md | 4 +-- hugo/content/docs/reference/semantic-model.md | 2 +- scripts/check-links.ts | 29 +++++++++++++------ 33 files changed, 86 insertions(+), 84 deletions(-) diff --git a/hugo/config.toml b/hugo/config.toml index 4d4e64a6..b680d91c 100644 --- a/hugo/config.toml +++ b/hugo/config.toml @@ -65,7 +65,7 @@ enableRobotsTXT = true # (Optional, default false) Set HTMl to .Site.BaseURL if enabled. It might be required # if a subdirectory is used within Hugos BaseURL. # See https://developer.mozilla.org/de/docs/Web/HTML/Element/base. - geekdocOverwriteHTMLBase = true + # geekdocOverwriteHTMLBase = true # (Optional, default false) Auto-decrease brightness of images and add a slightly grayscale to avoid # bright spots while using the dark mode. diff --git a/hugo/content/docs/_index.md b/hugo/content/docs/_index.md index e8aaead5..90382ded 100644 --- a/hugo/content/docs/_index.md +++ b/hugo/content/docs/_index.md @@ -2,4 +2,4 @@ title: "Documentation" weight: 0 --- - \ No newline at end of file + \ No newline at end of file diff --git a/hugo/content/docs/introduction/_index.md b/hugo/content/docs/introduction/_index.md index 8bb8600b..a4e5b09f 100644 --- a/hugo/content/docs/introduction/_index.md +++ b/hugo/content/docs/introduction/_index.md @@ -8,18 +8,18 @@ Langium is an open source language engineering tool with first-class support for ### Features -If you need a more detailed list of Langium features, you can find them in the [features section](/docs/features). +If you need a more detailed list of Langium features, you can find them in the [features section](./features). ### Try it out -If you want to see Langium in action, you can follow the [showcases](/showcase) or even the [playground](/playground). +If you want to see Langium in action, you can follow the [showcases](../../showcase) or even the [playground](../../playground). ### Learn Langium -If you are convinced by Langium and want to learn more about it, you can start with the [learn section](/docs/learn). +If you are convinced by Langium and want to learn more about it, you can start with the [learn section](../learn). ### More details -If you are looking for more details about Langium, you can find them in the [reference section](/docs/reference). +If you are looking for more details about Langium, you can find them in the [reference section](../reference). -If you are searching for a certain guide or recipe, you can find them in the [recipes section](/docs/recipes). +If you are searching for a certain guide or recipe, you can find them in the [recipes section](../recipes). diff --git a/hugo/content/docs/introduction/features.md b/hugo/content/docs/introduction/features.md index 0a00ac81..aa139d32 100644 --- a/hugo/content/docs/introduction/features.md +++ b/hugo/content/docs/introduction/features.md @@ -1,7 +1,8 @@ --- title: "Features" weight: 200 -url: /docs/features +aliases: + - /docs/features --- Designing programming languages from the ground up is hard, independent of whether your language is a "simple" domain specific language or a full-fledged general-purpose programming language. Not only do you have to keep up with the requirements of your domain experts, but you have to deal with all the technical complexity that comes with building a language, including questions such as: @@ -14,12 +15,12 @@ This is the point where Langium comes into play. Langium aims to lower the barri In this chapter, you'll get a closer look at the requirements developers usually have to implement by themselves when building a programming language: -- [Language Parsing](#language-parsing) -- [Semantic Models](#semantic-models) -- [Cross References and Linking](#cross-references-and-linking) -- [Workspace Management](#workspace-management) -- [Editing Support](#editing-support) -- [Try it out](#try-it-out) +- [Language Parsing](/docs/introduction/features#language-parsing) +- [Semantic Models](/docs/introduction/features#semantic-models) +- [Cross References and Linking](/docs/introduction/features#cross-references-and-linking) +- [Workspace Management](/docs/introduction/features#workspace-management) +- [Editing Support](/docs/introduction/features#editing-support) +- [Try it out](/docs/introduction/features#try-it-out) Langium provides out-of-the-box solutions for these problems, with the ability to fine-tune every part of it to fit your domain requirements. @@ -27,7 +28,7 @@ Langium provides out-of-the-box solutions for these problems, with the ability t ## Language Parsing -Programming languages and domain specific languages (DSLs) cannot be parsed using simple regular expressions (RegExp). Instead they require a more sophisticated parsing strategy. To define a custom language in Langium, you interact with a high level representation of your context-free grammar using the [Langium grammar language](/docs/reference/grammar-language), in a similar fashion to EBNF. +Programming languages and domain specific languages (DSLs) cannot be parsed using simple regular expressions (RegExp). Instead they require a more sophisticated parsing strategy. To define a custom language in Langium, you interact with a high level representation of your context-free grammar using the [Langium grammar language](../reference/grammar-language), in a similar fashion to EBNF. Based on the grammar, Langium is then able to construct a parser which transforms an input string into a semantic model representation. Just as the name suggests, this model captures the essential structure to describe your language. @@ -101,4 +102,4 @@ The LSP includes commonly used language features, such as code completion, custo You can try out most of these features using our [showcase](/showcase/) and [playground](/playground/). The languages shown there are written using Langium and integrated in the monaco-editor. -If you're interested in Langium, you can check out our [learning](/docs/learn/workflow) page next. There you'll learn how to get started writing your first language, and to learn more about how Langium can help you achieve your language designing goals. +If you're interested in Langium, you can check out our [learning](../learn/workflow) page next. There you'll learn how to get started writing your first language, and to learn more about how Langium can help you achieve your language designing goals. diff --git a/hugo/content/docs/introduction/playground.md b/hugo/content/docs/introduction/playground.md index c39edb55..93712c28 100644 --- a/hugo/content/docs/introduction/playground.md +++ b/hugo/content/docs/introduction/playground.md @@ -2,4 +2,4 @@ title: "Try it out!" weight: 400 --- - \ No newline at end of file + \ No newline at end of file diff --git a/hugo/content/docs/learn/_index.md b/hugo/content/docs/learn/_index.md index 71d41073..4bf74278 100644 --- a/hugo/content/docs/learn/_index.md +++ b/hugo/content/docs/learn/_index.md @@ -1,6 +1,5 @@ --- title: "Learn Langium" weight: 0 -url: /docs/learn --- diff --git a/hugo/content/docs/learn/minilogo/_index.md b/hugo/content/docs/learn/minilogo/_index.md index 504ad564..643d5464 100644 --- a/hugo/content/docs/learn/minilogo/_index.md +++ b/hugo/content/docs/learn/minilogo/_index.md @@ -19,4 +19,4 @@ By working through each of these tutorials, you'll be learning about: By the end of this series, you should be equipped to start working on your own language, and also have a pretty good idea for how you can integrate Langium into other projects as well. -With that being said, hop on in to the first guide on [Writing a Grammar in Langium](/docs/learn/minilogo/writing_a_grammar)! +With that being said, hop on in to the first guide on [Writing a Grammar in Langium](./writing_a_grammar)! diff --git a/hugo/content/docs/learn/minilogo/building_an_extension/_index.md b/hugo/content/docs/learn/minilogo/building_an_extension/_index.md index b50c7a1c..e2f5a810 100644 --- a/hugo/content/docs/learn/minilogo/building_an_extension/_index.md +++ b/hugo/content/docs/learn/minilogo/building_an_extension/_index.md @@ -7,11 +7,11 @@ aliases: {{< toc format=html >}} -In this tutorial we'll be going over how to build a VSIX extension (VSCode extension) for your Langium-based language. This will allow providing LSP support in VSCode for your language. We'll assume that you've already looked at the previous tutorial, and have had time to read the [guide on bundling](/docs/recipes/code-bundling), so that you're ready to build an extension. At this point we assume that your language is also working, and there are no issues running `npm run langium:generate` or `npm run build`. If there are, you'll want to correct those first. +In this tutorial we'll be going over how to build a VSIX extension (VSCode extension) for your Langium-based language. This will allow providing LSP support in VSCode for your language. We'll assume that you've already looked at the previous tutorial, and have had time to read the [guide on bundling](../../../recipes/code-bundling), so that you're ready to build an extension. At this point we assume that your language is also working, and there are no issues running `npm run langium:generate` or `npm run build`. If there are, you'll want to correct those first. ## Setting up the Scripts -To get started, you'll want to have a language expressed in Langium, such as [Lox](https://github.com/langium/langium-lox) or [MiniLogo](https://github.com/langium/langium-minilogo). If you have been following along with these tutorials, you should already have something ready. If you don't you can also use the default language generated by the yeoman generator for Langium, presented in the [workflow](/docs/learn/workflow/) section. +To get started, you'll want to have a language expressed in Langium, such as [Lox](https://github.com/langium/langium-lox) or [MiniLogo](https://github.com/langium/langium-minilogo). If you have been following along with these tutorials, you should already have something ready. If you don't you can also use the default language generated by the yeoman generator for Langium, presented in the [workflow](../../workflow/) section. Regardless of what you're working with, you'll want to make sure you have the following scripts in your **package.json**. @@ -89,4 +89,4 @@ And that's it, at this point you have an extension for your language that you ca As a quick aside, it's important to keep the extensions that your language recognizes synchronized in both your **package.json** and your **langium-config.json**. If you do make changes to your extensions, it's a good idea to double check that these are both synced up, and to do a full rebuild to get those changes into your extension. -And that's it for building an extension. In the next tutorial, we'll be setting up [Langium + Monaco in the web](/docs/learn/minilogo/langium_and_monaco/). +And that's it for building an extension. In the next tutorial, we'll be setting up [Langium + Monaco in the web](../langium_and_monaco/). diff --git a/hugo/content/docs/learn/minilogo/customizing_cli.md b/hugo/content/docs/learn/minilogo/customizing_cli.md index d2894308..8a3ec08e 100644 --- a/hugo/content/docs/learn/minilogo/customizing_cli.md +++ b/hugo/content/docs/learn/minilogo/customizing_cli.md @@ -7,7 +7,7 @@ aliases: {{< toc format=html >}} -In this tutorial, we'll be talking about customizing the command line interface for your language. We recommend reading through previous tutorials about [writing a grammar](/docs/learn/minilogo/writing_a_grammar) and [validation](/docs/learn/minilogo/validation). Once you have a good grasp on those concepts, then you should be all set for setting up a CLI. We will also continue to use the [MiniLogo](https://github.com/langium/langium-minilogo) language as a motivating example. +In this tutorial, we'll be talking about customizing the command line interface for your language. We recommend reading through previous tutorials about [writing a grammar](./writing_a_grammar) and [validation](./validation). Once you have a good grasp on those concepts, then you should be all set for setting up a CLI. We will also continue to use the [MiniLogo](https://github.com/langium/langium-minilogo) language as a motivating example. ## Overview @@ -17,7 +17,7 @@ Once you have a grammar and some validation in place, you may want to start conf If you've been using a language built with the yeoman generator for Langium, you should be able to find your CLI defined in **src/cli/index.ts**. This file describes the general layout of your languages's command line interface, and lets you register specific commands. By default, you're provided with a single command for your CLI, the **generate** command. -Much like the command implies, it allows you to take a program written in your DSL, parse it, and traverse the AST to produce some sort of generated output. We won't talk about the generator itself in this tutorial (that will come in the [next tutorial on generation](/docs/learn/minilogo/generation)). Instead we'll focus on a simple example for parsing and validating a program, which allows learning more about the CLI itself. +Much like the command implies, it allows you to take a program written in your DSL, parse it, and traverse the AST to produce some sort of generated output. We won't talk about the generator itself in this tutorial (that will come in the [next tutorial on generation](./generation)). Instead we'll focus on a simple example for parsing and validating a program, which allows learning more about the CLI itself. ## Adding a Parse and Validate Action @@ -150,4 +150,4 @@ Running the CLI again should show that this program has an error, and better yet This is perfect, as we didn't have to implement too much more logic to get validation in our CLI. Since we already hooked up our validation service before, the CLI just handles the interaction with an external program. This separation of concerns makes for a very flexible implementation that is easy to adapt over time. -That sums up how to add basic CLI functionality. [In the next tutorial, we will be talking about generation in more detail](/docs/learn/minilogo/generation), specifically about techniques that you can use to traverse your AST and produce a generated output. +That sums up how to add basic CLI functionality. [In the next tutorial, we will be talking about generation in more detail](./generation), specifically about techniques that you can use to traverse your AST and produce a generated output. diff --git a/hugo/content/docs/learn/minilogo/generation.md b/hugo/content/docs/learn/minilogo/generation.md index 7b47d670..a64b9045 100644 --- a/hugo/content/docs/learn/minilogo/generation.md +++ b/hugo/content/docs/learn/minilogo/generation.md @@ -7,7 +7,7 @@ aliases: {{< toc format=html >}} -In this tutorial we'll be showing how to implement basic generation for your language. When we're talking about generation, we're talking about transforming an AST from your Langium-based language into some output target. This could be another language of similar functionality (transpilation), a lower level language (compilation), or generating some artifacts/data that will be consumed by another application. If you haven't already, make sure to go back over and check out the [tutorial on customizing your CLI](/docs/learn/minilogo/customizing_cli), as it touches on details about how to implement endpoints for your application (like generation). +In this tutorial we'll be showing how to implement basic generation for your language. When we're talking about generation, we're talking about transforming an AST from your Langium-based language into some output target. This could be another language of similar functionality (transpilation), a lower level language (compilation), or generating some artifacts/data that will be consumed by another application. If you haven't already, make sure to go back over and check out the [tutorial on customizing your CLI](./customizing_cli), as it touches on details about how to implement endpoints for your application (like generation). Per usual, we'll be using the MiniLogo language as a motivating example here. @@ -377,4 +377,4 @@ If you're looking at the implementation of [MiniLogo that we've already written We could continue to extend on this with new features, and generate new sorts of output using a given input language. In this tutorial, we're able to take a MiniLogo program and convert it into some simple JSON drawing instructions that can be consumed by another program. This opens the door for us to write such a program in another language, such as Python or Javascript, and draw with these results. In later tutorials, we'll be talking about how to run Langium in the web with generation, so that we can immediately verify our results by drawing on an HTML5 canvas. -We recommend that you next read [the guide on bundling your language with Langium to reduce its size](/docs/recipes/code-bundling), before moving onto the tutorial about [bundling an extension](/docs/learn/minilogo/building_an_extension). This is an important step before deployment as an extension for VSCode, and also if you're planning to later deploy your language in the web. +We recommend that you next read [the guide on bundling your language with Langium to reduce its size](../../recipes/code-bundling), before moving onto the tutorial about [bundling an extension](./building_an_extension). This is an important step before deployment as an extension for VSCode, and also if you're planning to later deploy your language in the web. diff --git a/hugo/content/docs/learn/minilogo/generation_in_the_web.md b/hugo/content/docs/learn/minilogo/generation_in_the_web.md index c8db7cdb..bb181e8c 100644 --- a/hugo/content/docs/learn/minilogo/generation_in_the_web.md +++ b/hugo/content/docs/learn/minilogo/generation_in_the_web.md @@ -83,7 +83,7 @@ shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, documents And that's it for setting up the onBuildPhase listener itself. We still need to address the usage of `generateMiniLogoCmds`, which is tied to the LS implementation. -Based on the work done in previous tutorials, we already have set up a working generator with MinLogo. If you haven't already set this up you can go back to the [tutorial on generation](/docs/learn/minilogo/generation) and give it a look over. Ideally, we'll already have setup our `generateStatements` function for MiniLogo, meaning so long as the imported module doesn't have any modules that are browser incompatible, we should be able to use it as is. Based on the previous setup however, we should have a **generator.js** file that is free of such conflicts, as much of them should be separated into the cli directly. +Based on the work done in previous tutorials, we already have set up a working generator with MinLogo. If you haven't already set this up you can go back to the [tutorial on generation](./generation) and give it a look over. Ideally, we'll already have setup our `generateStatements` function for MiniLogo, meaning so long as the imported module doesn't have any modules that are browser incompatible, we should be able to use it as is. Based on the previous setup however, we should have a **generator.js** file that is free of such conflicts, as much of them should be separated into the cli directly. This saves us quite a bit of time, since we don't need to handle setting up & dispatching a document for validation, we simply tap into the existing workflow and collect the result when it's ready. This is a great example of how Langium's architecture allows us to easily extend existing functionality, and add new features without having to rewrite existing code. @@ -91,7 +91,7 @@ As a concluding note for this section, don't forget to rebuild your language ser ## Listening for Notifications in the Client -The next step we need to make is to actually listen for these notifications from the client's end. This takes us back to the [Langium + Monaco](/docs/learn/minilogo/langium_and_monaco) setup in the previous tutorial. +The next step we need to make is to actually listen for these notifications from the client's end. This takes us back to the [Langium + Monaco](./langium_and_monaco) setup in the previous tutorial. After starting the wrapper successfully, we want to retrieve the MonacoLanguageClient instance (a wrapper around the language client itself) and listen for `browser/DocumentChange` notifications. diff --git a/hugo/content/docs/learn/minilogo/langium_and_monaco.md b/hugo/content/docs/learn/minilogo/langium_and_monaco.md index 4dcee7b3..4362584e 100644 --- a/hugo/content/docs/learn/minilogo/langium_and_monaco.md +++ b/hugo/content/docs/learn/minilogo/langium_and_monaco.md @@ -618,4 +618,4 @@ npm run serve You should be greeted with a page that contains a working Monaco instance and a small MiniLogo program in the editor. This editor has the highlighting we would expect, and also is fully connected to the language server for our language. This means we have full LSP support for operations that we would expect to have in a native IDE, such as VSCode. -And that's it, we have successfully implemented Langium + Monaco in the web for our language. It's not doing much at this time besides presenting us with an editor, but in the next tutorial we'll talk about [using the same setup to add generation in the web](/docs/learn/minilogo/generation_in_the_web). Since our generation has already been configured natively in prior tutorials, we can use what we've written to quickly implement a web application that translates MiniLogo programs into drawing instructions for an HTML5 canvas. +And that's it, we have successfully implemented Langium + Monaco in the web for our language. It's not doing much at this time besides presenting us with an editor, but in the next tutorial we'll talk about [using the same setup to add generation in the web](./generation_in_the_web). Since our generation has already been configured natively in prior tutorials, we can use what we've written to quickly implement a web application that translates MiniLogo programs into drawing instructions for an HTML5 canvas. diff --git a/hugo/content/docs/learn/minilogo/validation.md b/hugo/content/docs/learn/minilogo/validation.md index c37a5189..fb04b7e4 100644 --- a/hugo/content/docs/learn/minilogo/validation.md +++ b/hugo/content/docs/learn/minilogo/validation.md @@ -7,7 +7,7 @@ aliases: {{< toc format=html >}} -In this tutorial, we will be talking about implementing validation for your Langium-based language. We recommend first reading the previous tutorial about [writing a grammar](/docs/learn/minilogo/writing_a_grammar/), as we will assume you're familiar with the topics covered there. We'll also assume that you have a working language to add validation to, so double check that `npm run langium:generate` succeeds without errors before you proceed. +In this tutorial, we will be talking about implementing validation for your Langium-based language. We recommend first reading the previous tutorial about [writing a grammar](./writing_a_grammar/), as we will assume you're familiar with the topics covered there. We'll also assume that you have a working language to add validation to, so double check that `npm run langium:generate` succeeds without errors before you proceed. For this tutorial, we'll be implementing validation for the [MiniLogo language](https://github.com/langium/langium-minilogo), but you can use your own language to follow along as well. @@ -152,4 +152,4 @@ checkUniqueParams(def: Def, accept: ValidationAcceptor): void { Although we've only implemented a pair of validations, hopefully this demonstrates the flexibility of the validator API. The validator can help enforce constraints or features of your language, and ensure that your programs are correct. You could also explore more customized validations for specific cases, perhaps where a parameter and a definition share the same name -- which is not handled here. So long as you can identify the AST node type that you need to validate, you can implement the logic here. -That's all for validation. Next we'll be talking about how we can [customize our CLI](/docs/learn/minilogo/customizing_cli). +That's all for validation. Next we'll be talking about how we can [customize our CLI](./customizing_cli). diff --git a/hugo/content/docs/learn/minilogo/writing_a_grammar.md b/hugo/content/docs/learn/minilogo/writing_a_grammar.md index 84b50b0b..92ef6a60 100644 --- a/hugo/content/docs/learn/minilogo/writing_a_grammar.md +++ b/hugo/content/docs/learn/minilogo/writing_a_grammar.md @@ -39,7 +39,7 @@ Now that we have an idea of our semantics and our concrete syntax, we can then s As an aside, our version of MiniLogo will be an *approximation* of Dr. Walkingshaw's version. We won't adhere to it completely, and we won't be incorporating some elements, such as variable declarations. -To get started sketching the grammar we'll be using the **Hello World** example from the yeoman generator. You can read about how to get this setup in the [learning](/docs/learn/workflow/) section of our docs. We'll be working with a fresh from the generator using only the defaults, and building up from that. We'll begin by modifying the default grammar file, and updating it to work for MiniLogo. You can find this file under **src/language/hello-world.langium** in your new project. If you used a name other than the default, the file will still be there, but using your custom name instead. +To get started sketching the grammar we'll be using the **Hello World** example from the yeoman generator. You can read about how to get this setup in the [learning](../workflow/) section of our docs. We'll be working with a fresh from the generator using only the defaults, and building up from that. We'll begin by modifying the default grammar file, and updating it to work for MiniLogo. You can find this file under **src/language/hello-world.langium** in your new project. If you used a name other than the default, the file will still be there, but using your custom name instead. We'll be overriding the existing langium grammar file completely, so delete the old contents before we begin. @@ -312,4 +312,4 @@ The generation should finish successfully, indicating that our grammar doesn't h - a semantic model (that ASTs can be mapped onto) - a parser that recognizes our language -With that, we have the beginnings of our very own language! Hopefully this gives a good idea of how to express a grammar in Langium, particularly with consideration to your concrete syntax & semantic domain. You can also consider the ways we can express cases that are left-recursive, like expressions, in an alternative fashion. Overall, our grammar should now be ready for the next step of [validation in the following tutorial](/docs/learn/minilogo/validation). +With that, we have the beginnings of our very own language! Hopefully this gives a good idea of how to express a grammar in Langium, particularly with consideration to your concrete syntax & semantic domain. You can also consider the ways we can express cases that are left-recursive, like expressions, in an alternative fashion. Overall, our grammar should now be ready for the next step of [validation in the following tutorial](validation). diff --git a/hugo/content/docs/learn/workflow/_index.md b/hugo/content/docs/learn/workflow/_index.md index ddec04f2..439894a8 100644 --- a/hugo/content/docs/learn/workflow/_index.md +++ b/hugo/content/docs/learn/workflow/_index.md @@ -1,13 +1,12 @@ --- title: "Langium's workflow" weight: 0 -url: /docs/learn/workflow aliases: - /docs/getting-started --- Langium's workflow can be expressed as a flow chart diagram, which boils down to the following steps in the diagram. -Be aware of the fact that the possibilities go beyond this simple workflow. For more advanced topics, you can find answers in the [recipes](/docs/recipes). +Be aware of the fact that the possibilities go beyond this simple workflow. For more advanced topics, you can find answers in the [recipes](../../recipes). {{}} flowchart TD @@ -40,43 +39,43 @@ This simple introduction can be seen as three main parts: * setting up your project environment (1.+2.): this is only done once * specifying the language features (3.-7.): this cycle you need to go through for each grammar change -* everything advanced (8.): The limit of the common workflow is reached here. For specific questions you can find answers in the [recipes](/docs/recipes). +* everything advanced (8.): The limit of the common workflow is reached here. For specific questions you can find answers in the [recipes](../../recipes). While the first part is straight-forward, the last part is about advanced topics that differ from project to project. The middle part will be explained briefly in the following section. ## Initial setup -### [1. Install Yeoman](/docs/learn/workflow/install) +### [1. Install Yeoman](./install) This step ensures that you start a Langium project with the Yeoman generator. Yeoman is a scaffolding tool that helps you to start a new project with a predefined structure. -### [2. Scaffold a Langium project](/docs/learn/workflow/scaffold) +### [2. Scaffold a Langium project](./scaffold) After installing Yeoman, you can scaffold a new Langium project. ## Core workflow -### [3. Write the grammar](/docs/learn/workflow/write_grammar) +### [3. Write the grammar](./write_grammar) The first step in the core workflow starts with the grammar. You will have some language feature in mind that you want to implement. The grammar is used to nail down the syntax of your features. You can use our Langium VS Code extension to get syntax highlighting and code completion for `.langium` files. If your grammar is free of errors, you can generate the files for the _abstract syntax tree (AST)_. -### [4. Generate the AST](/docs/learn/workflow/generate_ast) +### [4. Generate the AST](./generate_ast) The AST is the backbone of your language. It is used to represent the structure of your language elements. The AST is generated from the grammar. One important part of the AST are the _cross-references_. They are used to resolve references between language elements. If you have cross-references in your language, you need to _resolve_ them, after this step. The actual generation is done by a call of the Langium CLI. -### [5. Resolve cross-references](/docs/learn/workflow/resolve_cross_references) +### [5. Resolve cross-references](./resolve_cross_references) The cross-references are used to resolve references between language elements (between different sub trees of one file or even elements of other files(!)). This step is quite important, because it is the basis for the next steps. You can also see it like this: Step 4 will generate an AST with gaps, this fifth step will fill these gaps. -### [6. Create validations](/docs/learn/workflow/create_validations) +### [6. Create validations](./create_validations) From here we have a fully utilized AST. Now every input file that matches the syntax will be accepted. But we want to have more control over the input. We want to check if the input is semantically correct. This is done by creating _validations_. They are used to check the input against a set of rules. If the input does not match the rules, an error will be thrown. -### [7. Generate artifacts](/docs/learn/workflow/generate_everything) +### [7. Generate artifacts](./generate_everything) Now you have a fully working language. You can generate whatever you want from the input. This can be code, documentation, or anything else. You can use the AST to traverse the input and generate the output. -## [Find advanced topics](/docs/recipes) +## [Find advanced topics](../../recipes) Everything that is out of the scope of the common workflow is covered in the recipes. Here you can find answers to specific questions or problems that you might encounter during the development of your language. diff --git a/hugo/content/docs/learn/workflow/create_validations.md b/hugo/content/docs/learn/workflow/create_validations.md index 5022506d..af7f87aa 100644 --- a/hugo/content/docs/learn/workflow/create_validations.md +++ b/hugo/content/docs/learn/workflow/create_validations.md @@ -1,7 +1,6 @@ --- title: "6. Create validations" weight: 700 -url: /docs/learn/workflow/create_validations --- After resolving the cross-references, you can assume that the syntax tree is complete. Now you can start with the validation of the input files. The validation process is a crucial part of the language engineering workflow. The parser ensures the syntactic correctness of the input files. The validation process ensures the semantic correctness of the input files. diff --git a/hugo/content/docs/learn/workflow/generate_ast.md b/hugo/content/docs/learn/workflow/generate_ast.md index 8539c529..a5946da7 100644 --- a/hugo/content/docs/learn/workflow/generate_ast.md +++ b/hugo/content/docs/learn/workflow/generate_ast.md @@ -1,7 +1,6 @@ --- title: "4. Generate the AST" weight: 500 -url: /docs/learn/workflow/generate_ast --- After defining the grammar, you can generate the abstract syntax tree (AST) of your language. The AST is a tree representation of the source code that can be used to analyze and transform the code. The AST definition is generated by the Langium CLI. Simply call the following command on your terminal: diff --git a/hugo/content/docs/learn/workflow/generate_everything.md b/hugo/content/docs/learn/workflow/generate_everything.md index 39644153..146b10ec 100644 --- a/hugo/content/docs/learn/workflow/generate_everything.md +++ b/hugo/content/docs/learn/workflow/generate_everything.md @@ -1,7 +1,6 @@ --- title: "7. Generate artifacts" weight: 800 -url: /docs/learn/workflow/generate_everything --- The syntax was ensured. The semantics were checked. Your workspace is free of errors. Now the AST is a valid representation of your input file written in your language. It is time to generate some cool stuff! diff --git a/hugo/content/docs/learn/workflow/install.md b/hugo/content/docs/learn/workflow/install.md index cd369234..8d9d804a 100644 --- a/hugo/content/docs/learn/workflow/install.md +++ b/hugo/content/docs/learn/workflow/install.md @@ -1,7 +1,6 @@ --- title: "1. Install Yeoman" weight: 200 -url: /docs/learn/workflow/install --- Before diving into Langium itself, let's get your environment ready for development: diff --git a/hugo/content/docs/learn/workflow/resolve_cross_references.md b/hugo/content/docs/learn/workflow/resolve_cross_references.md index 72a84d4b..545161ca 100644 --- a/hugo/content/docs/learn/workflow/resolve_cross_references.md +++ b/hugo/content/docs/learn/workflow/resolve_cross_references.md @@ -1,7 +1,6 @@ --- title: "5. Resolve cross-references" weight: 600 -url: /docs/learn/workflow/resolve_cross_references --- This step takes place after generating the AST. The AST definition was created and you are able to parse input files. But the AST is not complete yet. It contains _cross-references_ that are not resolved. Cross-references are used to reference other elements in your language. diff --git a/hugo/content/docs/learn/workflow/scaffold.md b/hugo/content/docs/learn/workflow/scaffold.md index 071b69c9..c83b7058 100644 --- a/hugo/content/docs/learn/workflow/scaffold.md +++ b/hugo/content/docs/learn/workflow/scaffold.md @@ -1,7 +1,6 @@ --- title: "2. Scaffold a Langium project" weight: 300 -url: /docs/learn/workflow/scaffold --- To create your first working DSL, execute the Yeoman generator: diff --git a/hugo/content/docs/learn/workflow/write_grammar.md b/hugo/content/docs/learn/workflow/write_grammar.md index 8bebf921..c81c3042 100644 --- a/hugo/content/docs/learn/workflow/write_grammar.md +++ b/hugo/content/docs/learn/workflow/write_grammar.md @@ -1,7 +1,6 @@ --- title: "3. Write the grammar" weight: 400 -url: /docs/learn/workflow/write_grammar --- Your Langium project is now setup and ready to be used. The next step is to define the grammar of your language. The grammar is the most important part of your language definition. It defines the syntax of your language and how the language elements are structured. @@ -55,4 +54,4 @@ Greeting: 'Hello' person=[Person] '!'; Like the previous rule, the `Greeting` starts with a keyword. With the `person` assignment we introduce the _cross reference_, indicated by the brackets `[]`. A cross reference will allow your grammar to reference other elements that are contained in your file or workspace. By default, Langium will try to resolve this cross reference by parsing the terminal that is associated with its `name` property. In this case, we are looking for a `Person` whose `name` property matches the parsed `ID`. -That finishes the short introduction to Langium! Feel free to play around with the grammar and use `npm run langium:generate` to regenerate the generated TypeScript files. To go further, we suggest that you continue with our [tutorials](/docs/learn/minilogo/). +That finishes the short introduction to Langium! Feel free to play around with the grammar and use `npm run langium:generate` to regenerate the generated TypeScript files. To go further, we suggest that you continue with our [tutorials](../minilogo/). diff --git a/hugo/content/docs/recipes/_index.md b/hugo/content/docs/recipes/_index.md index 105b28bf..e0382023 100644 --- a/hugo/content/docs/recipes/_index.md +++ b/hugo/content/docs/recipes/_index.md @@ -1,7 +1,6 @@ --- title: "Recipes" weight: 400 -url: "/docs/recipes" --- ## Where to go from here? diff --git a/hugo/content/docs/recipes/builtin-library.md b/hugo/content/docs/recipes/builtin-library.md index 974047cd..9bbd5086 100644 --- a/hugo/content/docs/recipes/builtin-library.md +++ b/hugo/content/docs/recipes/builtin-library.md @@ -8,7 +8,7 @@ For example, TypeScript provides users with typings for globally accessible vari They are part of the JavaScript runtime, and not defined by any user or a package they might import. Instead, these features are contributed through what we call builtin libraries. -Loading a builtin library in Langium is very simple. We first start off with defining the source code of the library using the *hello world* language from the [getting started guide](/docs/learn/workflow): +Loading a builtin library in Langium is very simple. We first start off with defining the source code of the library using the *hello world* language from the [getting started guide](../learn/workflow): ```ts export const builtinHelloWorld = ` diff --git a/hugo/content/docs/recipes/code-bundling.md b/hugo/content/docs/recipes/code-bundling.md index 1f2d0183..384e2c26 100644 --- a/hugo/content/docs/recipes/code-bundling.md +++ b/hugo/content/docs/recipes/code-bundling.md @@ -5,7 +5,7 @@ aliases: - /guides/code-bundling --- -When you first create a Langium project using the [Yeoman generator](/docs/learn/workflow/scaffold#your-first-example-language), it will only contain a plain TypeScript configuration, without any additional build processes. +When you first create a Langium project using the [Yeoman generator](../learn/workflow/scaffold#your-first-example-language), it will only contain a plain TypeScript configuration, without any additional build processes. However, if you want to make your language available for consumption in a non-development context, you'll want to create a bundle. It is not absolutely necessary in a Node.js context, since you can always resolve local `node_modules` but it's still recommended [for vscode extensions](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). It improves performance and decreases file size by minifying your code and only including what you actually need. diff --git a/hugo/content/docs/recipes/keywords-as-identifiers/_index.md b/hugo/content/docs/recipes/keywords-as-identifiers/_index.md index d5da355e..78b80b13 100644 --- a/hugo/content/docs/recipes/keywords-as-identifiers/_index.md +++ b/hugo/content/docs/recipes/keywords-as-identifiers/_index.md @@ -8,7 +8,7 @@ These _keywords_ get a special keyword highlighting whenever they are used, by d You will quickly notice that a function such as `function get()` will lead to parser errors by default, as `get` is identified as keyword and not as identifier. This guide is all about how to explicitly enable these keywords (highlighted in blue) to be supported as identifiers (highlighted in white) as well. -Let's look at the "hello-world" example in the [playground](https://langium.org/playground?grammar=OYJwhgthYgBAEgUwDbIPYHU0mQEwFD6IB2ALiAJ6wCyauKAXPrC7ABQAOiIAzmsTwDUAXgAK3PsVgAfWKESJSAS2LAhwgOIgFy1QEoAVAG5C43vyatYAci7ni12MUiJhASQAiJ-Fp0rglqzWSKhojnaSwgDaZpIMngC6NgCE1t4AFkq49FKk3BAqYMiwGADKDLAA9AA6QpUmeSAFzsWeFZVRAPpgALQAXgCCPQBaCVHVAO6dCQb1hJnZJLCNzUU0ADKdAMIA8tTUAKIAcgAq7dU1BuM81aUzAPzVBhdzCznL%2BYXFpZu7%2B8dnKoXC5RAB61WI1RAMzmQA&content=A4UwTgzg9gdgBAKQIYxAKABIgDbaolEAQjTVElji1yjSA) or as a new local project created with `yo langium` (for details, how to set up your first Langium project, read [getting started](/docs/learn/workflow/)): +Let's look at the "hello-world" example in the [playground](https://langium.org/playground?grammar=OYJwhgthYgBAEgUwDbIPYHU0mQEwFD6IB2ALiAJ6wCyauKAXPrC7ABQAOiIAzmsTwDUAXgAK3PsVgAfWKESJSAS2LAhwgOIgFy1QEoAVAG5C43vyatYAci7ni12MUiJhASQAiJ-Fp0rglqzWSKhojnaSwgDaZpIMngC6NgCE1t4AFkq49FKk3BAqYMiwGADKDLAA9AA6QpUmeSAFzsWeFZVRAPpgALQAXgCCPQBaCVHVAO6dCQb1hJnZJLCNzUU0ADKdAMIA8tTUAKIAcgAq7dU1BuM81aUzAPzVBhdzCznL%2BYXFpZu7%2B8dnKoXC5RAB61WI1RAMzmQA&content=A4UwTgzg9gdgBAKQIYxAKABIgDbaolEAQjTVElji1yjSA) or as a new local project created with `yo langium` (for details, how to set up your first Langium project, read [getting started](../../learn/workflow/)): ![screenshot with the editor, an example and an error message](problem.png) @@ -56,7 +56,7 @@ That's it! (Don't forget to run `npm run langium:generate` after updating the gr ![screenshot with fixed grammar](fixed-1-grammar.png) -Since the `name` property is used for cross-references by the parser rule for greetings, "Hello" needs to be supported here as well. For that we recommend to introduce a [data type rule](/docs/reference/grammar-language/#data-type-rules) like "PersonID" in the example, since it makes it easier to support more keywords in the future: +Since the `name` property is used for cross-references by the parser rule for greetings, "Hello" needs to be supported here as well. For that we recommend to introduce a [data type rule](../../reference/grammar-language/#data-type-rules) like "PersonID" in the example, since it makes it easier to support more keywords in the future: ```langium Person: 'person' name=PersonID; @@ -155,7 +155,7 @@ Additionally, using keywords as identifiers impacts the user experience, therefo Some hints beyond this guide: -- In [multi-grammar projects](/docs/recipes/multiple-languages), only keywords of the included grammars are affected by this general problem, but not keywords of other languages or Langium grammar files. +- In [multi-grammar projects](../../recipes/multiple-languages), only keywords of the included grammars are affected by this general problem, but not keywords of other languages or Langium grammar files. - In order to get an overview about the keywords of your language, have a look into the generated TextMate grammar `*.tmLanguage.json` and search for the pattern named `keyword.control.*`, which contains a regex with the keywords. - Read about the concept of semantic tokens in the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) (LSP) including predefined semantic types for tokens. - Read about how [VS Code](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide) realizes semantic highlighting using semantic tokens. diff --git a/hugo/content/docs/recipes/multiple-languages.md b/hugo/content/docs/recipes/multiple-languages.md index 112a20e9..9e1f8093 100644 --- a/hugo/content/docs/recipes/multiple-languages.md +++ b/hugo/content/docs/recipes/multiple-languages.md @@ -25,7 +25,7 @@ The entire change touches several files. Let's summarize what needs to be done: ## Our scenario -To keep this guide easy, I will use the [`hello-world` project](/docs/learn/workflow) of the learning section. +To keep this guide easy, I will use the [`hello-world` project](../learn/workflow) of the learning section. Let’s imagine that we have three languages: diff --git a/hugo/content/docs/recipes/scoping/_index.md b/hugo/content/docs/recipes/scoping/_index.md index 78b4d172..9d5debe5 100644 --- a/hugo/content/docs/recipes/scoping/_index.md +++ b/hugo/content/docs/recipes/scoping/_index.md @@ -19,15 +19,15 @@ This kind of behavior is called lexical scoping. Although this default scoping i In general, the way we resolve references is split into three phases of the document lifecycle: -- [Symbol indexing](/docs/reference/document-lifecycle#symbol-indexing) is responsible for making objects globally available for referencing. -- [Scope computation](/docs/reference/document-lifecycle#computing-scopes) determines which elements are reachable from a given position in your document. -- Finally, the [linking phase](/docs/reference/document-lifecycle#linking) eagerly links each reference within a document to its target using your language's scoping rules. +- [Symbol indexing](../../reference/document-lifecycle#symbol-indexing) is responsible for making objects globally available for referencing. +- [Scope computation](../../reference/document-lifecycle#computing-scopes) determines which elements are reachable from a given position in your document. +- Finally, the [linking phase](../../reference/document-lifecycle#linking) eagerly links each reference within a document to its target using your language's scoping rules. In this recipe, we'll look at different scoping kinds and styles and see how we can achieve them using Langium: -1. [Qualified Name Scoping](/docs/recipes/scoping/qualified-name) -2. [Class Member Scoping](/docs/recipes/scoping/class-member) -3. [File-based scoping](/docs/recipes/scoping/file-based) +1. [Qualified Name Scoping](../../recipes/scoping/qualified-name) +2. [Class Member Scoping](../../recipes/scoping/class-member) +3. [File-based scoping](../../recipes/scoping/file-based) Note that these are just example implementations for commonly used scoping methods. The scoping API of Langium is designed to be flexible and extensible for any kind of use case. diff --git a/hugo/content/docs/recipes/scoping/qualified-name.md b/hugo/content/docs/recipes/scoping/qualified-name.md index 715bcabd..8f9ffbb1 100644 --- a/hugo/content/docs/recipes/scoping/qualified-name.md +++ b/hugo/content/docs/recipes/scoping/qualified-name.md @@ -23,7 +23,7 @@ void main() { As can be seen, using qualified name scoping is quite helpful in this case. It allows us to reference the `getDocumentation` function through the scope computed & made available by the `Langium` namespace, even though it's not directly accessible within the scope of `main` by itself. -Note that such behavior can also be accomplished using [class member scoping](/docs/recipes/scoping/class-member). +Note that such behavior can also be accomplished using [class member scoping](./class-member). However, there is one core advantage to using globally available elements: Compared to member scoping, this type of scoping requires few resources. The lookup required for qualified name scoping can be done in near constant time with just a bit of additional computation on a **per-document** basis, whereas member scoping needs to do a lot of computation on a **per-reference** basis. diff --git a/hugo/content/docs/reference/_index.md b/hugo/content/docs/reference/_index.md index b6ab5a27..15b974b1 100644 --- a/hugo/content/docs/reference/_index.md +++ b/hugo/content/docs/reference/_index.md @@ -9,16 +9,16 @@ This section contains the reference documentation for Langium. ### Glossary -If you are looking for a specific term or concept, you can find it in the [glossary](/docs/reference/glossary). +If you are looking for a specific term or concept, you can find it in the [glossary](./glossary). ### Grammar language -If you are looking for a specific grammar language feature, you can find it in the [grammar language](/docs/reference/grammar-language). +If you are looking for a specific grammar language feature, you can find it in the [grammar language](./grammar-language). ### Architecture If you are looking for a specific architecture feature, here are some nice readings: -* [Configuration via services](/docs/reference/configuration-services) -* [Document lifecycle](/docs/reference/document-lifecycle) -* [Semantic model](/docs/reference/semantic-model) +* [Configuration via services](./configuration-services) +* [Document lifecycle](./document-lifecycle) +* [Semantic model](./semantic-model) diff --git a/hugo/content/docs/reference/grammar-language.md b/hugo/content/docs/reference/grammar-language.md index 03f2c3c3..ff41bb4d 100644 --- a/hugo/content/docs/reference/grammar-language.md +++ b/hugo/content/docs/reference/grammar-language.md @@ -82,7 +82,7 @@ Person: ``` In this example, the parser will create an object of type `Person`. This object will have a property `name` which value and type must match the terminal rule `ID` (i.e. the property `name` is of type `string` and cannot start with a digit or special character). -By default, the parser will create an object with an inferred type corresponding to the parser rule name. It is possible to override this behavior by explicitly defining the type of the object to be created. This is done by adding the keyword `returns` followed by a separately declared type, or the keyword `infers` followed by the name of the type to be inferred for this rule (more about this [in the next chapter](/docs/reference/semantic-model)): +By default, the parser will create an object with an inferred type corresponding to the parser rule name. It is possible to override this behavior by explicitly defining the type of the object to be created. This is done by adding the keyword `returns` followed by a separately declared type, or the keyword `infers` followed by the name of the type to be inferred for this rule (more about this [in the next chapter](./semantic-model)): ```langium Person infers OtherType: 'person' name=ID; @@ -236,7 +236,7 @@ RuleOne returns TypeOne: 'keywordOne' name=ID | {TypeTwo} 'keywordTwo' name=ID; ``` -The example above requires that the return types `TypeOne` and `TypeTwo` are declared separately (see [the next chapter](/docs/reference/semantic-model)). If the type returned by the action is created on-the-fly, the keyword `infer` needs to be added: +The example above requires that the return types `TypeOne` and `TypeTwo` are declared separately (see [the next chapter](./semantic-model)). If the type returned by the action is created on-the-fly, the keyword `infer` needs to be added: ```langium RuleOne infers TypeOne: diff --git a/hugo/content/docs/reference/semantic-model.md b/hugo/content/docs/reference/semantic-model.md index 151bb111..3f39acd0 100644 --- a/hugo/content/docs/reference/semantic-model.md +++ b/hugo/content/docs/reference/semantic-model.md @@ -92,7 +92,7 @@ interface X extends AstNode { ``` ### Assignments -There are three available kinds of [assignments](/docs/reference/grammar-language/#assignments) in a parser rule: +There are three available kinds of [assignments](./grammar-language/#assignments) in a parser rule: 1. `=` for assigning a **single value** to a property, resulting in the property's type to be derived from the right hand side of the assignment. 2. `+=` for assigning **multiple values** to a property, resulting in the property's type to be an array of the right hand side of the assignment. diff --git a/scripts/check-links.ts b/scripts/check-links.ts index 35bf3184..c48c653f 100644 --- a/scripts/check-links.ts +++ b/scripts/check-links.ts @@ -1,6 +1,6 @@ import { glob } from "glob"; import { readFile } from "node:fs/promises"; -import { basename, dirname, resolve, relative } from 'node:path'; +import { basename, dirname, resolve, relative, join } from 'node:path'; import chalk from 'chalk'; import fm from "front-matter"; @@ -83,27 +83,32 @@ async function readMarkdownFiles() { const content = await readFile(mdFile, 'utf-8'); //urls - const { attributes: { url, aliases, slug }, body } = fm(content); + const { attributes: { url, aliases, slug } } = fm(content); let urls: string[] = []; if (aliases) { urls = [...urls, ...aliases]; } let documentLink: string = ''; + let folder = ''; if (url) { documentLink = url; + folder = dirname(documentLink); } else if (slug) { - documentLink = relative(contentDir, resolve(mdFile, '..', slug)); + documentLink = relative(contentDir, join(mdFile, '..', slug)); + folder = dirname(documentLink); } else { const base = basename(mdFile, '.md'); if (['index', '_index'].includes(base)) { - documentLink = relative(contentDir, resolve(mdFile, '..')); + documentLink = relative(contentDir, join(mdFile, '..')); + folder = documentLink; } else { - documentLink = relative(contentDir, resolve(mdFile, '..', base)); + documentLink = relative(contentDir, join(mdFile, '..', base)); + folder = dirname(documentLink); } } //links - const links = getAllLinks(content); + const links = getAllLinks(folder, content); //new file markdownFiles.push({ @@ -116,14 +121,20 @@ async function readMarkdownFiles() { return markdownFiles; } -function getAllLinks(content: string) { +function getAllLinks(folder: string, content: string) { const regexMdLinks = /\[([^\[]+)\](\(.*?\))/gm const matches = content.match(regexMdLinks) const singleMatch = /\[([^\[]+)\]\((.*?)\)/; const result: string[] = []; for (var i = 0; i < matches?.length ?? 0; i++) { var text = singleMatch.exec(matches[i]) - result.push(text[2]); + const link = text[2]; + if(link.startsWith("http") || link.startsWith("/")) { + result.push(link); + } else if(link.startsWith("#")) { + } else { + result.push(join(folder, link)); + } } return result; } @@ -137,4 +148,4 @@ function urlToString(link: string): string { return url.toString(); } -main(); \ No newline at end of file +main();