1 /* spec-compiler.jj Grammer definition for the specification */
6 Each construct should be embraced by /DOUBLE_STAR ... STAR/ annotation.
7 Within there, any line beginning with a "#" is a comment of the annotation.
8 Each constrcut should begin with @Begin and end with @End. Otherwise, the
9 annotation would be considered as normal comments of the source.
14 # If LANG is not define, it's C++ by default. C does not support class
15 # and template, so if it's defined as C, we should also have a explicit
29 b) Interface construct
33 IDENTIFIER | IDENTIFIER ...
34 @Condition: ... (Optional)
36 IDENTIFIER :: <C_CPP_Condition>
38 @ID: ... (Optional, use default ID)
42 # Type here must be a pointer
43 @DefineVar: Type var1 = SomeExpression (Optional)
46 @Post_action: (Optional)
47 @Post_check: (Optional)
50 c) Potential commit construct
52 @Potential_commit_point_define: ...
56 d) Commit point define construct
58 @Commit_point_define_check: ...
65 @Commit_point_define: ...
66 @Potential_commit_point_label: ...
70 e) Entry point construct
75 f) Interface define construct
77 @Interface_define: <Interface_Name>
85 JAVA_UNICODE_ESCAPE = true;
88 PARSER_BEGIN(SpecParser)
89 package edu.uci.eecs.specCompiler.grammerParser;
91 import java.io.FileInputStream;
92 import java.io.FileNotFoundException;
93 import java.io.InputStream;
94 import java.io.ByteArrayInputStream;
96 import java.util.ArrayList;
97 import java.util.HashMap;
98 import java.util.HashSet;
100 import edu.uci.eecs.specCompiler.specExtraction.Construct;
101 import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
102 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
103 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
104 import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
105 import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
106 import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
107 import edu.uci.eecs.specCompiler.specExtraction.ActionSubConstruct;
108 import edu.uci.eecs.specCompiler.specExtraction.ActionSubConstruct.DefineVar;
109 import edu.uci.eecs.specCompiler.specExtraction.SequentialDefineSubConstruct;
110 import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
111 import edu.uci.eecs.specCompiler.specExtraction.EntryPointConstruct;
112 import edu.uci.eecs.specCompiler.specExtraction.ClassBeginConstruct;
113 import edu.uci.eecs.specCompiler.specExtraction.ClassEndConstruct;
114 import edu.uci.eecs.specCompiler.specExtraction.FunctionHeader;
116 public class SpecParser {
117 private static ArrayList<String> _content;
118 private static File _file;
119 private static ArrayList<Construct> _constructs;
122 public static void main(String[] argvs)
123 throws ParseException, TokenMgrError {
125 String line = "int* A::B<sfd, _sdf>::id(const char * ch_ptr, int a)";
126 System.out.println(parseFuncHeader(line));
128 File f = new File("./grammer/spec.txt");
129 FileInputStream fis = new FileInputStream(f);
130 SpecParser parser = new SpecParser(fis);
132 ArrayList<String> content = new ArrayList<String>();
133 ArrayList<Construct> constructs = new ArrayList<Construct>();
134 parser.Parse(f, content, constructs);
135 for (int i = 0; i < content.size(); i++) {
136 System.out.println(content.get(i));
140 System.out.println("Parsing finished!");
141 } catch (FileNotFoundException e) {
146 public static void ParseFile(File f, ArrayList<String> content, ArrayList<Construct> constructs)
147 throws ParseException, TokenMgrError {
149 InputStream input = new FileInputStream(f);
150 SpecParser parser = new SpecParser(input);
151 parser.Parse(f, content, constructs);
152 } catch (FileNotFoundException e) {
157 public static ArrayList<String> getTemplateArg(String line)
158 throws ParseException {
159 InputStream input = new ByteArrayInputStream(line.getBytes());
160 SpecParser parser = new SpecParser(input);
161 return parser.TemplateParamList();
164 public static FunctionHeader parseFuncHeader(String line)
165 throws ParseException {
166 InputStream input = new ByteArrayInputStream(line.getBytes());
167 SpecParser parser = new SpecParser(input);
168 return parser.FuncDecl();
172 public static String stringArray2String(ArrayList<String> content) {
173 StringBuilder sb = new StringBuilder();
174 for (int i = 0; i < content.size(); i++) {
175 sb.append(content.get(i) + "\n");
177 return sb.toString();
181 PARSER_END(SpecParser)
199 "/**" : IN_POTENTIAL_SPEC
202 <IN_POTENTIAL_SPEC> TOKEN : {
203 <BEGIN: "@Begin"> : IN_SPEC
215 // "//" comment for the specification
216 <"//" (~["\n", "\r"])* (["\n", "\r"])>
219 <IN_COMMENT, IN_POTENTIAL_SPEC> SKIP : {
223 <IN_COMMENT, IN_POTENTIAL_SPEC> SKIP : { < ~[] > }
227 // "#" comment for the specification
228 <"#" (~["\n", "\r"])* (["\n", "\r"])>
235 <OPTIONS: "@Options:">
237 <GLOBAL_DEFINE: "@Global_define:">
239 <DECLARE_VAR: "@DeclareVar:">
241 <INIT_VAR: "@InitVar:">
243 <DEFINE_FUNC: "@DefineFunc:">
245 <INTERFACE_CLUSTER: "@Interface_cluster:">
247 <HAPPENS_BEFORE: "@Happens_before:">
249 <INTERFACE: "@Interface:">
251 <COMMIT_POINT_SET: "@Commit_point_set:">
253 <ENTRY_POINT: "@Entry_point">
255 <CLASS_BEGIN: "@Class_begin">
257 <CLASS_END: "@Class_end">
259 <INTERFACE_DEFINE: "@Interface_define:">
261 <CONDITION: "@Condition:">
263 <HB_CONDITION: "@HB_condition:">
271 <DEFINEVAR: "@DefineVar:">
275 <POST_ACTION: "@Post_action:">
277 <POST_CHECK: "@Post_check:">
279 <POTENTIAL_COMMIT_POINT_DEFINE: "@Potential_commit_point_define:">
283 <COMMIT_POINT_DEFINE_CHECK: "@Commit_point_define_check:">
285 <COMMIT_POINT_DEFINE: "@Commit_point_define:">
287 <POTENTIAL_COMMIT_POINT_LABEL: "@Potential_commit_point_label:">
291 <IN_SPEC, DEFAULT> TOKEN :
293 /* Specification & C/C++ shared tokens */
301 <TEMPLATE: "template">
305 <#LETTER: ["a"-"z", "A"-"Z"]>
307 <IDENTIFIER: (<LETTER> | "_") (<LETTER> | <DIGIT> | "_")*>
330 /* C/C++ only token*/
361 <GREATER_EQUALS: ">=">
365 <LOGICAL_EQUALS: "==">
385 ((~["\"","\\","\n","\r"])
387 ( ["n","t","b","r","f","\\","'","\""]
388 | ["0"-"7"] ( ["0"-"7"] )?
389 | ["0"-"3"] ["0"-"7"]
398 ((~["'","\\","\n","\r"])
400 (["n","t","b","r","f","\\","'","\""]
401 | ["0"-"7"] ( ["0"-"7"] )?
402 | ["0"-"3"] ["0"-"7"]
410 <DECIMAL_LITERAL> (["l","L"])?
411 | <HEX_LITERAL> (["l","L"])?
412 | <OCTAL_LITERAL> (["l","L"])?>
414 < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
416 < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
418 < #OCTAL_LITERAL: "0" (["0"-"7"])* >
420 < FLOATING_POINT_LITERAL:
421 <DECIMAL_FLOATING_POINT_LITERAL>
422 | <HEXADECIMAL_FLOATING_POINT_LITERAL> >
424 < #DECIMAL_FLOATING_POINT_LITERAL:
425 (["0"-"9"])+ "." (["0"-"9"])* (<DECIMAL_EXPONENT>)? (["f","F","d","D"])?
426 | "." (["0"-"9"])+ (<DECIMAL_EXPONENT>)? (["f","F","d","D"])?
427 | (["0"-"9"])+ <DECIMAL_EXPONENT> (["f","F","d","D"])?
428 | (["0"-"9"])+ (<DECIMAL_EXPONENT>)? ["f","F","d","D"]>
430 < #DECIMAL_EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
432 < #HEXADECIMAL_FLOATING_POINT_LITERAL:
433 "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])+ (".")? <HEXADECIMAL_EXPONENT> (["f","F","d","D"])?
434 | "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])* "." (["0"-"9","a"-"f","A"-"F"])+ <HEXADECIMAL_EXPONENT> (["f","F","d","D"])?>
436 < #HEXADECIMAL_EXPONENT: ["p","P"] (["+","-"])? (["0"-"9"])+ >
438 < #SPACE: (" " | "\t")+>
440 < #TO_END_OF_LINE: (~["\n"])+>
443 <INCLUDE: "#" (<SPACE>)? "include" <SPACE> (<STRING_LITERAL> | "<" (<LETTER> | <DOT>)+ ">")>
445 <DEFINE: "#" (<SPACE>)? <TO_END_OF_LINE>>
458 (((str = <STRUCT>.image | str = <CLASS>.image) { type = type + " " + str; })?
460 str = QualifiedName() {
461 if (!type.equals(""))
462 type = type + " " + str;
467 str = ParameterizedName() {
468 if (!type.equals(""))
469 type = type + " " + str;
474 ((str = "const".image {
475 if (!type.equals(""))
476 type = type + " " + str;
480 (str = <STAR>.image {
481 if (!type.equals(""))
482 type = type + " " + str;
487 if (!type.equals(""))
488 type = type + " " + str;
505 String ParameterizedName() :
511 (str = <IDENTIFIER>.image {res = str;})
512 ("<" str = <IDENTIFIER>.image { res = res + "<" + str; }
513 ("," str = <IDENTIFIER>.image { res = res + ", " + str; })* ">"
521 FunctionHeader FuncDecl() :
523 String ret, qualifiedName, bareName;
524 ArrayList<String> args;
528 qualifiedName = QualifiedName()
529 bareName = <IDENTIFIER>.image
530 args = FormalParamList()
532 FunctionHeader res = new FunctionHeader(ret, qualifiedName, bareName, args);
533 //System.out.println(res);
538 String QualifiedName() :
540 String qualifiedName, str;
543 { qualifiedName = ""; }
544 (LOOKAHEAD(2) (str = ParameterizedName() { qualifiedName = qualifiedName +
545 str + "::"; } <DOUBLECOLON> ))*
547 return qualifiedName;
551 ArrayList<String> TemplateParamList() :
553 ArrayList<String> params;
558 params = new ArrayList<String>();
562 (str = <IDENTIFIER>.image
563 str = <IDENTIFIER>.image {params.add(str);})
565 ("," str = <IDENTIFIER>.image
566 str = <IDENTIFIER>.image {params.add(str);})*
569 //System.out.println(params);
574 ArrayList<String> FormalParamList() :
576 ArrayList<String> typeParams;
580 typeParams = new ArrayList<String>();
583 (TypeParam(typeParams) (<COMMA> TypeParam(typeParams))*)?
590 void TypeParam(ArrayList<String> typeParams) :
595 (type = Type()) (param = <IDENTIFIER>.image)
597 typeParams.add(type);
598 typeParams.add(param);
602 ArrayList<String> C_CPP_CODE() :
606 boolean newLine = false;
607 boolean inTemplate = false;
608 ArrayList<String> content;
614 content = new ArrayList<String>();
619 t = <CONST> | t = <STRUCT> | t = <CLASS> |
620 (t = <TEMPLATE> { inTemplate = true; })|
621 t = <IDENTIFIER> | t = <POUND> |
622 (t = <OPEN_BRACE> { newLine = true; } ) |
623 (t = <CLOSE_BRACE> { newLine = true; } ) |
624 t = <EQUALS> | t = <OPEN_PAREN> | t = <CLOSE_PAREN> |
625 t = <OPEN_BRACKET> | t = <CLOSE_BRACKET>
626 | t = <HB_SYMBOL> | t = <COMMA> |
627 t = <DOT> | t = <STAR> | t = <NEGATE> | t = <EXCLAMATION> | t = <AND> | t = <OR> | t = <MOD> | t = <PLUS> |
628 t = <PLUSPLUS> | t = <MINUS> | t = <MINUSMINUS> | t = <DIVIDE> | t = <BACKSLASH> |
630 (t = <GREATER_THAN> { if (inTemplate) newLine = true; }) |
631 t = <GREATER_EQUALS> | t = <LESS_EQUALS> |
632 t = <LOGICAL_EQUALS> | t = <NOT_EQUALS> | t = <LOGICAL_AND> | t = <LOGICAL_OR> | t = <XOR> |
633 t = <QUESTION_MARK> | t = <COLON> | t = <DOUBLECOLON> |
634 (t = <SEMI_COLON> { newLine = true; } )
635 | t = <STRING_LITERAL> | t = <CHARACTER_LITERAL> |
636 t = <INTEGER_LITERAL> | t = <FLOATING_POINT_LITERAL> |
637 (t = <INCLUDE> { newLine = true; } ) |
638 (t = <DEFINE> { newLine = true; } )
641 text = text + " " + t.image;
656 void Parse(File f, ArrayList<String> content, ArrayList<Construct> constructs) :
659 ArrayList<String> code;
665 _constructs = constructs;
667 ((inst = ParseSpec() { _constructs.add(inst); }) |
668 ((code = C_CPP_CODE()) { _content.addAll(code); })
672 Construct ParseSpec() :
678 LOOKAHEAD(2) res = Global_construct() |
679 LOOKAHEAD(2) res = Interface() |
680 LOOKAHEAD(2) res = Potential_commit_point_define() |
681 LOOKAHEAD(2) res = Commit_point_define() |
682 LOOKAHEAD(2) res = Commit_point_define_check() |
683 LOOKAHEAD(2) res = Entry_point() |
684 LOOKAHEAD(2) res = Class_begin() |
685 LOOKAHEAD(2) res = Class_end() |
686 LOOKAHEAD(2) res = Interface_define()
689 //System.out.println(res);
694 GlobalConstruct Global_construct() :
697 SequentialDefineSubConstruct code;
698 HashMap<String, String> options;
704 options = new HashMap<String, String>();
708 ((key = <IDENTIFIER>.image)
710 (value = <IDENTIFIER>.image)
712 if (options.containsKey(key)) {
713 throw new ParseException("Duplicate options!");
715 options.put(key, value);
720 (code = Global_define())
721 { res = new GlobalConstruct(_file, _content.size(), code, options); }
722 (Interface_clusters(res))?
723 (Happens_before(res))?
726 res.unfoldInterfaceCluster();
731 SequentialDefineSubConstruct Global_define() :
733 String declareVar, initVar, defineFunc;
734 ArrayList<String> code;
743 (<DECLARE_VAR> (code = C_CPP_CODE() { declareVar = stringArray2String(code); } ))?
744 (<INIT_VAR> (code = C_CPP_CODE() { initVar = stringArray2String(code); } ))?
745 (<DEFINE_FUNC> (code = C_CPP_CODE() { defineFunc = stringArray2String(code); }))?
747 SequentialDefineSubConstruct res = new SequentialDefineSubConstruct(declareVar, initVar, defineFunc);
748 //System.out.println(res);
753 ConditionalInterface Conditional_interface() :
755 String interfaceName, hbConditionLabel;
759 hbConditionLabel = "";
761 interfaceName = <IDENTIFIER>.image (<OPEN_BRACKET> hbConditionLabel =
762 <IDENTIFIER>.image <CLOSE_BRACKET>)?
764 return new ConditionalInterface(interfaceName, hbConditionLabel);
768 void Interface_cluster(GlobalConstruct inst) :
771 ConditionalInterface condInterface;
774 (clusterName= <IDENTIFIER>.image)
775 <EQUALS> <OPEN_PAREN>
776 (condInterface = Conditional_interface()
777 { inst.addInterface2Cluster(clusterName, condInterface); }
779 (<COMMA> condInterface = Conditional_interface()
780 { inst.addInterface2Cluster(clusterName, condInterface); }
785 void Interface_clusters(GlobalConstruct inst) :
788 <INTERFACE_CLUSTER> (Interface_cluster(inst))+
791 void Happens_before(GlobalConstruct inst) :
793 ConditionalInterface left, right;
798 left = Conditional_interface() <HB_SYMBOL> right = Conditional_interface()
799 { inst.addHBCondition(left, right); }
803 InterfaceConstruct Interface() :
805 InterfaceConstruct res;
806 String interfaceName, condition, idCode, check, postAction,
807 postCheck, commitPoint, hbLabel, hbCondition;
808 ActionSubConstruct action;
809 ArrayList<String> commitPointSet;
810 HashMap<String, String> hbConditions;
811 ArrayList<String> content;
822 commitPointSet = new ArrayList<String>();
823 hbConditions = new HashMap<String, String>();
826 <INTERFACE> (interfaceName = <IDENTIFIER>.image)
828 (commitPoint = <IDENTIFIER>.image
829 { commitPointSet.add(commitPoint); }
832 (commitPoint = <IDENTIFIER>.image)
834 if (commitPointSet.contains(commitPoint)) {
835 throw new ParseException(interfaceName + " has" +
836 "duplicate commit point labels");
838 commitPointSet.add(commitPoint);
842 (<CONDITION> (content = C_CPP_CODE() { condition = stringArray2String(content); }))?
845 (hbLabel = <IDENTIFIER>.image)
846 (content = C_CPP_CODE() { hbCondition = stringArray2String(content); })
848 if (hbConditions.containsKey(hbLabel)) {
849 throw new ParseException(interfaceName + " has" +
850 "duplicate happens-before condtion labels");
852 hbConditions.put(hbLabel, hbCondition);
855 (<ID> (content = C_CPP_CODE() { idCode = stringArray2String(content); }))?
856 (<CHECK> (content = C_CPP_CODE() { check = stringArray2String(content); }))?
858 (<POST_ACTION> (content = C_CPP_CODE() { postAction = stringArray2String(content); }))?
859 (<POST_CHECK> (content = C_CPP_CODE() { postCheck = stringArray2String(content); }))?
862 res = new InterfaceConstruct(_file, _content.size(), interfaceName, commitPointSet, condition,
863 hbConditions, idCode, check, action, postAction, postCheck);
868 ActionSubConstruct Action() :
870 String type, name, expr, defineVarStr, code;
871 ArrayList<DefineVar> defineVars;
872 ArrayList<String> content;
876 defineVars = new ArrayList<DefineVar>();
882 (<DEFINEVAR> (content = C_CPP_CODE() { defineVarStr = stringArray2String(content); })
884 int eqIdx = defineVarStr.indexOf('=');
885 int typeEnd = defineVarStr.lastIndexOf(' ', eqIdx - 2);
886 type = defineVarStr.substring(0, typeEnd);
887 name = defineVarStr.substring(typeEnd + 1, eqIdx - 1);
888 expr = defineVarStr.substring(eqIdx + 2);
889 DefineVar defineVar = new DefineVar(type, name, expr);
890 defineVars.add(defineVar);
891 })* (<CODE> (content = C_CPP_CODE() { code = stringArray2String(content); }))? )
895 ActionSubConstruct res = new ActionSubConstruct(defineVars, code);
900 PotentialCPDefineConstruct Potential_commit_point_define() :
902 PotentialCPDefineConstruct res;
903 String label, condition;
904 ArrayList<String> content;
910 <POTENTIAL_COMMIT_POINT_DEFINE> (content = C_CPP_CODE() { condition = stringArray2String(content); })
911 <LABEL> (label = <IDENTIFIER>.image)
914 res = new PotentialCPDefineConstruct(_file, _content.size(), label, condition);
920 CPDefineConstruct Commit_point_define() :
922 CPDefineConstruct res;
923 String label, potentialCPLabel, condition;
924 ArrayList<String> content;
930 <COMMIT_POINT_DEFINE> (content = C_CPP_CODE() { condition = stringArray2String(content); })
931 <POTENTIAL_COMMIT_POINT_LABEL> (potentialCPLabel = <IDENTIFIER>.image)
932 <LABEL> (label = <IDENTIFIER>.image)
935 res = new CPDefineConstruct(_file, _content.size(), label, potentialCPLabel, condition);
941 CPDefineCheckConstruct Commit_point_define_check() :
943 CPDefineCheckConstruct res;
944 String label, condition;
945 ArrayList<String> content;
951 <COMMIT_POINT_DEFINE_CHECK> (content = C_CPP_CODE() { condition = stringArray2String(content); })
952 <LABEL> (label = <IDENTIFIER>.image)
955 res = new CPDefineCheckConstruct(_file, _content.size(), label, condition);
960 EntryPointConstruct Entry_point() :
968 return new EntryPointConstruct(_file, _content.size());
972 ClassBeginConstruct Class_begin() :
980 return new ClassBeginConstruct(_file, _content.size());
984 ClassEndConstruct Class_end() :
992 return new ClassEndConstruct(_file, _content.size());
996 InterfaceDefineConstruct Interface_define() :
1002 <INTERFACE_DEFINE> (name = <IDENTIFIER>.image)
1005 return new InterfaceDefineConstruct(_file, _content.size(), name);