123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- package muesli
- import (
- _ "bufio"
- _ "bytes"
- _ "errors"
- _ "fmt"
- _ "io"
- _ "os"
- _ "reflect"
- _ "runtime"
- _ "strings"
- _ "unicode"
- // "gitlab.com/beoran/woe/graphviz"
- // _ "gitlab.com/beoran/woe/monolog"
- )
- /* Grammar:
- Desrired syntax (verified LL(1) on smlweb.cpsc.ucalgary.ca)
- PROGRAM -> STATEMENTS.
- STATEMENTS -> STATEMENT STATEMENTS | .
- STATEMENT -> EXPRESSION eos | BLOCK .
- WORDOPS -> WORDOP WORDOPS | .
- EXPRESSION -> SETTER | GETTER | COMMAND.
- COMMAND -> WORDVALUE PARAMETERS.
- PARAMETERS -> PARAMETER PARAMETERS | .
- PARAMETER -> WORDVALUE | PARENTHESIS | GETTER | ARRARY | BLOCK .
- PARENTHESIS -> '(' EXPRESSION ')' .
- BLOCK -> '{' STATEMENTS '}' .
- WORDVALUE -> word | VALUE.
- VALUE -> string | integer | float | symbol.
- SETTER -> set word PARAMETERS .
- GETTER -> get word .
- *
- * program -> statements
- * statements -> statement+
- * statement -> get / set / command
- *
- */
- type Parser struct {
- Lexer *Lexer
- current *Token
- LoggerWrapper
- }
- func (parser *Parser) SetLogger(logger Logger) {
- parser.LoggerWrapper = LoggerWrapper{logger}
- }
- func (parser *Parser) Advance() {
- token := parser.Lexer.Lex()
- parser.current = &token
- parser.LogDebug("Next token: %s\n", token.String())
- }
- /* Looks at the current token and advances the lexer if the token is of any of
- the token kinds given in kinds. In this case it will return the accepted
- token and advance the parser. Otherwise, if no token kind matches, the lexer
- does not advance and the current token remains the same, except if that was nil.*/
- func (parser *Parser) Accept(kinds ...TokenKind) *Token {
- if parser.current == nil {
- parser.Advance()
- }
- for _, kind := range kinds {
- if kind == parser.current.TokenKind {
- accepted := parser.current
- parser.Advance()
- return accepted
- }
- }
- return nil
- }
- func (parser *Parser) ParseMany(astkind AstKind, parsefunc func(*Parser) *Ast) *Ast {
- ast := NewAst(astkind, nil, nil)
- for sub := parsefunc(parser); sub != nil && sub.AstKind != AstKindError; sub = parsefunc(parser) {
- ast.AppendChild(sub)
- }
- return ast
- }
- func (parser *Parser) NewAstError(message string) *Ast {
- sv := StringValue(message + " at token " + parser.current.String())
- pos := parser.current.Position
- tok := NewToken(TokenKindError, sv, pos)
- return NewAst(AstKindError, nil, &tok)
- }
- func (parser *Parser) ParseAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
- ast := NewAst(astkind, nil, nil)
- for _, parsefunc := range parsefuncs {
- sub := parsefunc(parser)
- if sub != nil {
- ast.AppendChild(sub)
- return ast
- }
- }
- return nil
- }
- func (parser *Parser) ParseRequireAny(astkind AstKind, parsefuncs ...(func(*Parser) *Ast)) *Ast {
- ast := parser.ParseAny(astkind, parsefuncs...)
- if ast == nil {
- err := parser.NewAstError("Unexpected token")
- return err
- }
- return ast
- }
- func (parser *Parser) ParseValue() *Ast {
- value := parser.Accept(TokenKindInteger, TokenKindString,
- TokenKindBoolean, TokenKindFloat, TokenKindSymbol)
- if value == nil {
- return nil
- }
- return NewAst(AstKindValue, nil, value)
- }
- func (parser *Parser) ParseWordValue() *Ast {
- value := parser.Accept(TokenKindInteger, TokenKindString,
- TokenKindBoolean, TokenKindFloat, TokenKindSymbol, TokenKindWord)
- if value == nil {
- return nil
- }
- return NewAst(AstKindWordValue, nil, value)
- }
- func (parser *Parser) ParseArgument() *Ast {
- return parser.ParseAny(AstKindArgument,
- (*Parser).ParseWordValue,
- (*Parser).ParseGet,
- (*Parser).ParseSet,
- (*Parser).ParseParenthesis,
- (*Parser).ParseList,
- (*Parser).ParseBlock)
- }
- func (parser *Parser) ParseArguments() *Ast {
- return parser.ParseMany(AstKindArguments, (*Parser).ParseArgument)
- }
- func (parser *Parser) ParseList() *Ast {
- op := parser.Accept(TokenKindOpenList)
- if op == nil {
- return nil
- }
- ast := NewAst(AstKindList, nil, op)
- args := parser.ParseArguments()
- if args.AstKind == AstKindError {
- return args
- }
- if cp := parser.Accept(TokenKindCloseList); cp == nil {
- return parser.NewAstError("expected closing brackets")
- }
- ast.AppendChild(args)
- return ast
- }
- func (parser *Parser) ParseParenthesis() *Ast {
- op := parser.Accept(TokenKindOpenParen)
- if op == nil {
- return nil
- }
- ast := NewAst(AstKindParenthesis, nil, op)
- expr := parser.ParseExpression()
- if expr == nil {
- return parser.NewAstError("expected expression")
- }
- if expr.AstKind == AstKindError {
- return expr
- }
- if cp := parser.Accept(TokenKindCloseParen); cp == nil {
- return parser.NewAstError("expected closing parenthesis")
- }
- ast.AppendChild(expr)
- return ast
- }
- func (parser *Parser) ParseBlock() *Ast {
- op := parser.Accept(TokenKindOpenBlock)
- if op == nil {
- return nil
- }
- ast := NewAst(AstKindBlock, nil, op)
- stats := parser.ParseStatements()
- if stats == nil {
- return parser.NewAstError("expected expression")
- }
- if stats.AstKind == AstKindError {
- return stats
- }
- if cp := parser.Accept(TokenKindCloseBlock); cp == nil {
- return parser.NewAstError("expected closing block")
- }
- ast.AppendChild(stats)
- return ast
- }
- /* Parses the target of a set or get expression */
- func (parser *Parser) ParseTarget() *Ast {
- target := parser.Accept(TokenKindWord, TokenKindSymbol)
- ast := NewAst(AstKindTarget, nil, target)
- if target == nil {
- paren := parser.ParseParenthesis()
- if paren == nil {
- return parser.NewAstError("expected word, symbol or parenthesis")
- }
- ast.AppendChild(paren)
- }
- return ast
- }
- func (parser *Parser) ParseSet() *Ast {
- set := parser.Accept(TokenKindSet)
- if set == nil {
- return nil
- }
- ast := NewAst(AstKindGet, nil, set)
- target := parser.ParseTarget()
- ast.AppendChild(target)
- argument := parser.ParseArgument()
- if argument == nil {
- return parser.NewAstError("Expected argument to set")
- }
- ast.AppendChild(argument)
- return ast
- }
- func (parser *Parser) ParseGet() *Ast {
- get := parser.Accept(TokenKindGet)
- if get == nil {
- return nil
- }
- ast := NewAst(AstKindGet, nil, get)
- target := parser.ParseTarget()
- ast.AppendChild(target)
- return ast
- }
- func (parser *Parser) ParseCommand() *Ast {
- word := parser.Accept(TokenKindWord)
- if word == nil {
- return nil
- }
- arguments := parser.ParseArguments()
- command := NewAst(AstKindCommand, nil, word)
- command.AppendChild(arguments)
- return command
- }
- func (parser *Parser) ParseExpression() *Ast {
- exp := parser.ParseRequireAny(AstKindExpression, (*Parser).ParseSet,
- (*Parser).ParseGet, (*Parser).ParseCommand)
- return exp
- }
- func (parser *Parser) ParseEmptyStatement() *Ast {
- eox := parser.Accept(TokenKindEOX)
- if eox == nil {
- return nil
- }
- ast := NewAst(AstKindEnd, nil, eox)
- return ast
- }
- func (parser *Parser) ParseStatement() *Ast {
- ast := parser.ParseAny(AstKindStatement,
- (*Parser).ParseBlock,
- (*Parser).ParseSet,
- (*Parser).ParseGet,
- (*Parser).ParseCommand,
- (*Parser).ParseParenthesis)
- if eox := parser.Accept(TokenKindEOX); eox == nil {
- return parser.NewAstError("expected end of statement")
- }
- return ast
- }
- func (parser *Parser) ParseStatements() *Ast {
- return parser.ParseMany(AstKindStatements, (*Parser).ParseStatement)
- }
- func (parser *Parser) ParseProgram() *Ast {
- ast := NewAst(AstKindProgram, nil, nil)
- stats := parser.ParseStatements()
- eof := parser.Accept(TokenKindEOF)
- aeof := NewAst(AstKindEnd, nil, eof)
- // be lenient with missing EOF for now...
- ast.AppendChild(stats)
- ast.AppendChild(aeof)
- return ast
- }
- func (parser *Parser) Parse() *Ast {
- ast := parser.ParseProgram()
- return ast
- }
- func NewParser(lexer *Lexer) *Parser {
- parser := &Parser{lexer, nil, LoggerWrapper{nil}}
- return parser
- }
- func NewParserFromString(input string) *Parser {
- lexer := NewLexerFromString(input)
- return NewParser(lexer)
- }
- func NewParserFromFilename(filename string) (*Parser, error) {
- lexer, err := NewLexerFromFileName(filename)
- if err != nil {
- return nil, err
- }
- return NewParser(lexer), nil
- }
|