ã¯ããã«
ããã«ã¡ã¯ãHabrauseræ§ã .NETãã©ãããã©ãŒã ã§ãCoolèšèªã§èšè¿°ãããã³ãŒããCIL ïŒCommon Intermediate LanguageïŒä»®æ³ãã·ã³ã®ã³ãŒãã«å€æããã³ã³ãã€ã©ãŒã®å®çšçãªäœæã«é¢ããè³æããèŠãããããšæããŸãã
æåã®éšåã§ã¯ãANTLRç°å¢ã§ã®æŒç®åã®åªå é äœãèæ ®ã«å ¥ããŠãCïŒèšèªã®ã¬ã¯ãµãŒãšããŒãµãŒãçæããææ³ãèšè¿°ããããã»ã¹ã«ã€ããŠèª¬æããŸãã ãŸããç§ã®éã§åºäŒã£ãèœãšãç©Žã調ã¹ãŸãã ãããã£ãŠãå°ãªããšã誰ãã®æéãç¯çŽããããšããŸãïŒå°æ¥çã«ã¯èªåã®ããã«ïŒã
2çªç®ã®éšåã§ã¯ã ã»ãã³ãã£ãã¯ã³ãŒãã¢ãã©ã€ã¶ãŒã®æ§ç¯ããã»ã¹ãã³ãŒãçæ ãããã³
èŠå ïŒãã®ã³ã³ãã€ã©ãéçºããåã«ãç§ã¯å®éã«äž»é¡ã®æç®ãå匷ããŸããã§ããã ç§ã®èå³ãåŒãããã€ãã®èšäºãèªãã ããå ¬åŒWebãµã€ãã§ANTLR ãããªãã¥ãŒããªã¢ã«ãèŠèŽãããããããããããã¯ã©ã¹ã¡ãŒããšè©±ãããããããšããã¹ãŠå€æããŸããã ãããã£ãŠãéçºããããœãããŠã§ã¢ã¯çæ³ãšã¯ã»ã©é ããã®ã§ãã
èªè ãç§ãããããç解ã§ããããã«ããŸãæåã«ããã€ãã®å®çŸ©ã瀺ããŸãïŒWikipediaããïŒã
- ããŒã¯ã³ - ããŒã¯ã³ã«å¯Ÿå¿ãããã³ã³ãã¥ãŒã¿ãŒãµã€ãšã³ã¹ã®åå¥è§£æã«ãããæåã®ã·ãŒã±ã³ã¹ã
- åå¥è§£æåšã¯ãåºåã§ãããŒã¯ã³ããšåŒã°ããæåã®ã·ãŒã±ã³ã¹ïŒæåãåèªã«ã°ã«ãŒãåãããªã©ïŒãååŸããããã«ãæåã®å ¥åã·ãŒã±ã³ã¹ïŒããšãã°ãããã°ã©ãã³ã°èšèªã®ãœãŒã¹ã³ãŒããªã©ïŒã®åæåæã®ããã®ã¢ãžã¥ãŒã«ã§ãã
- ããŒãµãŒã¯ãèšèªã®ããŒã¯ã³ïŒåèªãããŒã¯ã³ïŒã®ç·åœ¢ã·ãŒã±ã³ã¹ãæ£åŒãªææ³ãšæ¯èŒããããã®ã¢ãžã¥ãŒã«ã§ãã çµæã¯ã解æããªãŒãŸãã¯æ§æããªãŒã§ãã
ãã®ããã次ã®ããã°ã©ã ãšã©ã€ãã©ãªã䜿çšããŠã³ã³ãã€ã©ãéçºããŸããã
- ANTLRWorks-ææ³ãèšè¿°ããããŸããŸãªèšèªïŒCãCïŒãJavaãJavaScriptãObjective-CãPerlãPythonãRubyãªã©ïŒã®ã¬ã¯ãµãŒãšããŒãµãŒã®ã³ãŒããçæããããã®IDEã LLïŒ*ïŒè§£æã«åºã¥ããŠããŸãã
- ANTLR CïŒã©ã³ã¿ã€ã é åž ïŒAntlr3.Runtime.dllïŒã¯ãçæãããã¬ã¯ãµãŒãšããŒãµãŒã§äœ¿çšãããŸãã
- Visual Studio 2010次ã®èšäºã§ã¯ãæ§æã®åŒ·èª¿è¡šç€ºãšã³ãŒãè£å®ã®ããã®é«åºŠãªããã¹ããšãã£ã¿ãŒã§ããWPFã®ã³ã³ããŒãã³ãã«ã€ããŠèª¬æããŸãAvalonEdit ïŒã
- Javaã©ã³ã¿ã€ã ç°å¢ ïŒANTLRWorksã¯Javaã§èšè¿°ãããŠããããïŒã
- IL Disassemblerã¯ãCïŒãªã©ã®ã³ã³ãã€ã©ãCILã³ãŒããçæããæ¹æ³ãšããã®å€èŠ³ãç解ããããã«ã2çªç®ã®ããŒãã§äœ¿çšãããŸãã
èšèªã®èª¬æCool
ã¯ãŒã« -ã¯ã©ã¹ã«ãŒã ãªããžã§ã¯ãæåèšèªã¯ããã®ååã瀺ãããã«ãã¯ã©ã¹ããªããžã§ã¯ããªã©ã
ãã¹ãŠã®ãã£ãŒã«ãã¯ãåºæ¬ã¯ã©ã¹ãšæŽŸçã¯ã©ã¹å ã«è¡šç€ºãããŸãã ãã¹ãŠã®æ©èœã¯ã©ãããã§ãèŠãããšãã§ããŸãïŒãããªãã¯ïŒã
ãã®èšèªã¯åŒã«åºã¥ããŠããŸãã ãã¹ãŠã®é¢æ°ã¯åŒãåŒæ°ãšããŠåãããšãã§ãããã¹ãŠã®é¢æ°ã®æ¬äœã¯çµæãè¿ãåŒã§ãã è¡åºåãªã©ã®é¢æ°ã§ãããçµæãã€ãŸãåŒã³åºãå ã®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã
ãŸããCoolã«ã¯éçã¯ã©ã¹StringãIntãBoolãå«ãŸããŠããããããã¯ç¶æ¿ã§ãããnullå€ãåãããšãã§ããŸããïŒããã§ã¯voidãšåŒã°ããŸã ïŒã ãããã®ã¯ã©ã¹ã®ãªããžã§ã¯ãã¯ãåç §ã§ã¯ãªãå€ã«ãã£ãŠæž¡ãããŸã ã
ãã®èšèªã®ããŒã¯ãŒãïŒclassãelseãfalseãfiãifãinãinheritsãisvoidãletãloopãpoolãthenãwhileãcaseãesacãnewãofãnotãtrue
äžéšã®æŒç®åã¯ãäžãã£ãïŒCã®ãããªãã®ïŒãŸãã¯åèªã®çµããã§çµããããšã«æ³šæããŠãã ããã ïŒ
åæŒç®åãäœããã®çµæãè¿ãå Žåãifã¯äœãè¿ãå¿ èŠããããŸããïŒ çµå±ã®ãšããã圌ã¯2ã€ã®éžæè¢ã®ãªãã·ã§ã³ãè¿ãããšãã§ããŸãã æ£è§£ïŒæãè¿ãå ±éã®ç¥å ïŒæç§æžã§ã¯ãããã«ã€ããŠäœããã®åœ¢ã§è€éã«æžãããŠããŸããããŸã ç¹å¥ãªæŒç®åã䜿çšãããŠããŸãïŒã ããããããããããã«åçã瀺ããŸãã
å³1
ããã§ãã¯ã©ã¹Aããã³Bã®å Žåãæãè¿ãå ±éã®ç¥å ã¯ã¯ã©ã¹Dã§ãã
caseã¹ããŒãã¡ã³ãã¯ãifã¹ããŒãã¡ã³ããè€æ°åé©çšãããŠããããšã«äŒŒãŠããŸãã
voidã¯åžžã«whileæ§é äœã§è¿ãããŸãïŒãã¡ããã«ãŒããã«ãŒãããªãéãïŒã
ãã®ãããªæ§æ{<expr1>; ... <exprn>; }ã¯åŒexprnã®ãªããžã§ã¯ããã€ãŸã æåŸã®è¡šçŸã
ããã§ã®é¢æ°ã¯ãã¯ã©ã¹ãšãã®ç¥å ïŒä»®æ³é¢æ°ïŒã ãã§ãªããäžè¬ã«ãã®ã¯ã©ã¹ã®ç¥å ã§ãåŒã³åºãããšãã§ããŸãã ããã¯ãã@ãæŒç®åã䜿çšããŠå®è¡ã§ããŸãã äŸãšããŠãå³1ã®ã¯ã©ã¹éå±€ãèããŠã¿ãŸããããã¯ã©ã¹Eã«funcïŒïŒé¢æ°ãæãããä»ã®ãã¹ãŠã®åå«ã¯ç¬èªã®æ¹æ³ã§ãããåå®çŸ©ããŸãã 次ã«ããªããžã§ã¯ãAã®ã€ã³ã¹ã¿ã³ã¹ããããã¯ã©ã¹Dããfuncé¢æ°ãåŒã³åºãå Žåã次ã®æ§æã䜿çšããå¿ èŠããããŸãã
result <- (new A)@D.func()
SELF_TYPEããŒã¯ãŒã㯠ãç¹å®ã®æ©èœãèšè¿°ããã¯ã©ã¹ã®å矩èªãšããŠäœ¿çšãããŸãã èå¥åselfã¯ãçŸåšã®ã¯ã©ã¹ãžã®ãã€ã³ã¿ãŒã§ãïŒã€ãŸããããã¯ä»ã®èšèªã§ãïŒã
ããŒã«ã«å€æ°ã¯ã letæŒç®åã䜿çšããŠCoolèšèªã§å°å ¥ãããæå®ãããletãããã¯å ã§ã®ã¿äœ¿çšã§ããŸãã
void -nullã®é¡äŒŒç©ããªããžã§ã¯ããäœæãããŠããªãããšã瀺ããŸãã
ä»ã®ãã¹ãŠã®ãªãã¬ãŒã¿ãŒã¯èª¬æãå¿ èŠãšããªããšæããŸããæ確ã§ãªãå Žåã¯ãèšäºã®æåŸã«ç€ºãããŠãããªã³ã¯ã䜿çšããŠããã®ã¯ãŒã«ãªèšèªã®æ¹èšã®ããã¥ã¢ã«ãåŠç¿ã§ããŸãã
ANTLRWorksã§ã®ã¯ãŒã«ãªææ³ã®äœæ
ãããã£ãŠãå ã®ææ³ã¯æ¬¡ã®åœ¢åŒã§æäŸãããŸãã
program ::= [[class; ]]+ class ::= class TYPE [inherits TYPE] { [[feature; ]]*} feature ::= ID( [ formal [[, formal]]*] ) : TYPE { expr } | ID : TYPE [ <- expr ] formal ::= ID : TYPE expr ::= ID <- expr | expr[@TYPE].ID( [ expr [[, expr]]*] ) | ID( [ expr [[, expr]]*] ) | if expr then expr else expr fi | while expr loop expr pool | { [[expr; ]] +} | let ID : TYPE [ <- expr ] [[, ID : TYPE [ <- expr ]]]* in expr | case expr of [[ID : TYPE => expr; ]]+ esac | new TYPE | isvoid expr | expr + expr | expr ? expr | expr ? expr | expr / expr | ~expr | expr < expr | expr <= expr | expr = expr | not expr | (expr) | ID | integer | string | true | false
å¡äŸïŒ[[]] *-å埩; [[]] +ã¯æ£ã®å埩ã§ã;ã§ã¯ããã®ãããªææ³ãèŠãåŸã«äœãããå¿ èŠããããŸããïŒ
- å·Šååž°ã®ååšã ãã¡ãããååž°éäžæ³ã«åºã¥ãANTLRWorksã¯ããã®çš®ã®ãšã©ãŒãããã«æ€åºããŠçæããŸãã [èŽåœç]ã«ãŒã«compilation_unitã«ã¯ãaltããå°éå¯èœãªååž°ã«ãŒã«åŒã³åºãã«ããéLLïŒ*ïŒæ±ºå®ããããŸã...å·Šãã¡ã¯ã¿ãªã³ã°ãŸãã¯æ§æè¿°èªã䜿çšããŠè§£æ±ºããŸããŸãã¯backtrack = trueãªãã·ã§ã³ã䜿çšããŠ...ãããŠããã¡ãããANTLRã«ã¯ãªãã·ã§ã³backtrack = trueãããããã®å¶éãå æã§ããŸãã ãããããããé©çšãããšãå·Šååž°ã§ã®è¡šçŸã®ããã«ãçæãããå®å®è¹ã®å¥ã®ããŒããšäžèŽããå¿ èŠããããŸãã ããã§ããã¹ãŠåãããã«ããããåãé€ãããšã¯çŽ æŽãããããšã§ãã ããã«ããã®èšäºãããããããã«ããã®ãªãã·ã§ã³ã¯ããŒãµãŒã®é床ãäœäžããããããèè ã¯å¯èœãªéãããŒãµãŒãç Žæ£ããããšããå§ãããŸãã
- ããããäž»ãªããšã¯ããã®åœ¢åŒã®ææ³ã§ã¯æŒç®åã®åªå é äœãèæ ®ãããªãããšã§ãã å·Šååž°ãããŒãµãŒã®å¹çã«ã®ã¿åœ±é¿ããå Žåããã®åé¡ãç¡èŠãããšãåŸã§èª€ã£ãã³ãŒããçæãããŸãïŒããšãã°ã2 + 2 * 2ã¯6ã§ã¯ãªã8ã«ãªããŸãïŒ
- ã
- @
- ã
- èç¡
- * /
- +-
- <= <=
- ãããªã
- <-
expr: (ID ASSIGN^)* not; not: (NOT^)* relation; relation: addition ((LE^ | LT^ | GE^ | GT^ | EQUAL^) addition)*; addition: multiplication ((PLUS^ | MINUS^) multiplication)*; multiplication: isvoid ((MULT^ | DIV^) isvoid)*; isvoid: (ISVOID^)* neg; neg: (NEG^)* dot; dot: term ((ATSIGN typeName)? DOT ID LPAREN invokeExprs? RPAREN)? -> ^(Term term ID? typeName? invokeExprs?);
ãã®å Žåã®çšèªã«ã¯ãèæ ®ãããŠããªãæ®ãã®ãã¹ãŠã®åŒãå«ãŸããŸãã åãåªå 床ã®åŒã
èšèªã®ã³ã¡ã³ãã¯ãåºæ¬çã«è§£æã®éã«ç¡èŠããå¿ èŠãããäžé£ã®æåã§ãã ãã®ããã«ãANTLRã¯èšèšã䜿çšããŸã
ã³ã¡ã³ããèšè¿°ããåã«ãŒã«ã®å³åŽã«æžãããŠããŸãã äŸïŒ{$channel = Hidden;};
COMMENT : '--' .* ('\n'|'\r') {$channel = Hidden;};
ANTLRæŒç®å
次ã«ã䜿çšãããANTLRã¹ããŒãã¡ã³ãã«ã€ããŠèª¬æããŸãã
- ïŒ -è¿œå ã®èšèªããŒã¯ã³ã解æã劚ããªãããã«ããããã«å¿ èŠã§ãã ããšãã°ãããŒãµãŒã«ã®ã¿å¿ èŠãªè§ãã£ãããã®ä»ã®æŒç®åïŒããšãã°ãfiãesacæ§ææ§é ã®åãæ«å°ŸïŒã æ§ææšãæ§æ解ææšã§ã¯ãªãããŒã¯ã³ã®ã¹ããªãŒã ããæ§ç¯ãããããšãä¿èšŒããããã«ãæŒç®åãå¿ èŠã§ãã
- -> -ã¯ãå·ŠåŽã«ããããŒã¯ã³ã®ã·ãŒã±ã³ã¹ãå³åŽã«ããããŒã¯ã³ã®ã·ãŒã±ã³ã¹ã«å€æããããã«å¿ èŠã§ããããã¯ãã³ãŒããçæãããšãã«åŠçããã®ã«äŸ¿å©ã§ãããã®æŒç®åãšãšãã«ã^æŒç®åã䜿çšãããŸãã
- ^㯠ããã®æŒç®åãšãã®åå«ã§ããŒã¯ãããããŒã¯ã³ãããçæãããæ§æããªãŒã«æ°ããããŒããäœæããããã«äœ¿çšãããŸãã ãã®æŒç®åã«ã¯2ã€ã®åœ¢åŒããããŸãã
- åŸçœ®ã ããšãã°ããã®ãããªã«ãŒã«ã®å ŽåïŒ
relation: addition ((LE^ | LT^ | GE^ | GT^ | EQUAL^) addition)*;
- ãã¬ãã£ãã¯ã¹ã ããšãã°ããã®ãããªã«ãŒã«ã®å ŽåïŒ
CLASS typeName (INHERITS typeName)? LCURLY featureList RCURLY -> ^(Class typeName featureList typeName?)
- åŸçœ®ã ããšãã°ããã®ãããªã«ãŒã«ã®å ŽåïŒ
䜿çšãããŠããä»ã®ãã¹ãŠã®ANTLRæŒç®åã¯ã³ã¡ã³ããå¿ èŠãšããŸããïŒé¢æ£æ°åŠãåŠãã 人åãïŒã
- * -å埩ã
- + -æ£ã®å埩ã
- ïŒ -å·Šå©ãã®ããŒã¯ã³ãŸãã¯ããŒã¯ã³ã®ã°ã«ãŒãã¯ãååšããå Žåãšååšããªãå ŽåããããŸãã
STRING: '"' { StringBuilder b = new StringBuilder(); } ( '"' '"' { b.Append('"');} | c=~('"'|'\r'|'\n') { b.Append((char)c);} )* '"' { Text = b.ToString(); } ;
ããã§ã¯ãStringBuilderã䜿çšããŠæåååŠçãå¹çåããŸããååãšããŠããã®ãããªã³ãŒãã®ä»ã®ç¹åšã¯ãã¬ã¯ãµãŒã®æé©åã«ã¯åãå ¥ããããŸããããã¹ãŠã®ã«ãŒã«ã«ã¯åãå ¥ããããŸãããCïŒã¬ã¯ãµãŒããã³ããŒãµãŒã³ãŒãã§åå空éãæå®ããã«ã¯ïŒããšãã°ãSystem.Text for StringBuilderïŒã次ã®æ§æèŠçŽ ã䜿çšãããŸãïŒããã§ã¯ããäžèŠãªãèŠåãç¡å¹ã«ãªã£ãŠããŸãïŒã
@lexer::header {#pragma warning disable 3021 using System; using System.Text; } @parser::header {#pragma warning disable 3021 using System.Text;}
ANTLRWorksã§ææ³ãã³ã³ãã€ã«ããåŸãCïŒã¬ã¯ãµãŒãšããŒãµãŒã®ã³ãŒããçæããå¿ èŠããããŸãïŒããããšããcapïŒã
æå®ãããèšå®ã®ANTLRWorksã¯3ã€ã®ãã¡ã€ã«ãçæããŸãã
- CoolGrammar.tokens
- CoolGrammarLexer.cs
- CoolGrammarParser.cs
CïŒã³ãŒãã§çæãããã¬ã¯ãµãŒã䜿çšãã
çæãããCïŒã³ãŒãå ã®ãã¹ãŠã®ããŒã¯ã³ã®ãªã¹ããååŸããããšã¯ãããã»ã©ç°¡åã§ã¯ãããŸããïŒããã¯å¿ ãããå¿ èŠã§ã¯ãããŸããïŒã
var stream = new ANTLRStringStream(Source); // Source - . lexer = new CoolGrammarLexer(stream, new RecognizerSharedState() { errorRecovery = true }); IToken token; token = lexer.NextToken(); while (token.Type != CoolGrammarLexer.EOF) { // . // : CoolTokens.Dictionary[token.Type] ( '(' LPAREN, // , ) // : token.Text ( '(' "(") // : token.Line // : token.Column token = lexer.NextToken(); // , , . } // 0, // ( ). lexer.Reset();
CoolTokens.Dictionaryã¯æ¬¡ã®ããã«çæããå¿ èŠããããŸãã
var Lines = File.ReadAllLines(fileName); Dictionary = new Dictionary<int, string>(Lines.Length); foreach (var line in Lines) { var parts = line.Split('='); if (!Dictionary.ContainsKey(int.Parse(parts[1]))) Dictionary.Add(int.Parse(parts[1]), parts[0]); }
fileName-CoolCompiler.tokensãã¡ã€ã«ãžã®ãã¹
CïŒã³ãŒãã§çæãããããŒãµãŒã䜿çšãã
var tokenStream = new CommonTokenStream(lexer); // lexer, . parser = new CoolGrammarParser(tokenStream); Tree = parser.program(); // , (.. program ).
æ§æããªãŒãèµ°æ»ããã«ã¯ãIListã€ã³ã¿ãŒãã§ã€ã¹ã®æ¬¡ã®ããããã£ãšã¡ãœããã䜿çšãããŸãã - treeNode.ChildCount-treeNodeããŒãã®åã®æ°
- treeNode.GetChildïŒiïŒ-treeNodeããŒãiããåãååŸãã
- treeNode.Type-ãã®ããŒãã®ããŒã¯ã³ã intåã§ãããã¬ã¯ãµãŒã¯ã©ã¹ã§å®£èšãããå®æ°ãšæ¯èŒããå¿ èŠããããŸãã äŸïŒtreeNode.Type == CoolGrammarLexer.EQUALïŒç¹å®ã®ããŒã¯ã³ãã=ãèšå·ã§ãããã©ããïŒããªãŒããã©ããŒã¹ãããšãã¯ãæååãæ¯èŒãããããæ°å€ãè¿œå ããæ¹ãéããããTextã§ã¯ãªãTypeããããã£ã䜿çšããå¿ èŠããããŸãããã¹ãŠã®å®æ°ãèªåçã«çæãããããããšã©ãŒã®å¯èœæ§ãæžå°ããŸãã
- treeNode.Line-ã³ãŒãå ã®ããŒã¯ã³è¡çªå·
- treeNode.CharPositionInLine-è¡ã®å é ããã®ã³ãŒãå ã®ããŒã¯ã³ã®äœçœ®
ãããã«
ãã®èšäºã§ã¯ãANTLRWorksã§ææ³ãèšè¿°ããCïŒã¬ã¯ãµãŒãšããŒãµãŒã®çæã«äœ¿çšããæ¹æ³ãããã³ã¬ã¯ãµãŒãšããŒãµãŒã®äœ¿çšæ¹æ³ã«ã€ããŠèª¬æããŸããã 次ã®èšäºã§ã¯ãèšèªã®ã»ãã³ãã£ã¯ã¹ã®åŠçïŒã€ãŸããåãã§ãã¯ãã»ãã³ãã£ãã¯ãšã©ãŒã®åŠçïŒãæ§æããªãŒã®åããŒãããã€ãã¹ããŠãCILåœä»€ã®èª¬æã察å¿ããæ§ææ§æã®CILã³ãŒããçæããæ¹æ³ãä»®æ³ãã·ã³ã¹ã¿ãã¯ã®åäœæ¹æ³ãçµã¿èŸŒã¿ã®äœ¿çšæ¹æ³ã«ã€ããŠèª¬æããŸãã³ãŒãçæã容æã«ãã.NETã©ã€ãã©ãªSystem.Reflection.Emitã ãã¡ãããéäžã§åºäŒã£ãèœãšãç©Žã«ã€ããŠèª¬æããŸãïŒç¹ã«ãSystem.Reflection.Emitã䜿çšããŠã¯ã©ã¹éå±€ãäœæããïŒã ãŸãã
æåŸã«ãç§ã¯habrasocietyã«1ã€ã®è³ªåãããããšæããŸããçãã¯èŠã€ãããŸããã§ããã
CïŒlexerã®å ŽåãNoViableAltExceptionãã¹ããŒããã³ãŒããåžžã«çæããŸããããã®ã¹ããŒãã€ã³ã¿ãŒã»ããããããšã¯ã§ããŸããã
catch (NoViableAltException nvae) { DebugRecognitionException(nvae); throw; }
ãã®è¡ã«åãªãã¹ããŒã§ã¯ãªããããšãã°äŸå€ãçºçããããã¬ã¯ãµãŒãåäœãç¶ããããã«ãã©ã®ããã«ææ³ãã¡ã€ã«ãæžãããšãã§ããŸããïŒ ãŸããCïŒã³ãŒããçæããããã³ã«ãã®è¡ãä¿®æ£ããå¿
èŠããããŸã泚ïŒANTLRã§@rulecatchã䜿çšããæäœã§ã¯äœãèµ·ãããŸããã§ããã
誰ãããã®åé¡ãç解ããã³ã¡ã³ãã«çããæžããŠããããå¬ããã§ãã
æšå¥šèªæž
- 確å®ANTLRãªãã¡ã¬ã³ã¹ãTerence Parrã2007幎ã
- ã³ã³ãã€ã©ãŒ ååãæè¡ããã³ããŒã«ã2008幎ãã¢ã«ãã¬ããW.ã¢ããã¢ãã«S.ã©ã ãã©ãã»ãã£ããžã§ããªãŒD.ãŠã«ãã³