Last active
August 13, 2020 16:04
-
-
Save heyajulia/3e2f889cdab2a59b3c0d58ca310d4b87 to your computer and use it in GitHub Desktop.
ANTLR4 grammar for a breakfast menu: https://craftinginterpreters.com/representing-code.html#rules-for-grammars
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage instructions
Prerequisites
Compiling
Parsing expressions with TestRig
Using the generated parser and lexer from Java