| 
									
										
										
										
											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" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export Parser | 
					
						
							|  |  |  | type Parser struct { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	verbose, indent int; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	S *Scanner.Scanner; | 
					
						
							|  |  |  | 	tok int;  // one token look-ahead | 
					
						
							|  |  |  | 	beg, end int;  // token position | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	ident string;  // last ident seen | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) PrintIndent() { | 
					
						
							|  |  |  | 	for i := P.indent; i > 0; i-- { | 
					
						
							|  |  |  | 		print "  "; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-08 16:39:04 -07:00
										 |  |  | 	P.tok, P.beg, P.end = P.S.Scan(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ident = P.S.src[P.beg : P.end]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if P.verbose > 1 { | 
					
						
							|  |  |  | 		P.PrintIndent(); | 
					
						
							|  |  |  | 		print Scanner.TokenName(P.tok), "\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) Open(S *Scanner.Scanner, verbose int) { | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Error(msg string) { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	panic "error: ", msg, "\n"; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) Expect(tok int) { | 
					
						
							|  |  |  | 	if tok != P.tok { | 
					
						
							|  |  |  | 		P.Error("expected `" + Scanner.TokenName(tok) + "`, found `" + Scanner.TokenName(P.tok) + "`"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Next();  // make progress in any case | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseType(); | 
					
						
							|  |  |  | func (P *Parser) ParseExpression(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIdent() { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	if P.verbose > 0 { | 
					
						
							|  |  |  | 		P.PrintIndent(); | 
					
						
							|  |  |  | 		print "Ident = \"", P.ident, "\"\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.IDENT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseQualifiedIdent() { | 
					
						
							|  |  |  | 	P.Trace("QualifiedIdent"); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseTypeName() { | 
					
						
							|  |  |  | 	P.Trace("TypeName"); | 
					
						
							|  |  |  | 	P.ParseQualifiedIdent(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseArrayType() { | 
					
						
							|  |  |  | 	P.Trace("ArrayType"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RBRACK { | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseChannelType() { | 
					
						
							|  |  |  | 	P.Trace("ChannelType"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	panic "ChannelType"; | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseInterfaceType() { | 
					
						
							|  |  |  | 	P.Trace("InterfaceType"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	panic "InterfaceType"; | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseFunctionType() { | 
					
						
							|  |  |  | 	P.Trace("FunctionType"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	panic "FunctionType"; | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseMapType() { | 
					
						
							|  |  |  | 	P.Trace("MapType"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.MAP); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseFieldDecl() { | 
					
						
							|  |  |  | 	P.Trace("FieldDecl"); | 
					
						
							|  |  |  | 	P.ParseIdentList(); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseStructType() { | 
					
						
							|  |  |  | 	P.Trace("StructType"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.STRUCT); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	for P.tok != Scanner.RBRACE { | 
					
						
							| 
									
										
										
										
											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 16:39:04 -07:00
										 |  |  | 	if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParsePointerType() { | 
					
						
							|  |  |  | 	P.Trace("PointerType"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.MUL); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseType() { | 
					
						
							|  |  |  | 	P.Trace("Type"); | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT: | 
					
						
							|  |  |  | 		P.ParseTypeName(); | 
					
						
							|  |  |  | 	case Scanner.LBRACK: | 
					
						
							|  |  |  | 		P.ParseArrayType(); | 
					
						
							|  |  |  | 	case Scanner.CHAN: | 
					
						
							|  |  |  | 		P.ParseChannelType(); | 
					
						
							|  |  |  | 	case Scanner.INTERFACE: | 
					
						
							|  |  |  | 		P.ParseInterfaceType(); | 
					
						
							|  |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		P.ParseFunctionType(); | 
					
						
							|  |  |  | 	case Scanner.MAP: | 
					
						
							|  |  |  | 		P.ParseMapType(); | 
					
						
							|  |  |  | 	case Scanner.STRUCT: | 
					
						
							|  |  |  | 		P.ParseStructType(); | 
					
						
							|  |  |  | 	case Scanner.MUL: | 
					
						
							|  |  |  | 		P.ParsePointerType(); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		P.Error("type expected"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseImportSpec() { | 
					
						
							|  |  |  | 	P.Trace("ImportSpec"); | 
					
						
							|  |  |  | 	if P.tok == Scanner.PERIOD { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.STRING); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseImportDecl() { | 
					
						
							|  |  |  | 	P.Trace("ImportDecl"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.IMPORT); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.ParseImportSpec(); | 
					
						
							|  |  |  | 		for P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseImportSpec(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseImportSpec(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseExpressionList() { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Trace("ExpressionList"); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseConstSpec() { | 
					
						
							|  |  |  | 	P.Trace("ConstSpec"); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	// TODO factor this code | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT, Scanner.LBRACK, Scanner.CHAN, Scanner.INTERFACE, | 
					
						
							|  |  |  | 		Scanner.FUNC, Scanner.MAP, Scanner.STRUCT, Scanner.MUL: | 
					
						
							|  |  |  | 		P.ParseType(); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseConstDecl() { | 
					
						
							|  |  |  | 	P.Trace("ConstDecl"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.CONST); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.ParseConstSpec(); | 
					
						
							|  |  |  | 		for P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseConstSpec(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseConstSpec(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseTypeSpec() { | 
					
						
							|  |  |  | 	P.Trace("TypeSpec"); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	// TODO factor this code | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT, Scanner.LBRACK, Scanner.CHAN, Scanner.INTERFACE, | 
					
						
							|  |  |  | 		Scanner.FUNC, Scanner.MAP, Scanner.STRUCT, Scanner.MUL: | 
					
						
							|  |  |  | 		P.ParseType(); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseTypeDecl() { | 
					
						
							|  |  |  | 	P.Trace("TypeDecl"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.TYPE); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.ParseTypeSpec(); | 
					
						
							|  |  |  | 		for P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseTypeSpec(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseTypeSpec(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseVarSpec() { | 
					
						
							|  |  |  | 	P.Trace("VarSpec"); | 
					
						
							|  |  |  | 	P.ParseIdentList(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseType(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.ASSIGN { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseExpressionList(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseVarDecl() { | 
					
						
							|  |  |  | 	P.Trace("VarDecl"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.VAR); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.ParseVarSpec(); | 
					
						
							|  |  |  | 		for P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 			P.ParseVarSpec(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseVarSpec(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameterSection() { | 
					
						
							|  |  |  | 	P.Trace("ParameterSection"); | 
					
						
							|  |  |  | 	P.ParseIdentList(); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameterList() { | 
					
						
							|  |  |  | 	P.Trace("ParameterList"); | 
					
						
							|  |  |  | 	P.ParseParameterSection(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseParameterSection(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseParameters() { | 
					
						
							|  |  |  | 	P.Trace("Parameters"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 		P.ParseParameterList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseResult() { | 
					
						
							|  |  |  | 	P.Trace("Result"); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		// TODO: here we allow empty returns - should proably fix this | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseType(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Named signatures | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //        name (params) | 
					
						
							|  |  |  | //        name (params) type | 
					
						
							|  |  |  | //        name (params) (results) | 
					
						
							|  |  |  | // (recv) name (params) | 
					
						
							|  |  |  | // (recv) name (params) type | 
					
						
							|  |  |  | // (recv) name (params) (results) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseNamedSignature() { | 
					
						
							|  |  |  | 	P.Trace("NamedSignature"); | 
					
						
							|  |  |  | 	if P.tok == Scanner.LPAREN { | 
					
						
							|  |  |  | 		P.ParseParameters(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.ParseIdent();  // function name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	P.ParseParameters(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO factor this code | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT, Scanner.LBRACK, Scanner.CHAN, Scanner.INTERFACE, | 
					
						
							|  |  |  | 		Scanner.FUNC, Scanner.MAP, Scanner.STRUCT, Scanner.MUL, Scanner.LPAREN: | 
					
						
							|  |  |  | 		P.ParseResult(); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseDeclaration(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParseStatement() bool; | 
					
						
							|  |  |  | func (P *Parser) ParseStatementList(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | func (P *Parser) ParseBlock(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParsePrimaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParsePrimaryExprList() { | 
					
						
							|  |  |  | 	P.Trace("PrimaryExprList"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.ParsePrimaryExpr(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParsePrimaryExpr(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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(); | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	case Scanner.ASSIGN: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.DEFINE: | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	case Scanner.COMMA: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParsePrimaryExprList(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.ADD_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.SUB_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.MUL_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.QUO_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.REM_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.AND_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.OR_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.XOR_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.SHL_ASSIGN: | 
					
						
							|  |  |  | 		case Scanner.SHR_ASSIGN: | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			P.Error("expected assignment operand"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseReturnStat() { | 
					
						
							|  |  |  | 	P.Trace("ReturnStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.RETURN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseBreakStat() { | 
					
						
							|  |  |  | 	P.Trace("BreakStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.BREAK); | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseContinueStat() { | 
					
						
							|  |  |  | 	P.Trace("ContinueStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.CONTINUE); | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIfStat() { | 
					
						
							|  |  |  | 	P.Trace("IfStat"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.IF); | 
					
						
							|  |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 		P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseExpression(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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 16:39:04 -07:00
										 |  |  | 			if !P.ParseStatement() { | 
					
						
							|  |  |  | 				P.Error("statement expected"); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseForStat() { | 
					
						
							|  |  |  | 	P.Trace("ForStat"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.FOR); | 
					
						
							|  |  |  | 	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(); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCase() { | 
					
						
							|  |  |  | 	P.Trace("Case"); | 
					
						
							|  |  |  | 	if P.tok == Scanner.CASE { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.DEFAULT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.COLON); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCaseList() { | 
					
						
							|  |  |  | 	P.Trace("CaseList"); | 
					
						
							|  |  |  | 	P.ParseCase(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { | 
					
						
							|  |  |  | 		P.ParseCase(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseCaseClause() { | 
					
						
							|  |  |  | 	P.Trace("CaseClause"); | 
					
						
							|  |  |  | 	P.ParseCaseList(); | 
					
						
							|  |  |  | 	if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.FALLTHROUGH { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSwitchStat() { | 
					
						
							|  |  |  | 	P.Trace("SwitchStat"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.SWITCH); | 
					
						
							|  |  |  | 	if P.tok != Scanner.LBRACE { | 
					
						
							|  |  |  | 		P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.ParseExpression(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	for P.tok != Scanner.RBRACE { | 
					
						
							|  |  |  | 		P.ParseCaseClause(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | func (P *Parser) ParseStatement() bool { | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	P.Trace("Statement"); | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.CONST: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.TYPE: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.VAR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.FUNC: | 
					
						
							|  |  |  | 		P.ParseDeclaration(); | 
					
						
							|  |  |  | 	case Scanner.IDENT: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		switch P.ident { | 
					
						
							|  |  |  | 		case "print", "panic": | 
					
						
							|  |  |  | 			P.ParseBuiltinStat(); | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			P.ParseSimpleStat(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.GO: | 
					
						
							|  |  |  | 		panic "go statement"; | 
					
						
							|  |  |  | 	case Scanner.RETURN: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseReturnStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.BREAK: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseBreakStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.CONTINUE: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.ParseContinueStat(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	case Scanner.GOTO: | 
					
						
							|  |  |  | 		panic "goto statement"; | 
					
						
							|  |  |  | 	case Scanner.LBRACE: | 
					
						
							|  |  |  | 		P.ParseBlock(); | 
					
						
							|  |  |  | 	case Scanner.IF: | 
					
						
							|  |  |  | 		P.ParseIfStat(); | 
					
						
							|  |  |  | 	case Scanner.FOR: | 
					
						
							|  |  |  | 		P.ParseForStat(); | 
					
						
							|  |  |  | 	case Scanner.SWITCH: | 
					
						
							|  |  |  | 		P.ParseSwitchStat(); | 
					
						
							|  |  |  | 	case Scanner.RANGE: | 
					
						
							|  |  |  | 		panic "range statement"; | 
					
						
							|  |  |  | 	case Scanner.SELECT: | 
					
						
							|  |  |  | 		panic "select statement"; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		// no statement found | 
					
						
							|  |  |  | 		P.Ecart(); | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseStatementList() { | 
					
						
							|  |  |  | 	P.Trace("StatementList"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	for P.ParseStatement() { | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseBlock() { | 
					
						
							|  |  |  | 	P.Trace("Block"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LBRACE); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		P.ParseStatementList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACE); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseFuncDecl() { | 
					
						
							|  |  |  | 	P.Trace("FuncDecl"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.FUNC); | 
					
						
							|  |  |  | 	P.ParseNamedSignature(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 		// forward declaration | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.ParseBlock(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseExportDecl() { | 
					
						
							|  |  |  | 	P.Trace("ExportDecl"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.EXPORT); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseDeclaration() { | 
					
						
							|  |  |  | 	P.Trace("Declaration"); | 
					
						
							|  |  |  | 	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: | 
					
						
							|  |  |  | 		P.Error("declaration expected"); | 
					
						
							|  |  |  | 		P.Next();  // make progress | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseNew() { | 
					
						
							|  |  |  | 	P.Trace("New"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.NEW); | 
					
						
							|  |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	P.ParseType(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.COMMA { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpressionList() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseOperand() { | 
					
						
							|  |  |  | 	P.Trace("Operand"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.IDENT: | 
					
						
							|  |  |  | 		P.ParseQualifiedIdent(); | 
					
						
							|  |  |  | 	case Scanner.STRING: | 
					
						
							|  |  |  | 		fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NUMBER: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	case Scanner.LPAREN: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 		P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	case Scanner.IOTA: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.TRUE: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.FALSE: | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 	case Scanner.NEW: | 
					
						
							|  |  |  | 		P.ParseNew(); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic "unknown operand" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseSelectorOrTypeAssertion() { | 
					
						
							|  |  |  | 	P.Trace("SelectorOrTypeAssertion"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.PERIOD); | 
					
						
							|  |  |  | 	if P.tok == Scanner.IDENT { | 
					
						
							|  |  |  | 		P.ParseIdent(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 		P.ParseType(); | 
					
						
							|  |  |  | 		P.Expect(Scanner.RPAREN); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseIndexOrSlice() { | 
					
						
							|  |  |  | 	P.Trace("IndexOrSlice"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.LBRACK); | 
					
						
							|  |  |  | 	P.ParseExpression(); | 
					
						
							|  |  |  | 	if P.tok == Scanner.COLON { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseExpression(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RBRACK); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseInvocation() { | 
					
						
							|  |  |  | 	P.Trace("Invocation"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Expect(Scanner.LPAREN); | 
					
						
							|  |  |  | 	if P.tok != Scanner.RPAREN { | 
					
						
							|  |  |  | 		P.ParseExpressionList(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.Expect(Scanner.RPAREN); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParsePrimaryExpr() { | 
					
						
							|  |  |  | 	P.Trace("PrimaryExpr"); | 
					
						
							|  |  |  | 	P.ParseOperand(); | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.PERIOD: | 
					
						
							|  |  |  | 			P.ParseSelectorOrTypeAssertion(); | 
					
						
							|  |  |  | 		case Scanner.LBRACK: | 
					
						
							|  |  |  | 			P.ParseIndexOrSlice(); | 
					
						
							|  |  |  | 		case Scanner.LPAREN: | 
					
						
							|  |  |  | 			P.ParseInvocation(); | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 			P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseUnaryExpr() { | 
					
						
							|  |  |  | 	P.Trace("UnaryExpr"); | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.ADD: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.SUB: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NOT: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.XOR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.LSS: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.GTR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.MUL: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.AND: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseUnaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	P.ParsePrimaryExpr(); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseMultiplicativeExpr() { | 
					
						
							|  |  |  | 	P.Trace("MultiplicativeExpr"); | 
					
						
							|  |  |  | 	P.ParseUnaryExpr(); | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.MUL: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.QUO: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.REM: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.SHL: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.SHR: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.AND: | 
					
						
							|  |  |  | 			P.ParseUnaryExpr(); | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 			P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseAdditiveExpr() { | 
					
						
							|  |  |  | 	P.Trace("AdditiveExpr"); | 
					
						
							|  |  |  | 	P.ParseMultiplicativeExpr(); | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		switch P.tok { | 
					
						
							|  |  |  | 		case Scanner.ADD: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.SUB: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.OR: fallthrough; | 
					
						
							|  |  |  | 		case Scanner.XOR: | 
					
						
							|  |  |  | 			P.ParseMultiplicativeExpr(); | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 			P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseRelationalExpr() { | 
					
						
							|  |  |  | 	P.Trace("RelationalExpr"); | 
					
						
							|  |  |  | 	P.ParseAdditiveExpr(); | 
					
						
							|  |  |  | 	switch P.tok { | 
					
						
							|  |  |  | 	case Scanner.EQL: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.NEQ: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.LSS: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.LEQ: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.GTR: fallthrough; | 
					
						
							|  |  |  | 	case Scanner.GEQ: | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 		P.Next(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | 		P.ParseAdditiveExpr(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseLANDExpr() { | 
					
						
							|  |  |  | 	P.Trace("LANDExpr"); | 
					
						
							|  |  |  | 	P.ParseRelationalExpr(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.CAND { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseRelationalExpr(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseLORExpr() { | 
					
						
							|  |  |  | 	P.Trace("LORExpr"); | 
					
						
							|  |  |  | 	P.ParseLANDExpr(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.COR { | 
					
						
							|  |  |  | 		P.Next(); | 
					
						
							|  |  |  | 		P.ParseLANDExpr(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseExpression() { | 
					
						
							|  |  |  | 	P.Trace("Expression"); | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.ParseLORExpr(); | 
					
						
							|  |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (P *Parser) ParseProgram() { | 
					
						
							|  |  |  | 	P.Trace("Program"); | 
					
						
							|  |  |  | 	P.Expect(Scanner.PACKAGE); | 
					
						
							|  |  |  | 	P.ParseIdent(); | 
					
						
							|  |  |  | 	for P.tok == Scanner.IMPORT { | 
					
						
							|  |  |  | 		P.ParseImportDecl(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for P.tok != Scanner.EOF { | 
					
						
							|  |  |  | 		P.ParseDeclaration(); | 
					
						
							|  |  |  | 		if P.tok == Scanner.SEMICOLON { | 
					
						
							|  |  |  | 			P.Next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-07-08 16:39:04 -07:00
										 |  |  | 	P.Ecart(); | 
					
						
							| 
									
										
										
										
											2008-07-07 17:27:14 -07:00
										 |  |  | } |