|
Re: allow anythin in a block? [message #796773 is a reply to message #796740] |
Sun, 12 February 2012 14:39 |
Henrik Lindberg Messages: 2509 Registered: July 2009 |
Senior Member |
|
|
This is mainly a lexical problem, and as you figured out, you can not
simply have a terminal in the main language that eats everything - since
well - it will eat everything :)
You can try creating a data rule that accepts anything - e.g. something
like:
ALL : '{' (kw1 | ... | kwN | terminal1 | ... | terminalN)* '}' ;
but you then have to handle balanced blocks of things inside "ALL", and
before you know it, you are halfway through a grammar for the embedded
language.
An alternative is to use an external lexer (this is supported by Xtext,
so not as difficult as it sounds). In this lexer you can have more
advanced rules, use predicates, and replace which token gets returned
depending on context. The problem now is to be able to identify when the
lexer should switch to "ALL-mode" - this is problematic if the only
marker is a '{' that is in a particular place in the grammar. Looking at
the sample from your grammar, this particular block appears after seeing
')' '{' - which also does not seem significant enough. If you can modify
you language to use something more significant e.g. «lang» to indicate a
block in language 'lang' say something like:
Procedure: 'procedure' name = ID ( args+=ID* ')'
language = LANGUAGE '{' any_code += ANY* '}'
;
terminal LANGUAGE: '«' ID '»' ;
terminal ANY : . ;
....then, in your external lexer, you then:
- switch mode to "any-mode" when you see the LANGUAGE token
- make all terminals return token ANY instead of their normal return
(can be done by making rules active only when not in 'any-mode' or
by adding code to every terminal rule that checks mode).
- keep track of matching braces so you can find the end brace that
ends the "any-mode"
You can look at the external lexer in project cloudsmith/geppetto at
github where I do something similar.
An even simpler approach (somewhat uglier), is to use a special marker
for both the start and end of the external language - e.g. «lang»«/lang»
In this case, you can write a terminal that eats all of that. If you
don't care about the lang ID, you could use just '«' as start and '»' as
end for "foreign language text".
Hope that helps and gives you some ideas about how to proceed.
Regards
- henrik
On 2012-12-02 14:28, Phil Mising name wrote:
> Hi all,
>
> The DSL I create is allowing multiple languages to integrate. I don't
> have the time to implement syntax rules for the other languages. They
> will be implemented at a later date. For now it should be possible to
> enter anything in the corresponding blocks where later on other DSLs
> will be.
> Like:
> Procedure:
> 'procedure' name=ID '(' (args+=ID)* ')' '{' any_code=ALL '}' ;
>
> terminal ALL: '{' -> '}';
>
> I tried with a terminal, but then ofcourse in my main DSL the tokens
> will be active too. So above can't work because of other uses of the
> brackets in the main DSL.
>
> Any suggestions for a quick way to allow anything in the defined
> procedure above?
>
> Regards,
> Phil
|
|
|
|
Powered by
FUDForum. Page generated in 0.01473 seconds