Browse Source

Attempt at improving the syntax, but operators are spoiling the broth here, I feel. I'll investigate a more TCL like syntax next. Also fixed some lexer bugs.

Beoran 7 years ago
parent
commit
15cb0472db
2 changed files with 204 additions and 50 deletions
  1. 150 42
      raku/raku.go
  2. 54 8
      raku/raku_test.go

+ 150 - 42
raku/raku.go

@@ -74,7 +74,7 @@ const (
 	TokenKeywordDo    TokenType = -11
 	TokenKeywordEnd   TokenType = -12
 	TokenKeywordThe   TokenType = -13
-	TokenKeywordTo    TokenType = -14
+	TokenKeywordDef   TokenType = -14
 	TokenLastKeyword  TokenType = -15
 	TokenLast         TokenType = -15
 )
@@ -99,16 +99,17 @@ var tokenTypeMap map[TokenType]string = map[TokenType]string{
 	TokenKeywordDo:  "TokenKeywordDo",
 	TokenKeywordEnd: "TokenKeywordEnd",
 	TokenKeywordThe: "TokenKeywordThe",
-	TokenKeywordTo:  "TokenKeywordTo",
+	TokenKeywordDef: "TokenKeywordDef",
 }
 
 var keywordMap map[string]TokenType = map[string]TokenType{
-	"a":   TokenKeywordA,
-	"an":  TokenKeywordA,
-	"do":  TokenKeywordDo,
-	"end": TokenKeywordEnd,
-	"the": TokenKeywordThe,
-	"to":  TokenKeywordTo,
+	"a":      TokenKeywordA,
+	"an":     TokenKeywordA,
+	"do":     TokenKeywordDo,
+	"def":    TokenKeywordDef,
+	"define": TokenKeywordDef,
+	"end":    TokenKeywordEnd,
+	"the":    TokenKeywordThe,
 }
 
 var sigilMap map[string]TokenType = map[string]TokenType{
@@ -193,8 +194,15 @@ func LookupSigil(sigil string) (bool, TokenType) {
 	return found, kind
 }
 
+func LexSigil(me *Lexer) LexerRule {
+	me.Found(TokenType(me.Peek()))
+	_ = me.Next()
+	me.Advance()
+	return LexNormal
+}
+
 func LexWord(me *Lexer) LexerRule {
-	me.SkipNotIn(" \t\r\n'")
+	me.SkipNotIn(" \t\r\n'({[]})")
 
 	iskw, kind := LookupKeyword(me.CurrentStringValue())
 	if iskw {
@@ -206,13 +214,13 @@ func LexWord(me *Lexer) LexerRule {
 }
 
 func LexSymbol(me *Lexer) LexerRule {
-	me.SkipNotIn(" \t\r\n'")
+	me.SkipNotIn(" \t\r\n'({[]})")
 	me.Found(TokenSymbol)
 	return LexNormal
 }
 
 func LexNumber(me *Lexer) LexerRule {
-	me.SkipNotIn(" \tBBBT\r\n")
+	me.SkipNotIn(" \t\r\n'({[]})")
 	me.Found(TokenNumber)
 	return LexNormal
 }
@@ -233,7 +241,8 @@ func LexComment(me *Lexer) LexerRule {
 }
 
 func LexPunctuator(me *Lexer) LexerRule {
-	me.Found(TokenType(me.Peek()))
+	me.Found(TokenType(me.Next()))
+	me.Advance()
 	return LexNormal
 }
 
@@ -244,7 +253,7 @@ func LexEOL(me *Lexer) LexerRule {
 }
 
 func LexOperator(me *Lexer) LexerRule {
-	me.SkipNotIn(" \t\r\n")
+	me.SkipNotIn(" \t\r\n({[]})")
 	issig, kind := LookupSigil(me.CurrentStringValue())
 	if issig {
 		me.Found(kind)
@@ -297,6 +306,8 @@ func LexNormal(me *Lexer) LexerRule {
 		return LexWhitespace
 	} else if strings.ContainsRune(".,;:", peek) {
 		return LexPunctuator
+	} else if strings.ContainsRune("([{}])", peek) {
+		return LexSigil
 	} else if strings.ContainsRune("$", peek) {
 		return LexSymbol
 	} else if strings.ContainsRune("\r\n", peek) {
@@ -501,6 +512,8 @@ const (
 	AstTypeValue
 	AstTypeEox
 	AstTypeOperator
+	AstTypeParenthesis
+	AstTypeModifier
 	AstTypeError
 )
 
@@ -527,6 +540,8 @@ var astTypeMap map[AstType]string = map[AstType]string{
 	AstTypeValue:              "AstTypeValue",
 	AstTypeEox:                "AstTypeEox",
 	AstTypeOperator:           "AstTypeOperator",
+	AstTypeParenthesis:        "AstTypeParenthesis",
+	AstTypeModifier:           "AstTypeModifier",
 	AstTypeError:              "AstTypeError",
 }
 
@@ -636,14 +651,14 @@ func (me *Parser) SetupRules() {
 }
 
 func (me *Parser) Expect(types ...TokenType) bool {
-	fmt.Print("Expecting: ", types, " from ", me.now.AstType, " have ", me.LookaheadType(), " \n")
+	monolog.Debug("Expecting: ", types, " from ", me.now.AstType, " have ", me.LookaheadType(), " \n")
 	for _, t := range types {
 		if me.LookaheadType() == t {
-			fmt.Print("Found: ", t, "\n")
+			monolog.Debug("Found: ", t, "\n")
 			return true
 		}
 	}
-	fmt.Print("Not found.\n")
+	monolog.Debug("Not found.\n")
 	return false
 }
 
@@ -765,12 +780,14 @@ func (me *Parser) ParseOperator() bool {
 	return me.Consume(AstTypeOperator, TokenOperator)
 }
 
+/*
 func (me *Parser) ParseOperation() bool {
 	me.NewAstChildDescend(AstTypeOperation)
 	res := me.ParseOperator() && me.ParseParameter()
 	me.AstAscend(res)
 	return res
 }
+*/
 
 func (me *Parser) ParseOperations() bool {
 	me.NewAstChildDescend(AstTypeOperations)
@@ -828,16 +845,24 @@ func (me *Parser) AstAscend(keep bool) {
 	}
 }
 
-func (me TokenType) CloseForOpen() (TokenType, bool) {
+func (me TokenType) BlockCloseForOpen() (TokenType, bool) {
 	switch me {
 	case TokenOpenBrace:
 		return TokenCloseBrace, true
+	case TokenOpenParen:
+		return TokenCloseParen, true
+	default:
+		return TokenError, false
+	}
+
+}
+
+func (me TokenType) ParenthesisCloseForOpen() (TokenType, bool) {
+	switch me {
 	case TokenOpenBracket:
 		return TokenCloseBracket, true
 	case TokenOpenParen:
 		return TokenCloseParen, true
-	case TokenKeywordDo:
-		return TokenKeywordEnd, true
 	default:
 		return TokenError, false
 	}
@@ -847,7 +872,7 @@ func (me TokenType) CloseForOpen() (TokenType, bool) {
 func (me *Parser) ParseBlock() bool {
 	me.Advance()
 	open := me.LookaheadType()
-	done, ok := open.CloseForOpen()
+	done, ok := open.BlockCloseForOpen()
 	if !ok {
 		/* Not an opening of a block, so no block found. */
 		return false
@@ -866,6 +891,28 @@ func (me *Parser) ParseBlock() bool {
 	return res
 }
 
+func (me *Parser) ParseParenthesis() bool {
+	me.Advance()
+	open := me.LookaheadType()
+	done, ok := open.ParenthesisCloseForOpen()
+	if !ok {
+		/* Not an opening of a parenthesis, so no parenthesis found. */
+		return false
+	}
+	me.DropLookahead()
+	me.NewAstChildDescend(AstTypeParenthesis)
+	res := me.ParseExpression()
+	me.AstAscend(res)
+	if res {
+		me.Advance()
+		if me.LookaheadType() != done {
+			return me.ParseError()
+		}
+		me.DropLookahead()
+	}
+	return res
+}
+
 func (me *Parser) ParseWords() bool {
 	me.NewAstChildDescend(AstTypeWords)
 	res := me.ParseWord()
@@ -877,7 +924,7 @@ func (me *Parser) ParseWords() bool {
 
 func (me *Parser) ParseDefinition() bool {
 	me.Advance()
-	res := me.Consume(AstTypeDefinition, TokenKeywordTo)
+	res := me.Consume(AstTypeDefinition, TokenKeywordDef)
 	if !res {
 		return false
 	}
@@ -893,6 +940,27 @@ func (me *Parser) ParseDefinition() bool {
 	return res
 }
 
+func (me *Parser) ParseOperation() bool {
+	me.NewAstChildDescend(AstTypeOperation)
+	res := me.ParseOperator() && me.ParseModifier()
+	me.AstAscend(res)
+	return res
+}
+
+func (me *Parser) ParseModifier() bool {
+	me.NewAstChildDescend(AstTypeModifier)
+	res := me.ParseOperation() || me.ParseWordValue() ||
+		me.ParseParenthesis() || me.ParseBlock()
+	me.AstAscend(res)
+	return res
+}
+
+func (me *Parser) ParseModifiers() bool {
+	for me.ParseModifier() {
+	}
+	return true
+}
+
 func (me *Parser) ParseError() bool {
 	me.now.NewChild(AstTypeError, me.lookahead)
 	fmt.Printf("Parse error: at %s\n", me.lookahead)
@@ -900,14 +968,17 @@ func (me *Parser) ParseError() bool {
 }
 
 func (me *Parser) ParseExpression() bool {
-	return me.ParseWordExpression() || me.ParseValueExpression()
+	return me.ParseWordValue() && me.ParseModifiers()
 }
 
 func (me *Parser) ParseStatement() bool {
-
 	me.NewAstChildDescend(AstTypeStatement)
 	/* First case is for an empty expression/statement. */
-	res := me.ParseEOX() || me.ParseDefinition() || me.ParseExpression() || me.ParseBlock()
+	res := me.ParseEOX() ||
+		me.ParseDefinition() ||
+		(me.ParseExpression() && me.ParseEOX()) ||
+		me.ParseBlock()
+
 	me.AstAscend(res)
 	return res
 }
@@ -967,36 +1038,73 @@ func (me *Ast) Dotty() {
 }
 
 /*
-	PROGRAM -> STATEMENTS.
+
+PROGRAM -> STATEMENTS.
 STATEMENTS -> STATEMENT STATEMENTS | .
-STATEMENT -> DEFINITION | EXPRESSION | BLOCK .
-DEFINITION -> to WORDS BLOCK.
+STATEMENT -> EXPRESSION EOX  | DEFINITION | BLOCK | EOX .
+DEFINITION -> define WORDS BLOCK.
 WORDS -> word WORDS | .
-EXPRESSION -> WORD_EXPRESSION | VALUE_EXPRESSION.
-WORD_EXPRESSION -> word WORD_CALLOP.
-WORD_CALLOP -> WORD_OPERATION | WORD_CALL.
-OPERATION -> operator PARAMETERS_NONEMPTY EOX.
-WORD_CALL -> PARAMETERS EOX.
-VALUE_EXPRESSION -> value VALUE_CALLOP.
-VALUE_CALLOP -> VALUE_OPERATION | VALUE_CALL.
-VALUE_CALL -> EOX.
-PARAMETERS_NONEMPTY -> PARAMETER PARAMETERS.
-PARAMETERS -> PARAMETERS_NONEMPTY | .
-PARAMETER -> BLOCK | WORDVALUE | OPERATION.
-BLOCK -> ob STATEMENTS cb | op STATEMENTS cp | oa STATEMENTS ca | do STATEMENTS end.
-WORDVALUE -> word | VALUE.
+EXPRESSION -> WORDVALUE MODIFIERS.
+MODIFIERS -> MODIFIER MODIFIERS | .
+OPERATION ->  operator MODIFIER .
+MODIFIER -> OPERATION | WORDVALUE | PARENTHESIS | BLOCK.
+PARENTHESIS -> '(' EXPRESSION ')' | ot EXPRESSION ct.
+BLOCK -> oe STATEMENTS ce | do STATEMENTS end .
+WORDVALUE -> word | VALUE | a | the.
 VALUE -> string | number | symbol.
 EOX -> eol | period.
 
-
 	AstNodeBlock = AstNodeType(iota)
 )
 */
 
+type DefineType int
+
+const (
+		DefineTypeNone = DefineType(iota),
+		DefineTypeGo,
+		DefineTypeUser,
+		DefineTypeVar,
+)
+
+type Value interface {
+	
+}
+
+type DefinePattern struct {
+	Parts []string
+}
+
+type GoDefineFunc func(runtime Runtime, args ... Value) Value;
+
+type UserDefine struct {
+	DefinePattern
+	* Ast	
+}
+
+type GoDefine struct {
+	DefinePattern
+	* GoDefineFunc
+}
+
+
+type Define struct {
+	DefineType
+	Ast * definition
+}
+
 type Environment struct {
-	Parent *Environment
+	Parent *Environment	
+}
+
+
+type Runtime struct {
+	Environment
 }
 
+
+
+
 func main() {
 	fmt.Println("Hello World!")
 }

+ 54 - 8
raku/raku_test.go

@@ -11,14 +11,32 @@ import (
 
 func HelperTryLexing(me *Lexer, test *testing.T) {
 	go me.Start()
+	me.Advance()
 	test.Logf("Lexing started:")
 	test.Logf("Lexer buffer: %v", me.buffer)
 
 	for token := range me.Output {
-		test.Logf("Token %s", token)
+		// test.Logf("Token %s", token)
+		_ = token
 	}
 }
 
+func LexAll(me *Lexer) []*Token {
+	res := make([]*Token, 0)
+	go me.Start()
+
+	for token := range me.Output {
+		res = append(res, token)
+	}
+	return res
+}
+
+func LexText(input string) []*Token {
+	lexer := OpenLexer(strings.NewReader(input))
+	tokens := LexAll(lexer)
+	return tokens
+}
+
 func Assert(test *testing.T, ok bool, text string) bool {
 	if !ok {
 		test.Error(text)
@@ -30,11 +48,11 @@ func TestLexing(test *testing.T) {
 	const input = `
 say "hello \"world\\"
 
-to open a door do
+define open a door do
 	set door's open to true
 end
 
-to increment variable by value do
+def increment variable by value do
 	variable = variable + value 
 end
 `
@@ -134,9 +152,9 @@ func TestParseProgram(test *testing.T) {
 }
 
 func TestParseProgram2(test *testing.T) {
-	const input = `to greet someone [
+	const input = `to greet someone  {
 say "hello" someone
-]
+}
 
 greet bob
 
@@ -154,14 +172,14 @@ end
 
 func TestParseblock(test *testing.T) {
 	// monolog.Setup("raku_test.log", true, false)
-	const input = `[
+	const input = `{
 say "hello"
 say "world"
 let i be 3 + 4
 let j be 7 + 5
 let ij be i * j
 return ij
-]
+}
 `
 	parser := NewParserForText(input)
 	Assert(test, parser.ParseBlock(), "Could not parse block.")
@@ -171,10 +189,38 @@ return ij
 
 func TestParseProgram3(test *testing.T) {
 	// monolog.Setup("raku_test.log", true, false)
-	const input = `let foo be set equal = 3 + 4 bar
+	const input = `set foo to (3 + 4)
 `
 	parser := NewParserForText(input)
 	Assert(test, parser.ParseProgram(), "Could not parse program.")
 	tree.Display(parser.Ast)
 	parser.Ast.Dotty()
 }
+
+func TestParseParenthesis(test *testing.T) {
+	// monolog.Setup("raku_test.log", true, false)
+	const input = `(3 + 4 * 5)`
+	parser := NewParserForText(input)
+	Assert(test, parser.ParseParenthesis(), "Could not parse parenthesis.")
+	tree.Display(parser.Ast)
+	parser.Ast.Dotty()
+}
+
+func LexingTest(test *testing.T, input string, expected ...TokenType) {
+	tokens := LexText(input)
+	if len(tokens) != len(expected) {
+		test.Errorf("Amount of tokens does not match expected amount: %d, should be %d", len(tokens), len(expected))
+	}
+	for index := 0; index < len(expected); index++ {
+		want := expected[index]
+		tok := tokens[index]
+		if tok.TokenType != want {
+			test.Errorf("Wrong token type recognized: %v, should be %s", tok, want)
+		}
+	}
+}
+
+func TestLexingParen(test *testing.T) {
+	LexingTest(test, "(", TokenOpenParen, TokenEOF)
+	LexingTest(test, "((", TokenOpenParen, TokenOpenParen, TokenEOF)
+}