Skip to content

Instantly share code, notes, and snippets.

@heyajulia
Last active August 13, 2020 16:04
Show Gist options
  • Save heyajulia/3e2f889cdab2a59b3c0d58ca310d4b87 to your computer and use it in GitHub Desktop.
Save heyajulia/3e2f889cdab2a59b3c0d58ca310d4b87 to your computer and use it in GitHub Desktop.
grammar Breakfast;
breakfast : ('toast' | 'biscuits' | 'English muffin' | protein) ('with' breakfast 'on the side')? ;
protein : 'really'+ 'crispy bacon'
| 'sausage'
| ( 'scrambled' | 'poached' | 'fried' ) 'eggs' ;
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines
package com.example.breakfast;
import com.example.breakfast.BreakfastParser.BreakfastContext;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
public class Main {
public static void main(String[] args) {
String source = "poached eggs with English muffin on the side";
BreakfastLexer lexer = new BreakfastLexer(CharStreams.fromString(source));
BreakfastParser parser = new BreakfastParser(new CommonTokenStream(lexer));
BreakfastContext tree = parser.breakfast();
TranslatingBreakfastVisitor visitor = new TranslatingBreakfastVisitor();
System.out.println(visitor.visit(tree));
}
}
package com.example.breakfast;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.antlr.v4.runtime.tree.TerminalNode;
public class TranslatingBreakfastVisitor implements BreakfastVisitor<String> {
@Override
public String visitBreakfast(BreakfastParser.BreakfastContext ctx) {
StringBuilder sb = new StringBuilder();
for (ParseTree child : ctx.children) {
sb.append(child.accept(this));
}
return sb.toString();
}
@Override
public String visitProtein(BreakfastParser.ProteinContext ctx) {
StringBuilder sb = new StringBuilder();
for (ParseTree child : ctx.children) {
sb.append(child.accept(this));
}
return sb.toString();
}
@Override
public String visitCrispiness(BreakfastParser.CrispinessContext ctx) {
return "erg" + ", erg".repeat(Math.max(0, ctx.getChildCount() - 1));
}
@Override
public String visitCooked(BreakfastParser.CookedContext ctx) {
switch (ctx.getText()) {
case "scrambled":
return "roer";
case "poached":
return "gepocheerd ";
case "fried":
return "gefrituurd ";
default:
throw new IllegalStateException("Unexpected value: " + ctx.getText());
}
}
@Override
public String visitBread(BreakfastParser.BreadContext ctx) {
switch (ctx.getText()) {
case "toast":
return "toast";
case "biscuits":
return "biscuit";
case "English muffin":
return "Engelse muffin";
default:
throw new IllegalStateException("Unexpected value: " + ctx.getText());
}
}
@Override
public String visit(ParseTree parseTree) {
return parseTree.accept(this);
}
@Override
public String visitChildren(RuleNode ruleNode) {
return ruleNode.accept(this);
}
@Override
public String visitTerminal(TerminalNode terminalNode) {
switch (terminalNode.getText()) {
case "with":
return " met ";
case "crispy bacon":
return " knapperige bacon";
case "eggs":
return "ei";
case "sausage":
return "worst";
case "on the side":
return " erbij";
default:
throw new IllegalStateException("Unexpected value: " + terminalNode.getText());
}
}
@Override
public String visitErrorNode(ErrorNode errorNode) {
return "(fout)";
}
}
package com.example.breakfast
import com.example.breakfast.BreakfastParser.BreakfastContext
import com.example.breakfast.BreakfastParser.ProteinContext
import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.ErrorNode
import org.antlr.v4.runtime.tree.ParseTree
import org.antlr.v4.runtime.tree.RuleNode
import org.antlr.v4.runtime.tree.TerminalNode
class TranslatingBreakfastVisitor : BreakfastVisitor<String> {
override fun visit(tree: ParseTree): String {
return tree.accept(this)
}
private fun visitChildren(ctx: ParserRuleContext): String {
val sb = StringBuilder()
ctx.children.forEach {
sb.append(it.accept(this))
}
return sb.toString()
}
override fun visitBreakfast(ctx: BreakfastContext): String {
return visitChildren(ctx)
}
override fun visitProtein(ctx: ProteinContext): String {
return visitChildren(ctx)
}
override fun visitChildren(node: RuleNode): String {
return node.accept(this)
}
override fun visitErrorNode(node: ErrorNode): String {
return "(fout)"
}
override fun visitTerminal(node: TerminalNode): String {
return when (val text = node.text) {
"with" -> "met "
"on the side" -> "erbij "
"poached" -> "gepocheerde "
"eggs" -> "eieren "
"toast" -> "toast "
"biscuit" -> "Amerikaans biscuit "
"English muffin" -> "Engelse muffin "
"really" -> "erg "
"crispy bacon" -> "knapperige bacon "
"sausage" -> "worst "
"scrambled" -> "roer"
"fried" -> "gefrituurde "
else -> throw IllegalStateException("Unexpected value: $text")
}
}
}
@heyajulia
Copy link
Author

heyajulia commented Aug 12, 2020

Usage instructions

Prerequisites

  • Java JDK
  • Java JRE
  • ANTLR 4.8 "complete" JAR

Compiling

java -jar antlr-4.8-complete.jar Breakfast.g4
javac -cp antlr-4.8-complete.jar Breakfast*.java

Parsing expressions with TestRig

% java --class-path ".:antlr-4.8-complete.jar" org.antlr.v4.gui.TestRig Breakfast breakfast -gui
poached eggs with English muffin on the side
^D

ANTLR's graphical Parse Tree Inspector tool

Using the generated parser and lexer from Java

mkdir -p com/example/breakfast
mv *.java com/example/breakfast
java -jar antlr-4.8-complete.jar -package com.example.breakfast -visitor -o com/example/breakfast Breakfast.g4
javac -cp antlr-4.8-complete.jar com/example/breakfast/*.java
java -cp ".:antlr-4.8-complete.jar" com.example.breakfast.Main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment