Skip to content

Commit

Permalink
Fix antlr#3508: Document the $parser attribute and its use in target-…
Browse files Browse the repository at this point in the history
…agnostic grammars.

Signed-off-by: Ross Patterson <[email protected]>
  • Loading branch information
RossPatterson committed Aug 1, 2022
1 parent 1e35007 commit cad7792
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions doc/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ returnStat : 'return' expr {System.out.println("first token "+$start.getText());
|start|Token|The first token to be potentially matched by the rule that is on the main token channel; in other words, this attribute is never a hidden token. For rules that end up matching no tokens, this attribute points at the first token that could have been matched by this rule. When referring to the current rule, this attribute is available to any action within the rule.|
|stop|Token|The last nonhidden channel token to be matched by the rule. When referring to the current rule, this attribute is available only to the after and finally actions.|
|ctx|ParserRuleContext|The rule context object associated with a rule invocation. All of the other attributes are available through this attribute. For example, `$ctx.start` accesses the start field within the current rules context object. It’s the same as `$start`.|
|parser|Parser|The parser itself. This attribute can be used, for example, to invoke a method defined in the parser's `@members` section from a semantic predicate.|

## Dynamically-Scoped Attributes

Expand Down
33 changes: 29 additions & 4 deletions doc/python-target.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,39 @@ If your grammar is targeted to Python only, you may ignore the following. But if
ID {$text.equals("test")}?
```

Unfortunately, this is not portable, but you can work around it. The trick involves:
Unfortunately, this is not portable, as Java and Python (and other target languages) have different syntaxes for all but the simplest language elements. But you can work around it. The trick involves:

* deriving your parser from a parser you provide, such as BaseParser
* implementing utility methods in this BaseParser, such as "isEqualText"
* adding a "self" field to the Java/C# BaseParser, and initialize it with "this"
* implementing utility methods, such as "isEqualText", in this BaseParser, in different files for each target language
* invoking your utility methods in the semantic predicate from the `$parser` object

Thanks to the above, you should be able to rewrite the above semantic predicate as follows:

File `MyGrammarParser.g4`:
```
ID {$self.isEqualText($text,"test")}?
options { superClass = MyGrammarBaseParser; }
...
ID {$parser.isEqualText($text,"test")}?
```

File `MyGrammarBaseParser.py`:
```python
from antlr4 import *

class MyGrammarBaseParser(Parser):

def isEqualText(a, b):
return a is b
```

File `MyGrammarBaseParser.java`:
```java
import org.antlr.v4.runtime.*;

public abstract class MyGrammarBaseParser extends Parser {

public static boolean isEqualText(a, b) {
return a.equals(b);
}
}
```

0 comments on commit cad7792

Please sign in to comment.