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.
  • Loading branch information
RossPatterson committed Aug 1, 2022
1 parent 14703f2 commit 26d989f
Show file tree
Hide file tree
Showing 2 changed files with 29 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|Paser|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
32 changes: 28 additions & 4 deletions doc/python-target.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,38 @@ 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 MyParser.g4:
```
ID {$self.isEqualText($text,"test")}?
options { superClass = BaseParser; }
...
ID {$parser.isEqualText($text,"test")}?
```

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

class BaseParser(Parser):

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

File BaseParser.java
```java
import org.antlr.v4.runtime.*;

public abstract class BaseParser extends Parser

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

0 comments on commit 26d989f

Please sign in to comment.