Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393729
  • 博文数量: 53
  • 博客积分: 1910
  • 博客等级: 中尉
  • 技术积分: 1130
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-10 14:56
文章分类

全部博文(53)

文章存档

2013年(1)

2012年(17)

2011年(33)

2010年(2)

分类: Python/Ruby

2011-05-11 18:25:07

  学习Language Implementation Patterns 一书过程中,结合python 把promote 样例代码重新写了一下

语法代码如下:

Cymbol.g:

 

  1. grammar Cymbol;
  2. options {
  3. language=Python;
  4. output = AST; // build trees
  5. ASTLabelType = CymbolAST; // use custom tree nodes
  6. }
  7. tokens {
  8. METHOD_DECL; // function definition
  9. ARG_DECL; // parameter
  10. BLOCK;
  11. VAR_DECL;
  12. FIELD_DECL;
  13. CALL;
  14. ELIST; // expression list
  15. EXPR; // root of an expression
  16. UNARY_MINUS;
  17. UNARY_NOT;
  18. ASSIGN='=';
  19. INDEX;
  20. }
  21. compilationUnit
  22. @after {$tree.setUnknownTokenBoundaries();} // (liunote $tree =>CymbolAST tree) For every node in this subtree, make sure it's start/stop token's are set. (set => startIndex ,stopIndex )
  23. : ( // hard to distinguish alts from left edge so backtrack
  24. options {backtrack=true;}
  25. : structDeclaration | methodDeclaration | varDeclaration
  26. )+
  27. ;
  28. structDeclaration
  29. : 'struct' ID '{' structMember+ '}' ';' -> ^('struct' ID structMember+)
  30. ;
  31. structMember
  32. : type ID ';' -> ^(FIELD_DECL type ID)
  33. | type ID '[]' ';' -> ^(FIELD_DECL ^('[]' type) ID)
  34. | structDeclaration
  35. ;
  36. // START: method
  37. methodDeclaration
  38. : type ID '(' formalParameters? ')' block
  39. -> ^(METHOD_DECL type ID formalParameters? block)
  40. ;
  41. // END: method
  42. formalParameters
  43. : parameter (',' parameter)* -> parameter+
  44. ;
  45. parameter
  46. : type ID -> ^(ARG_DECL type ID)
  47. | type ID '[]' -> ^(ARG_DECL ^('[]' type) ID)
  48. ;
  49. type: primitiveType
  50. | 'struct' ID -> ID
  51. ;
  52. primitiveType
  53. : 'float'
  54. | 'int'
  55. | 'char'
  56. | 'boolean'
  57. | 'void'
  58. ;
  59. // START: block
  60. block
  61. : '{' statement* '}' -> ^(BLOCK statement*)
  62. ;
  63. // END: block
  64. // START: var
  65. varDeclaration
  66. : type ID ('=' expression)? ';' -> ^(VAR_DECL type ID expression?)
  67. | type ID '[]' ('=' expression)? ';' -> ^(VAR_DECL ^('[]' type) ID expression?)
  68. ;
  69. // END: var
  70. statement
  71. options {backtrack=true;} // hard to distinguish struct from var from left
  72. : block
  73. | structDeclaration
  74. | varDeclaration
  75. | 'if' '(' expression ')' s=statement ('else' e=statement)? // liunote see Definitive P193 improve
  76. -> ^('if' expression $s $e?)
  77. | 'return' expression? ';' -> ^('return' expression?)
  78. | lhs '=' expression ';' -> ^('=' lhs expression) // liunote handles 1. array item asignment link a[1]=5; 2.struct item asignment like a.i =1;
  79. | a=postfixExpression ';' // handles function calls like f(i);
  80. -> ^(EXPR postfixExpression)
  81. ;
  82. lhs : postfixExpression -> ^(EXPR postfixExpression)
  83. ;
  84. // liunote expressionList used by call f(i+1, c, a.i)
  85. expressionList
  86. : expr (',' expr)* -> ^(ELIST expr+)
  87. | -> ELIST
  88. ;
  89. expression
  90. : expr -> ^(EXPR expr)
  91. ;
  92. /* liunote a infer method for expr rule (according priority) !!! */
  93. expr: equalityExpression
  94. ;
  95. equalityExpression
  96. : relationalExpression (('!='^ | '=='^) relationalExpression)*
  97. ;
  98. relationalExpression
  99. : additiveExpression
  100. ( ( ( '<'^
  101. | '>'^
  102. | '<='^
  103. | '>='^
  104. )
  105. additiveExpression
  106. )*
  107. )
  108. ;
  109. additiveExpression
  110. : multiplicativeExpression (('+'^ | '-'^) multiplicativeExpression)*
  111. ;
  112. multiplicativeExpression
  113. : unaryExpression (('*'^ | '/'^) unaryExpression)*
  114. ;
  115. // unary (one meta)
  116. unaryExpression
  117. : op='-' unaryExpression -> ^(UNARY_MINUS[$op] unaryExpression) /* definitive P189 ,UNARY_NOT,UNARY_MINUS => token name */
  118. | op='!' unaryExpression -> ^(UNARY_NOT[$op] unaryExpression)
  119. | postfixExpression
  120. ;
  121. // START: call
  122. postfixExpression
  123. : primary
  124. (
  125. ( r='('^ expressionList ')'! {$r.setType(CALL);} // liunote (TokenRewriteStream)Token.setType
  126. | r='['^ expr ']'! {$r.setType(INDEX);}
  127. | r='.'^ ID
  128. )
  129. )*
  130. ;
  131. // END: call
  132. primary
  133. : ID
  134. | INT
  135. | FLOAT
  136. | CHAR
  137. | 'true'
  138. | 'false'
  139. | '(' expression ')' -> expression
  140. ;
  141. // LEXER RULES
  142. ID : LETTER (LETTER | '0'..'9')* //{ self.setText('myid'); print self.getText()}
  143. ;
  144. fragment
  145. LETTER
  146. : ('a'..'z' | 'A'..'Z')
  147. ;
  148. CHAR: '\'' . '\'' ;
  149. //STRING: '\"' STR_CHARS '\"' {realc = str(int($STR_CHARS.text,8)); self.setText(realc);} //{setText($STR_CHARS.text);} ;
  150. //fragment STR_CHARS : ~'"'* ;
  151. INT : '0'..'9'+ ;
  152. //fragment
  153. //NONZERODIGIT
  154. // : '1'..'9'
  155. // ;
  156. //fragment
  157. //DIGIT
  158. // : '0'..'9' {print $INT.text}
  159. // ;
  160. //INT
  161. // : NONZERODIGIT (DIGIT)* // base-10
  162. // ( '.' (DIGIT)*
  163. // ( (('e' | 'E') ('+' | '-')? (DIGIT)+) {$type=FLOAT;} /* liunote $setType ???,lexer class no,token has*/
  164. // | ('d' | 'D')! {$type=FLOAT;}
  165. // | {$type=FLOAT;}
  166. // )
  167. // | ('e' | 'E') ('+' | '-')? (DIGIT)+ {$type=FLOAT;} /*1.55e+22, 1.55e-22*/
  168. // | ('d' | 'D')! {$type=FLOAT;}
  169. // )?
  170. // ;
  171. FLOAT
  172. : INT '.' INT* {$type=FLOAT;}
  173. | '.' INT+
  174. ;
  175. //FLOAT
  176. // : '.' (DIGIT)+
  177. // ;
  178. // ( ('e' | 'E') ('+' | '-')? (DIGIT)+
  179. // | ('d' | 'D')! /*{self.setType(FIXED);}*/
  180. // )?
  181. // ;
  182. WS : (' '|'\r'|'\t'|'\n') {$channel=HIDDEN;}
  183. ;
  184. SL_COMMENT
  185. : '//' ~('\r'|'\n')* '\r'? '\n' {$channel=HIDDEN;}
  186. ;

 

Def.g:

 

  1. // START: header
  2. tree grammar Def;
  3. options {
  4. language=Python;
  5. tokenVocab = Cymbol;
  6. ASTLabelType = CymbolAST;
  7. //filter = true;
  8. superClass=MyTreeFilter;
  9. }
  10. // liunote ???
  11. @header{
  12. from MyTreeFilter import MyTreeFilter
  13. from SymbolTable import SymbolTable;
  14. from ArrayType import ArrayType;
  15. from StructSymbol import StructSymbol;
  16. from MethodSymbol import MethodSymbol;
  17. from LocalScope import LocalScope;
  18. from VariableSymbol import VariableSymbol;
  19. from CymbolAST import CymbolAST;
  20. }
  21. /*
  22. @members{
  23. SymbolTable symtab;
  24. Scope currentScope;
  25. MethodSymbol currentMethod;
  26. public Def(TreeNodeStream input, SymbolTable symtab) {
  27. this(input);
  28. this.symtab = symtab;
  29. currentScope = symtab.globals;
  30. }
  31. }
  32. */
  33. @init {
  34. #//self.symtab = SymbolTable();
  35. #//self.currentScope = Scope();
  36. self.currentMethod = None #//MethodSymbol();
  37. }
  38. @members {
  39. def def_init2(self, symtab): # //liunote Def is Def tree class 's construct func
  40. #//self.__init__(input); # this(input) # do by Def class's init
  41. self.symtab = symtab
  42. self.currentScope = symtab.globals
  43. }
  44. // END: header
  45. //downup : topdown ( bottomup );
  46. topdown
  47. : enterBlock
  48. | enterMethod
  49. | enterStruct
  50. | atoms
  51. | varDeclaration
  52. | ret
  53. ;
  54. bottomup
  55. : exitBlock
  56. | exitMethod
  57. | exitStruct
  58. ;
  59. // S C O P E S
  60. enterBlock
  61. : BLOCK {self.currentScope = LocalScope(self.currentScope);} //{currentScope = new LocalScope(currentScope);} // push scope
  62. ;
  63. exitBlock
  64. : BLOCK
  65. {
  66. #//System.out.println("locals: "+currentScope);
  67. #//currentScope = currentScope.getEnclosingScope(); # pop scope
  68. self.currentScope = self.currentScope.getEnclosingScope(); #// pop scope
  69. }
  70. ;
  71. // START: struct
  72. enterStruct
  73. : ^('struct' ID .+)
  74. {
  75. #//System.out.println("line "+str($ID.getLine())+": def struct "+$ID.text);
  76. #//StructSymbol ss = new StructSymbol($ID.text, currentScope);
  77. ss = StructSymbol($ID.text, self.currentScope);
  78. #//ss = StructSymbol();
  79. #//ss.StructSymbol_init($ID.text, self.currentScope);
  80. ss.cymbolast_def = $ID;
  81. $ID.symbol = ss;
  82. #//currentScope.define(ss); # def struct in current scope
  83. self.currentScope.define(ss); # //def struct in current scope
  84. self.currentScope = ss; # //set current scope to struct scope
  85. }
  86. ;
  87. // liunote why 'struct' match exitStruct ,because , if find struct string when downup walk up struct !!! ,downup walk is down to down to down only leaf up ,says depth-first
  88. exitStruct
  89. : 'struct'
  90. {
  91. #//System.out.println("fields: "+currentScope);
  92. self.currentScope = self.currentScope.getEnclosingScope(); #// pop scope
  93. }
  94. ;
  95. // END: struct
  96. enterMethod
  97. : ^(METHOD_DECL type ID .*) // match method subtree with 0-or-more args
  98. {
  99. #//System.out.println("line "+$ID.getLine()+": def method "+$ID.text);
  100. #//MethodSymbol ms = new MethodSymbol($ID.text,$type.type,currentScope);
  101. ms = MethodSymbol($ID.text,$type.type,self.currentScope); # //liunote ID.getText => CommTree.getText => self.token.text
  102. self.currentMethod = ms;
  103. ms.cymbolast_def = $ID; # //track AST location of def's ID
  104. $ID.symbol = ms; # track in AST
  105. self.currentScope.define(ms); # def method in globals
  106. self.currentScope = ms; # set current scope to method scope
  107. }
  108. ;
  109. /** Track method associated with this return. */
  110. ret : ^('return' .) {$ret.start.symbol = self.currentMethod;} //$ret.start => ret tree node start child node ???
  111. ;
  112. exitMethod
  113. : METHOD_DECL
  114. {
  115. self.currentScope = self.currentScope.getEnclosingScope(); #// pop arg scope
  116. }
  117. ;
  118. // D e f i n e s y m b o l s
  119. // START: atoms
  120. /** Set scope for any identifiers in expressions or assignments */
  121. atoms
  122. @init {t = self.input.LT(1);} // liunote err =>{t = CymbolAST(self.input.LT(1)); print type(self.input.LT(1));} //{CymbolAST t = (CymbolAST)input.LT(1);} // liunote ??? CommonTreeNodeStream LT ->Get tree node at current input pointer + i ahead where i=1 is next node.
  123. : {t.hasAncestor(EXPR) or t.hasAncestor(ASSIGN)}? ID // liunote hasAncestor: Walk upwards looking for ancestor with this token type
  124. {t.scope = self.currentScope;}
  125. ;
  126. //END: atoms
  127. // START: var
  128. varDeclaration // global, parameter, or local variable
  129. : ^((FIELD_DECL|VAR_DECL|ARG_DECL) type ID .?)
  130. {
  131. #//System.out.println("line "+$ID.getLine()+": def "+$ID.text);
  132. #// liutst def out
  133. print ("line "+ str($ID.getLine())+": def "+$ID.text);
  134. #//VariableSymbol vs = new VariableSymbol($ID.text,$type.type);
  135. vs = VariableSymbol($ID.text,$type.type);
  136. #//track AST location of def's ID
  137. vs.cymbolast_def = $ID;
  138. $ID.symbol = vs; # //track in AST
  139. self.currentScope.define(vs);
  140. }
  141. ;
  142. // END: field
  143. // Actions at the start of alternative are in node discovery position.
  144. // Actions at the end of an alternative are in node finishing position.
  145. // Actions embedded within the alternative happen in between node discovery and finishing
  146. /** Not included in tree pattern matching directly. Needed by declarations */
  147. type returns [type] //[Type type] liunote type rule name same as return name ???
  148. : ^('[]' typeElement) {$type = ArrayType($typeElement.type);} //{$type = new ArrayType($typeElement.type);}
  149. | typeElement {$type = $typeElement.type;}
  150. ;
  151. typeElement returns [type] //[Type type]
  152. @init {t = self.input.LT(1); } // {t = CymbolAST(self.input.LT(1)); print type(self.input.LT(1));} //{CymbolAST t = (CymbolAST)input.LT(1);} //liunote ???
  153. @after {
  154. t.symbol = self.currentScope.resolve(t.getText()); # // return Type
  155. t.scope = self.currentScope;
  156. #//$type = (Type)t.symbol;
  157. $type = (t.symbol) #Type_init(t.symbol);
  158. }
  159. : 'float'
  160. | 'int'
  161. | 'char'
  162. | 'boolean'
  163. | 'void'
  164. | ID // struct name
  165. ;

Types.g:

 

  1. // START: header
  2. tree grammar Types;
  3. options {
  4. language=Python;
  5. tokenVocab = Cymbol;
  6. ASTLabelType = CymbolAST;
  7. //filter = true;
  8. superClass=MyTreeFilter;
  9. }
  10. // liunote ???
  11. @header{
  12. from MyTreeFilter import MyTreeFilter
  13. from SymbolTable import SymbolTable
  14. from ArrayType import ArrayType
  15. from StructSymbol import StructSymbol
  16. from MethodSymbol import MethodSymbol
  17. from LocalScope import LocalScope
  18. from VariableSymbol import VariableSymbol
  19. }
  20. /*
  21. @members {
  22. SymbolTable symtab;
  23. public Types(TreeNodeStream input, SymbolTable symtab) {
  24. this(input);
  25. this.symtab = symtab;
  26. }
  27. }
  28. */
  29. @members {
  30. def Types_init2(self,symtab):
  31. self.symtab = symtab;
  32. }
  33. // END: header
  34. bottomup // match subexpressions innermost to outermost
  35. : exprRoot
  36. | decl
  37. | ret
  38. | assignment
  39. ;
  40. // START: datatransfer
  41. decl: ^(VAR_DECL . ID (init=.)?) // call declinit if we have init expr
  42. /*{if ( $init!=null && $init.evalType!=null )
  43. symtab.declinit($ID, $init);}
  44. *//* liunote $init=>CymbolAST */
  45. {if $init != None and $init.evalType != None:
  46. self.symtab.declinit($ID, $init);
  47. }
  48. ;
  49. ret : ^('return' v=.) {self.symtab.ret($start.symbol, $v);} //{symtab.ret((MethodSymbol)$start.symbol, $v);} liunote $ret.start ???
  50. ;
  51. assignment // don't walk exprs, just examine types; '.' is wildcard
  52. : ^('=' lhs=. rhs=.) {self.symtab.assign($lhs, $rhs);}
  53. ;
  54. // END: datatransfer
  55. exprRoot // invoke type computation rule after matching EXPR
  56. : ^(EXPR expr) {$EXPR.evalType = $expr.type;} // annotate AST
  57. ;
  58. expr returns [type] //[Type type]
  59. @after { $start.evalType = $type; }
  60. : 'true' {$type = SymbolTable._boolean;} // liunote : _boolean is class SymbolTable static var
  61. | 'false' {$type = SymbolTable._boolean;}
  62. | CHAR {$type = SymbolTable._char;}
  63. | INT {$type = SymbolTable._int;}
  64. | FLOAT {$type = SymbolTable._float;}
  65. | ID /*{VariableSymbol s=(VariableSymbol)$ID.scope.resolve($ID.text);
  66. $ID.symbol = s; $type = s.type;}*/ /* liunote CymbolAST =>$ID */ /* no use cast ,because python return no type*/
  67. {
  68. s=$ID.scope.resolve($ID.text);
  69. $ID.symbol = s;
  70. $type = s.type;
  71. } // liunote $type is expr returns [type]
  72. | ^(UNARY_MINUS a=expr) {$type=self.symtab.uminus($a.start);}
  73. | ^(UNARY_NOT a=expr) {$type=self.symtab.unot($a.start);}
  74. | member {$type = $member.type;}
  75. | arrayRef {$type = $arrayRef.type;}
  76. | call {$type = $call.type;}
  77. | binaryOps {$type = $binaryOps.type;}
  78. ;
  79. binaryOps returns [type] //[Type type]
  80. @after { $start.evalType = $type; } /* => ((CymbolAST)retval.start).evalType = retval.type; */
  81. : ( ^(bop a=expr b=expr) {$type=self.symtab.bop($a.start, $b.start);}
  82. | ^(relop a=expr b=expr) {$type=self.symtab.relop($a.start, $b.start);}
  83. | ^(eqop a=expr b=expr) {$type=self.symtab.eqop($a.start, $b.start);}
  84. )
  85. ;
  86. arrayRef returns [type] //[Type type]
  87. : ^(INDEX ID expr)
  88. {
  89. $type = self.symtab.arrayIndex($ID, $expr.start);
  90. $start.evalType = $type;
  91. }
  92. ;
  93. call returns [type] //[Type type]
  94. @init {args = [];}//{List args = new ArrayList();}
  95. : ^(CALL ID ^(ELIST (expr {args.append($expr.start);})*))
  96. {
  97. $type = self.symtab.call($ID, args);
  98. $start.evalType = $type;
  99. }
  100. ;
  101. member returns [type] //[Type type]
  102. : ^('.' expr ID)
  103. {
  104. $type = self.symtab.member($expr.start, $ID);
  105. $start.evalType = $type;
  106. }
  107. ;
  108. bop : '+' | '-' | '*' | '/' ;
  109. relop: '<' | '>' | '<=' | '>=' ;
  110. eqop: '!=' | '==' ;

 

 

阅读(1009) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~