The usual way of defining a new modelling language (languages like UML, BPMN, but also formal logics, such as LTL, CTL, paraconsistent logics, etc., really any language you can make models with) is to first decide what its purpose is. You then find and define the concepts and relations, which should be used to create models with that language, so that you can use these models to realise the purpose. If it is a formal language, then you define and prove some desirable properties that its models have.
If the purpose is, say, to model processes, then you probably need a concept for the smallest (primitive) steps that you want to make processes of, and relations to say that one step is before another, is done in parallel with another, and so on. So in that language, you can say in a model that step A is before B and that B is before C, and that C has to be done in parallel with step D.
It can be difficult to precisely define the purpose of a modelling language. To say that a language needs to model processes is not precise, which is illustrated by the variety of modelling languages which already exist, and all model processes in (sometimes only slightly) different ways.
The practical problem is that if you do not precisely define the purpose of the language, then designing it is harder, as your target starts moving: you make a language that can represent sequences of steps, and then you discover that you need to show parallel steps, and then, perhaps you think it is a good idea to enable it to show the timing of steps, and so on.
This is an issue I’ve seen over and over, and not only with young researchers.
A simple way to deal with these problems is to define Language Services that the language should deliver, before you choose the language components, define how they work together, and so on.
A Language Service is simply a question that you want ANY model of the language to be able to answer, and the answer should be the same, regardless of who asks (you, someone else, a machine that can read the models).
Here is an example of a Language Service:
Given a model M and a step x in M, which steps should be done before doing x?
Different languages can deliver this Language Service, but if a language defines what a step is, and conditions when a step is before another one, then it is clear how to compute the answer.
If the above was the only Language Service that a language had to satisfy, then the following language, call it P, is the simplest one which does so.
In P, any model is a set of expressions, and every expression is a pair (a, b), where a and b represent steps, and (a,b) represents that a should be done before b.
So P isa language with one concept, called “step”, and one relation, called “before”. If the before relation is transitive, then to answer the question in the language service, you have to find the transitive closure of the graph, in which nodes are steps, and edges are before relations. The answer is the set of all steps, on all paths that end in the step x. And the answer is independent of who asked, that is, it is not open to interpretation.
So the next time you need to make a modelling language, start by listing the Language Services that it should deliver.