| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | // Copyright 2009 The Go Authors.  All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package Parser | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import Scanner "scanner" | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | import Globals "globals" | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | import Object "object" | 
					
						
							|  |  |  | import Type "type" | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | import Universe "universe" | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | import AST "ast" | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // So I can submit and have a running parser for now... | 
					
						
							|  |  |  | const EnableSemanticTests = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | export Parser | 
					
						
							|  |  |  | type Parser struct { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	comp *Globals.Compilation; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	verbose, indent int; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	S *Scanner.Scanner; | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// Token | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	tok int;  // one token look-ahead | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	pos int;  // token source position | 
					
						
							|  |  |  | 	val string;  // token value (for IDENT, NUMBER, STRING only) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Semantic analysis | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	top_scope *Globals.Scope; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	exports *Globals.List; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Support functions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) PrintIndent() { | 
					
						
							|  |  |  | 	for i := P.indent; i > 0; i-- { | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 		print ". "; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Trace(msg string) { | 
					
						
							|  |  |  | 	if P.verbose > 0 { | 
					
						
							|  |  |  | 		P.PrintIndent(); | 
					
						
							|  |  |  | 		print msg, " {\n"; | 
					
						
							|  |  |  | 		P.indent++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Ecart() { | 
					
						
							|  |  |  | 	if P.verbose > 0 { | 
					
						
							|  |  |  | 		P.indent--; | 
					
						
							|  |  |  | 		P.PrintIndent(); | 
					
						
							|  |  |  | 		print "}\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Next() { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	P.tok, P.pos, P.val = P.S.Scan(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.verbose > 1 { | 
					
						
							|  |  |  | 		P.PrintIndent(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		print "[", P.pos, "] ", Scanner.TokenName(P.tok), "\n"; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int) { | 
					
						
							|  |  |  | 	P.comp = comp; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.verbose = verbose; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.indent = 0; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.S = S; | 
					
						
							|  |  |  | 	P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.top_scope = Universe.scope; | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	P.exports = Globals.NewList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-10 14:42:33 -07:00
										 |  |  | func (P *Parser) Error(pos int, msg string) { | 
					
						
							|  |  |  | 	P.S.Error(pos, msg); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Expect(tok int) { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	if P.tok != tok { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'"); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	P.Next();  // make progress in any case | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) Optional(tok int) { | 
					
						
							|  |  |  | 	if P.tok == tok { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // Scopes | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) OpenScope() { | 
					
						
							|  |  |  | 	P.top_scope = Globals.NewScope(P.top_scope); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) CloseScope() { | 
					
						
							|  |  |  | 	P.top_scope = P.top_scope.parent; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Lookup(ident string) *Globals.Object { | 
					
						
							|  |  |  | 	for scope := P.top_scope; scope != nil; scope = scope.parent { | 
					
						
							|  |  |  | 		obj := scope.Lookup(ident); | 
					
						
							|  |  |  | 		if obj != nil { | 
					
						
							|  |  |  | 			return obj; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	if EnableSemanticTests && scope.Lookup(obj.ident) != nil { | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		// TODO is this the correct error position? | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Error(obj.pos, `"` + obj.ident + `" is declared already`); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		return;  // don't insert it into the scope | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	scope.Insert(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Declare(obj *Globals.Object) { | 
					
						
							|  |  |  | 	P.DeclareInScope(P.top_scope, obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ---------------------------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // Common productions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) TryType() *Globals.Type; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | func (P *Parser) ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) TryStatement() bool; | 
					
						
							|  |  |  | func (P *Parser) ParseDeclaration(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseIdent() string { | 
					
						
							|  |  |  | 	P.Trace("Ident"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ident := ""; | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		ident = P.val; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		if P.verbose > 0 { | 
					
						
							|  |  |  | 			P.PrintIndent(); | 
					
						
							|  |  |  | 			print "Ident = \"", ident, "\"\n"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.IDENT);  // use Expect() error handling | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return ident; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentDecl(kind int) *Globals.Object { | 
					
						
							|  |  |  | 	P.Trace("IdentDecl"); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	obj := Globals.NewObject(pos, kind, P.ParseIdent()); | 
					
						
							|  |  |  | 	P.Declare(obj); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentDeclList(kind int) *Globals.List { | 
					
						
							|  |  |  | 	P.Trace("IdentDeclList"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	list := Globals.NewList(); | 
					
						
							|  |  |  | 	list.AddObj(P.ParseIdentDecl(kind)); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		list.AddObj(P.ParseIdentDecl(kind)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return list; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdentList() { | 
					
						
							|  |  |  | 	P.Trace("IdentList"); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseQualifiedIdent() *Globals.Object { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("QualifiedIdent"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if EnableSemanticTests { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		ident := P.ParseIdent(); | 
					
						
							|  |  |  | 		obj := P.Lookup(ident); | 
					
						
							|  |  |  | 		if obj == nil { | 
					
						
							|  |  |  | 			P.Error(pos, `"` + ident + `" is not declared`); | 
					
						
							|  |  |  | 			obj = Globals.NewObject(pos, Object.BAD, ident); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 			panic "Qualified ident not complete yet"; | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseIdent(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return obj; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseIdent(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		if P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseIdent(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Types | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseType() *Globals.Type{ | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Trace("Type"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	typ := P.TryType(); | 
					
						
							|  |  |  | 	if typ == nil { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "type expected"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		typ = Universe.bad_t; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseTypeName() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("TypeName"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if EnableSemanticTests { | 
					
						
							|  |  |  | 		obj := P.ParseQualifiedIdent(); | 
					
						
							|  |  |  | 		typ := obj.typ; | 
					
						
							|  |  |  | 		if obj.kind != Object.TYPE { | 
					
						
							|  |  |  | 			P.Error(obj.pos, `"` + obj.ident + `" is not a type`); | 
					
						
							|  |  |  | 			typ = Universe.bad_t; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return typ; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseQualifiedIdent(); | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return Universe.bad_t; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseArrayType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("ArrayType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.ARRAY); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	if P.tok != Scanner.RBRACK { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		// TODO set typ.len_ | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ.elt = P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseChannelType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("ChannelType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Expect(Scanner.CHAN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.CHANNEL); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	case Scanner.SEND: | 
					
						
							|  |  |  | 		typ.flags = Type.SEND; | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.RECV: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		typ.flags = Type.RECV; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		typ.flags = Type.SEND + Type.RECV; | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ.elt = P.ParseType(); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseVarDeclList() { | 
					
						
							|  |  |  | 	P.Trace("VarDeclList"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	list := P.ParseIdentDeclList(Object.VAR); | 
					
						
							|  |  |  | 	typ := P.ParseType();  // TODO should check completeness of types | 
					
						
							|  |  |  | 	for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		p.obj.typ = typ;  // TODO should use/have set_type() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseParameterSection() { | 
					
						
							|  |  |  | 	P.Trace("ParameterSection"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	P.ParseVarDeclList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameterList() { | 
					
						
							|  |  |  | 	P.Trace("ParameterList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseParameterSection(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseParameterSection(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameters() { | 
					
						
							|  |  |  | 	P.Trace("Parameters"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 		P.ParseParameterList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) TryResult() bool { | 
					
						
							|  |  |  | 	P.Trace("Result (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	res := false; | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		// TODO: here we allow empty returns - should proably fix this | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 		res = true; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		res = P.TryType() != nil; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type { | 
					
						
							|  |  |  |   // Determine if we have a receiver or not. | 
					
						
							|  |  |  |   if p0 > 0 && check_recv { | 
					
						
							|  |  |  |     // method | 
					
						
							|  |  |  | 	if p0 != 1 { | 
					
						
							|  |  |  | 		panic "p0 != 1"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   typ := Globals.NewType(Type.FUNCTION); | 
					
						
							|  |  |  |   if p0 == 0 { | 
					
						
							|  |  |  | 	typ.flags = 0; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  | 	typ.flags = Type.RECV; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   typ.len_ = r0 - p0; | 
					
						
							|  |  |  |   typ.scope = sig; | 
					
						
							|  |  |  |   return typ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // Anonymous signatures | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //          (params) | 
					
						
							|  |  |  | //          (params) type | 
					
						
							|  |  |  | //          (params) (results) | 
					
						
							|  |  |  | // (recv) . (params) | 
					
						
							|  |  |  | // (recv) . (params) type | 
					
						
							|  |  |  | // (recv) . (params) (results) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseAnonymousSignature() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("AnonymousSignature"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	sig := P.top_scope; | 
					
						
							|  |  |  | 	p0 := 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	recv_pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		p0 = sig.entries.len_; | 
					
						
							|  |  |  | 		if (p0 != 1) { | 
					
						
							|  |  |  | 			P.Error(recv_pos, "must have exactly one receiver") | 
					
						
							|  |  |  | 			panic "UNIMPLEMENTED"; | 
					
						
							|  |  |  | 			// TODO do something useful here | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	r0 := sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.TryResult(); | 
					
						
							|  |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return MakeFunctionType(sig, p0, r0, true); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Named signatures | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //        name (params) | 
					
						
							|  |  |  | //        name (params) type | 
					
						
							|  |  |  | //        name (params) (results) | 
					
						
							|  |  |  | // (recv) name (params) | 
					
						
							|  |  |  | // (recv) name (params) type | 
					
						
							|  |  |  | // (recv) name (params) (results) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("NamedSignature"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	sig := P.top_scope; | 
					
						
							|  |  |  | 	p0 := 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		recv_pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 		p0 = sig.entries.len_; | 
					
						
							|  |  |  | 		if (p0 != 1) { | 
					
						
							|  |  |  | 			print "p0 = ", p0, "\n"; | 
					
						
							|  |  |  | 			P.Error(recv_pos, "must have exactly one receiver") | 
					
						
							|  |  |  | 			panic "UNIMPLEMENTED"; | 
					
						
							|  |  |  | 			// TODO do something useful here | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	name = P.ParseIdent(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseParameters(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	r0 := sig.entries.len_; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.TryResult(); | 
					
						
							|  |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return name, MakeFunctionType(sig, p0, r0, true); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseFunctionType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("FunctionType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.FUNC); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := P.ParseAnonymousSignature(); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseMethodDecl() { | 
					
						
							|  |  |  | 	P.Trace("MethodDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	P.ParseParameters(); | 
					
						
							|  |  |  | 	P.TryResult(); | 
					
						
							|  |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseInterfaceType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("InterfaceType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Expect(Scanner.INTERFACE); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.INTERFACE); | 
					
						
							|  |  |  | 	typ.scope = P.top_scope; | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	for P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseMethodDecl(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseMapType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("MapType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.MAP); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Globals.NewType(Type.MAP); | 
					
						
							|  |  |  | 	typ.key = P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ.elt = P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseFieldDecl() { | 
					
						
							|  |  |  | 	P.Trace("FieldDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	P.ParseVarDeclList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParseStructType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("StructType"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.STRUCT); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	typ := Globals.NewType(Type.STRUCT); | 
					
						
							|  |  |  | 	typ.scope = P.top_scope; | 
					
						
							|  |  |  | 	for P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseFieldDecl(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		if P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 			P.Expect(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | func (P *Parser) ParsePointerType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("PointerType"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.MUL); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	typ := Universe.undef_t; | 
					
						
							|  |  |  | 	if (EnableSemanticTests && P.tok == Scanner.IDENT && P.Lookup(P.val) == nil) { | 
					
						
							|  |  |  | 		// forward declaration | 
					
						
							|  |  |  | 		panic "UNIMPLEMENTED *forward_declared_type"; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		typ = Globals.NewType(Type.POINTER); | 
					
						
							|  |  |  | 		typ.elt = P.ParseType(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.Ecart();	 | 
					
						
							|  |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | // Returns nil if no type was found. | 
					
						
							|  |  |  | func (P *Parser) TryType() *Globals.Type { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Trace("Type (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	var typ *Globals.Type = nil; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	case Scanner.IDENT: typ = P.ParseTypeName(); | 
					
						
							|  |  |  | 	case Scanner.LBRACK: typ = P.ParseArrayType(); | 
					
						
							|  |  |  | 	case Scanner.CHAN: typ = P.ParseChannelType(); | 
					
						
							|  |  |  | 	case Scanner.INTERFACE: typ = P.ParseInterfaceType(); | 
					
						
							|  |  |  | 	case Scanner.FUNC: typ = P.ParseFunctionType(); | 
					
						
							|  |  |  | 	case Scanner.MAP: typ = P.ParseMapType(); | 
					
						
							|  |  |  | 	case Scanner.STRUCT: typ = P.ParseStructType(); | 
					
						
							|  |  |  | 	case Scanner.MUL: typ = P.ParsePointerType(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	return typ; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Blocks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseStatement() { | 
					
						
							|  |  |  | 	P.Trace("Statement"); | 
					
						
							|  |  |  | 	if !P.TryStatement() { | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "statement expected"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Next();  // make progress | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseStatementList() { | 
					
						
							|  |  |  | 	P.Trace("StatementList"); | 
					
						
							|  |  |  | 	for P.TryStatement() { | 
					
						
							|  |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseBlock() { | 
					
						
							|  |  |  | 	P.Trace("Block"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	P.OpenScope(); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 	P.CloseScope(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Expressions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseExpressionList() { | 
					
						
							|  |  |  | 	P.Trace("ExpressionList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseNew() { | 
					
						
							|  |  |  | 	P.Trace("New"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.NEW); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseExpressionList() | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseFunctionLit() { | 
					
						
							|  |  |  | 	P.Trace("FunctionLit"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseFunctionType(); | 
					
						
							|  |  |  | 	P.ParseBlock(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | func (P *Parser) ParseExpressionPair() { | 
					
						
							|  |  |  | 	P.Trace("ExpressionPair"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.COLON); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseExpressionPairList() { | 
					
						
							|  |  |  | 	P.Trace("ExpressionPairList"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.ParseExpressionPair(); | 
					
						
							|  |  |  | 	for (P.tok == Scanner.COMMA) { | 
					
						
							|  |  |  | 		P.ParseExpressionPair(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCompositeLit(typ *Globals.Type) { | 
					
						
							|  |  |  | 	P.Trace("CompositeLit"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// TODO I think we should use {} instead of () for | 
					
						
							|  |  |  | 	// composite literals to syntactically distinguish | 
					
						
							|  |  |  | 	// them from conversions. For now: allow both. | 
					
						
							|  |  |  | 	var paren int; | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		paren = Scanner.RPAREN; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 		paren = Scanner.RBRACE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// TODO: should allow trailing ',' | 
					
						
							|  |  |  | 	if P.tok != paren { | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			if P.tok != paren { | 
					
						
							|  |  |  | 				P.ParseExpressionList(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if P.tok == Scanner.COLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseExpression(); | 
					
						
							|  |  |  | 			if P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 				P.Next(); | 
					
						
							|  |  |  | 				if P.tok != paren { | 
					
						
							|  |  |  | 					P.ParseExpressionPairList(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.Expect(paren); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseOperand() { | 
					
						
							|  |  |  | 	P.Trace("Operand"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT: | 
					
						
							|  |  |  | 		P.ParseQualifiedIdent(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		// TODO enable code below | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		if obj.kind == Object.TYPE { | 
					
						
							|  |  |  | 			P.ParseCompositeLit(obj.typ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*/ | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.LPAREN: | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 		P.Expect(Scanner.RPAREN); | 
					
						
							|  |  |  | 	case Scanner.STRING: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NUMBER: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NIL: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.IOTA: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.TRUE: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.FALSE: | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		P.ParseFunctionLit(); | 
					
						
							|  |  |  | 	case Scanner.NEW: | 
					
						
							|  |  |  | 		P.ParseNew(); | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		typ := P.TryType(); | 
					
						
							|  |  |  | 		if typ != nil { | 
					
						
							|  |  |  | 			P.ParseCompositeLit(typ); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			P.Error(P.pos, "operand expected"); | 
					
						
							|  |  |  | 			P.Next();  // make progress | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseSelectorOrTypeAssertion() { | 
					
						
							|  |  |  | 	P.Trace("SelectorOrTypeAssertion"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.PERIOD); | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Expect(Scanner.LPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseIndexOrSlice() { | 
					
						
							|  |  |  | 	P.Trace("IndexOrSlice"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.COLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseInvocation() { | 
					
						
							|  |  |  | 	P.Trace("Invocation"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParsePrimaryExpr() { | 
					
						
							|  |  |  | 	P.Trace("PrimaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseOperand(); | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.PERIOD: | 
					
						
							|  |  |  | 			P.ParseSelectorOrTypeAssertion(); | 
					
						
							|  |  |  | 		case Scanner.LBRACK: | 
					
						
							|  |  |  | 			P.ParseIndexOrSlice(); | 
					
						
							|  |  |  | 		case Scanner.LPAREN: | 
					
						
							|  |  |  | 			P.ParseInvocation(); | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			P.Ecart(); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParsePrimaryExprList() { | 
					
						
							|  |  |  | 	P.Trace("PrimaryExprList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParsePrimaryExpr(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParsePrimaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseUnaryExpr() AST.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("UnaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.ADD: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SUB: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NOT: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.XOR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.MUL: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.RECV: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	case Scanner.AND: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseUnaryExpr(); | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		return nil;  // TODO fix this | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParsePrimaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	return nil;  // TODO fix this | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func Precedence(tok int) int { | 
					
						
							|  |  |  | 	// TODO should use a map or array here for lookup | 
					
						
							|  |  |  | 	switch tok { | 
					
						
							|  |  |  | 	case Scanner.LOR: | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	case Scanner.LAND: | 
					
						
							|  |  |  | 		return 2; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.SEND, Scanner.RECV: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 3; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 4; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR: | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		return 5; | 
					
						
							| 
									
										
										
										
											2008-07-16 17:00:48 -07:00
										 |  |  | 	case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND: | 
					
						
							|  |  |  | 		return 6; | 
					
						
							| 
									
										
										
										
											2008-07-09 10:45:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Trace("BinaryExpr"); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	x := P.ParseUnaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	for prec := Precedence(P.tok); prec >= prec1; prec-- { | 
					
						
							|  |  |  | 		for Precedence(P.tok) == prec { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 			e := new(AST.BinaryExpr); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 			e.typ = Universe.undef_t;  // TODO fix this | 
					
						
							|  |  |  | 			e.op = P.tok;  // TODO should we use tokens or separate operator constants? | 
					
						
							|  |  |  | 			e.x = x; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 			e.y = P.ParseBinaryExpr(prec + 1); | 
					
						
							|  |  |  | 			x = e; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseExpression() { | 
					
						
							|  |  |  | 	P.Trace("Expression"); | 
					
						
							|  |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.ParseBinaryExpr(1); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		panic "imbalanced tracing code (Expression)"; | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Statements | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParseBuiltinStat() { | 
					
						
							|  |  |  | 	P.Trace("BuiltinStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.IDENT); | 
					
						
							|  |  |  | 	P.ParseExpressionList();  // TODO should be optional | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSimpleStat() { | 
					
						
							|  |  |  | 	P.Trace("SimpleStat"); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	if P.tok == Scanner.COLON { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParsePrimaryExprList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.DEFINE: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.ADD_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SUB_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.MUL_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.QUO_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.REM_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.AND_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.OR_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.XOR_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SHL_ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SHR_ASSIGN: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.INC: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	case Scanner.DEC: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) ParseGoStat() { | 
					
						
							|  |  |  | 	P.Trace("GoStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.GO); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParseReturnStat() { | 
					
						
							|  |  |  | 	P.Trace("ReturnStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.RETURN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) ParseControlFlowStat(tok int) { | 
					
						
							|  |  |  | 	P.Trace("ControlFlowStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	P.Expect(tok); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | func (P *Parser) ParseIfStat() *AST.IfStat { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("IfStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.IF); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.ParseBlock(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.ELSE { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.IF { | 
					
						
							|  |  |  | 			P.ParseIfStat(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// TODO should be P.ParseBlock() | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.ParseStatement(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseForStat() { | 
					
						
							|  |  |  | 	P.Trace("ForStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.FOR); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseSimpleStat(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.ParseBlock(); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCase() { | 
					
						
							|  |  |  | 	P.Trace("Case"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok == Scanner.CASE { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.DEFAULT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.COLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCaseList() { | 
					
						
							|  |  |  | 	P.Trace("CaseList"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.ParseCase(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { | 
					
						
							|  |  |  | 		P.ParseCase(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCaseClause() { | 
					
						
							|  |  |  | 	P.Trace("CaseClause"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.ParseCaseList(); | 
					
						
							|  |  |  | 	if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.FALLTHROUGH { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSwitchStat() { | 
					
						
							|  |  |  | 	P.Trace("SwitchStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.SWITCH); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 		if P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-10 20:50:38 -07:00
										 |  |  | 			if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 				P.ParseExpression(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	for P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseCaseClause(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | func (P *Parser) ParseCommCase() { | 
					
						
							|  |  |  |   P.Trace("CommCase"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  |   if P.tok == Scanner.CASE { | 
					
						
							|  |  |  | 	P.Next(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.GTR { | 
					
						
							|  |  |  | 		// send | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 		P.Expect(Scanner.EQL); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// receive | 
					
						
							|  |  |  | 		if P.tok != Scanner.LSS { | 
					
						
							|  |  |  | 			P.ParseIdent(); | 
					
						
							|  |  |  | 			P.Expect(Scanner.ASSIGN); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Expect(Scanner.LSS); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  | 	P.Expect(Scanner.DEFAULT); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   P.Expect(Scanner.COLON); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  |   P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCommClause() { | 
					
						
							|  |  |  | 	P.Trace("CommClause"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.ParseCommCase(); | 
					
						
							|  |  |  | 	if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							|  |  |  | 		P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseRangeStat() bool { | 
					
						
							|  |  |  | 	P.Trace("RangeStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Expect(Scanner.RANGE); | 
					
						
							|  |  |  | 	P.ParseIdentList(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.DEFINE); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	P.ParseBlock(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSelectStat() bool { | 
					
						
							|  |  |  | 	P.Trace("SelectStat"); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Expect(Scanner.SELECT); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	for P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseCommClause(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | func (P *Parser) TryStatement() bool { | 
					
						
							|  |  |  | 	P.Trace("Statement (try)"); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	res := true; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.CONST: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.TYPE: fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-15 09:22:20 -07:00
										 |  |  | 	case Scanner.VAR: | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseDeclaration(); | 
					
						
							| 
									
										
										
										
											2008-07-15 09:22:20 -07:00
										 |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		// for now we do not allow local function declarations | 
					
						
							|  |  |  | 		fallthrough; | 
					
						
							| 
									
										
										
										
											2008-07-17 15:11:46 -07:00
										 |  |  | 	case Scanner.SEND: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.RECV: | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.ParseSimpleStat();  // send or receive | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.IDENT: | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		switch P.val { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		case "print", "panic": | 
					
						
							|  |  |  | 			P.ParseBuiltinStat(); | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.GO: | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 		P.ParseGoStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.RETURN: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseReturnStat(); | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 	case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: | 
					
						
							|  |  |  | 		P.ParseControlFlowStat(P.tok); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.LBRACE: | 
					
						
							|  |  |  | 		P.ParseBlock(); | 
					
						
							|  |  |  | 	case Scanner.IF: | 
					
						
							|  |  |  | 		P.ParseIfStat(); | 
					
						
							|  |  |  | 	case Scanner.FOR: | 
					
						
							|  |  |  | 		P.ParseForStat(); | 
					
						
							|  |  |  | 	case Scanner.SWITCH: | 
					
						
							|  |  |  | 		P.ParseSwitchStat(); | 
					
						
							|  |  |  | 	case Scanner.RANGE: | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 		P.ParseRangeStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.SELECT: | 
					
						
							| 
									
										
										
										
											2008-07-09 14:01:17 -07:00
										 |  |  | 		P.ParseSelectStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		// no statement found | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 		res = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-23 16:04:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		panic "imbalanced tracing code (Statement)" | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Declarations | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseImportSpec() { | 
					
						
							|  |  |  | 	P.Trace("ImportSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else if P.tok == Scanner.IDENT { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.STRING); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseImportDecl() { | 
					
						
							|  |  |  | 	P.Trace("ImportDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.IMPORT); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:16:33 -07:00
										 |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		for P.tok != Scanner.RPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			P.ParseImportSpec(); | 
					
						
							|  |  |  | 			P.Optional(Scanner.SEMICOLON);  // TODO this seems wrong | 
					
						
							| 
									
										
										
										
											2008-07-09 10:16:33 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-09 10:16:33 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseImportSpec(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseConstSpec() { | 
					
						
							|  |  |  | 	P.Trace("ConstSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	list := P.ParseIdentDeclList(Object.CONST); | 
					
						
							|  |  |  | 	typ := P.TryType(); | 
					
						
							|  |  |  | 	if typ != nil { | 
					
						
							|  |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			p.obj.typ = typ;  // TODO should use/have set_type()! | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.ParseExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseConstDecl() { | 
					
						
							|  |  |  | 	P.Trace("ConstDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.CONST); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		for P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 			P.ParseConstSpec(); | 
					
						
							|  |  |  | 			if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 				P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseConstSpec(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseTypeSpec() { | 
					
						
							|  |  |  | 	P.Trace("TypeSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 	pos := P.pos; | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	ident := P.ParseIdent(); | 
					
						
							|  |  |  | 	obj := P.top_scope.Lookup(ident);  // only lookup in top scope! | 
					
						
							|  |  |  | 	if obj != nil { | 
					
						
							|  |  |  | 		// ok if forward declared type | 
					
						
							|  |  |  | 		if obj.kind != Object.TYPE || obj.typ.form != Type.UNDEF { | 
					
						
							|  |  |  | 			// TODO use obj.pos to refer to decl pos in error msg! | 
					
						
							|  |  |  | 			P.Error(pos, `"` + ident + `" is declared already`); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		obj = Globals.NewObject(pos, Object.TYPE, ident); | 
					
						
							|  |  |  | 		obj.typ = Universe.undef_t;  // TODO fix this | 
					
						
							|  |  |  | 		P.top_scope.Insert(obj); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	typ := P.TryType();  // no type if we have a forward decl | 
					
						
							|  |  |  | 	if typ != nil { | 
					
						
							|  |  |  | 		// TODO what about the name of incomplete types? | 
					
						
							|  |  |  | 		obj.typ = typ;  // TODO should use/have set_typ()! | 
					
						
							|  |  |  | 		if typ.obj == nil { | 
					
						
							|  |  |  | 			typ.obj = obj;  // primary type object | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseTypeDecl() { | 
					
						
							|  |  |  | 	P.Trace("TypeDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.TYPE); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		for P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 			P.ParseTypeSpec(); | 
					
						
							|  |  |  | 			if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 				P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.ParseTypeSpec(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseVarSpec() { | 
					
						
							|  |  |  | 	P.Trace("VarSpec"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	list := P.ParseIdentDeclList(Object.VAR); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		typ := P.ParseType(); | 
					
						
							|  |  |  | 		for p := list.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 			p.obj.typ = typ;  // TODO should use/have set_type()! | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseExpressionList(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseVarDecl() { | 
					
						
							|  |  |  | 	P.Trace("VarDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.VAR); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		for P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 			P.ParseVarSpec(); | 
					
						
							|  |  |  | 			if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 				P.Expect(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseVarSpec(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseFuncDecl() { | 
					
						
							|  |  |  | 	P.Trace("FuncDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.FUNC); | 
					
						
							|  |  |  | 	P.ParseNamedSignature(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		// forward declaration | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseBlock(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseExportDecl() { | 
					
						
							|  |  |  | 	P.Trace("ExportDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	P.Expect(Scanner.EXPORT); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		for P.tok != Scanner.RPAREN { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 			P.exports.AddStr(P.ParseIdent()); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 			P.Optional(Scanner.COMMA);  // TODO this seems wrong | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		P.exports.AddStr(P.ParseIdent()); | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 		for P.tok == Scanner.COMMA { | 
					
						
							| 
									
										
										
										
											2008-07-08 18:37:31 -07:00
										 |  |  | 			P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 			P.exports.AddStr(P.ParseIdent()); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | func (P *Parser) ParseDeclaration() { | 
					
						
							|  |  |  | 	P.Trace("Declaration"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	indent := P.indent; | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.CONST: | 
					
						
							|  |  |  | 		P.ParseConstDecl(); | 
					
						
							|  |  |  | 	case Scanner.TYPE: | 
					
						
							|  |  |  | 		P.ParseTypeDecl(); | 
					
						
							|  |  |  | 	case Scanner.VAR: | 
					
						
							|  |  |  | 		P.ParseVarDecl(); | 
					
						
							|  |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		P.ParseFuncDecl(); | 
					
						
							|  |  |  | 	case Scanner.EXPORT: | 
					
						
							|  |  |  | 		P.ParseExportDecl(); | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-18 17:18:29 -07:00
										 |  |  | 		P.Error(P.pos, "declaration expected"); | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 		P.Next();  // make progress | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	if indent != P.indent { | 
					
						
							| 
									
										
										
										
											2008-07-23 16:59:06 -07:00
										 |  |  | 		panic "imbalanced tracing code (Declaration)" | 
					
						
							| 
									
										
										
										
											2008-07-09 14:48:26 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-15 15:37:14 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-15 10:05:17 -07:00
										 |  |  | // ---------------------------------------------------------------------------- | 
					
						
							|  |  |  | // Program | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | func (P *Parser) MarkExports() { | 
					
						
							|  |  |  | 	if !EnableSemanticTests { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	scope := P.top_scope; | 
					
						
							|  |  |  | 	for p := P.exports.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 		obj := scope.Lookup(p.str); | 
					
						
							|  |  |  | 		if obj != nil { | 
					
						
							|  |  |  | 			obj.mark = true; | 
					
						
							|  |  |  | 			// For now we export deep | 
					
						
							|  |  |  | 			// TODO this should change eventually - we need selective export | 
					
						
							|  |  |  | 			if obj.kind == Object.TYPE { | 
					
						
							|  |  |  | 				typ := obj.typ; | 
					
						
							|  |  |  | 				if typ.form == Type.STRUCT || typ.form == Type.INTERFACE { | 
					
						
							|  |  |  | 					scope := typ.scope; | 
					
						
							|  |  |  | 					for p := scope.entries.first; p != nil; p = p.next { | 
					
						
							|  |  |  | 						p.obj.mark = true; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// TODO need to report proper src position | 
					
						
							|  |  |  | 			P.Error(0, `"` + p.str + `" is not declared - cannot be exported`); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | func (P *Parser) ParseProgram() { | 
					
						
							|  |  |  | 	P.Trace("Program"); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.PACKAGE); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 	pkg := P.comp.pkgs[0]; | 
					
						
							|  |  |  | 	pkg.obj = P.ParseIdentDecl(Object.PACKAGE); | 
					
						
							| 
									
										
										
										
											2008-07-10 18:05:00 -07:00
										 |  |  | 	P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	{	P.OpenScope(); | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		pkg.scope = P.top_scope; | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		for P.tok == Scanner.IMPORT { | 
					
						
							|  |  |  | 			P.ParseImportDecl(); | 
					
						
							|  |  |  | 			P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for P.tok != Scanner.EOF { | 
					
						
							|  |  |  | 			P.ParseDeclaration(); | 
					
						
							|  |  |  | 			P.Optional(Scanner.SEMICOLON); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-17 18:02:10 -07:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		P.MarkExports(); | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 		P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-10 18:05:00 -07:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-07-14 18:06:41 -07:00
										 |  |  | 	P.CloseScope(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } |