123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- package raku
- import (
- "fmt"
- "strings"
- "gitlab.com/beoran/woe/graphviz"
- "gitlab.com/beoran/woe/monolog"
- "gitlab.com/beoran/woe/tree"
- )
- type ParseAction func(parser *ManualParser) bool
- type RuleType int
- const (
- RuleTypeNone = RuleType(iota)
- RuleTypeAlternate
- RuleTypeSequence
- )
- type Rule struct {
- tree.Node
- Name string
- RuleType
- ParseAction
- }
- func NewRule(name string, ruty RuleType) *Rule {
- res := &Rule{}
- res.RuleType = ruty
- res.Name = name
- return res
- }
- func (me *Rule) NewChild(action ParseAction) *Rule {
- child := NewRule("foo", RuleTypeNone)
- tree.AppendChild(me, child)
- return child
- }
- func (me *Rule) Walk(walker func(rule *Rule) *Rule) *Rule {
- node_res := tree.Walk(me,
- func(node tree.Noder) tree.Noder {
- rule_res := walker(node.(*Rule))
- if rule_res == nil {
- return nil
- } else {
- return rule_res
- }
- })
- return node_res.(*Rule)
- }
- type ManualParser struct {
- *Ast
- *Tokenizer
- Classifier
- now *Ast
- position int
- tokens []*Token
- lookahead *Token
- }
- func (me *ManualParser) SetupRules() {
- }
- func (me *ManualParser) Expect(types ...TokenType) bool {
- monolog.Debug("Expecting: ", types, " from ", me.now.AstType, " have ", me.LookaheadType(), " \n")
- for _, t := range types {
- if me.LookaheadType() == t {
- monolog.Debug("Found: ", t, "\n")
- return true
- }
- }
- monolog.Debug("Not found.\n")
- return false
- }
- type Parsable interface {
- isParsable()
- }
- func (me TokenType) isParsable() {
- }
- func (me ParseAction) isParsable() {
- }
- /* Advance the lexer but only of there is no lookahead token already available in me.lookahead.
- */
- func (me *ManualParser) Advance() *Token {
- if me.lookahead == nil {
- me.lookahead = me.tokens[me.position]
- me.position++
- }
- return me.lookahead
- }
- func (me *ManualParser) DropLookahead() {
- me.lookahead = nil
- }
- func (me *ManualParser) Lookahead() *Token {
- return me.lookahead
- }
- func (me *ManualParser) LookaheadType() TokenType {
- if me.lookahead == nil {
- return TokenError
- }
- return me.Lookahead().TokenType
- }
- func (me *ManualParser) Consume(atyp AstType, types ...TokenType) bool {
- me.Advance()
- res := me.Expect(types...)
- if res {
- me.NewAstChild(atyp)
- me.DropLookahead()
- }
- return res
- }
- func (me *ManualParser) ConsumeWithoutAst(types ...TokenType) bool {
- me.Advance()
- res := me.Expect(types...)
- if res {
- me.DropLookahead()
- }
- return res
- }
- /*
- func (me * ManualParser) OneOf(restype AstType, options ...Parsable) bool {
- res := false
- k, v := range options {
- switch option := v.Type {
- case TokenType: res := Consume(restype, option)
- case ParseAction: res := option(me)
- }
- }
- return res
- }
- */
- func (me *ManualParser) ParseEOX() bool {
- return me.ConsumeWithoutAst(TokenEOL, TokenPeriod)
- }
- func (me *ManualParser) ParseValue() bool {
- return me.Consume(AstTypeValue, TokenString, TokenNumber, TokenSymbol)
- }
- func (me *ManualParser) ParseWord() bool {
- return me.Consume(AstTypeWord, TokenWord, TokenArticle)
- }
- func (me *ManualParser) ParseWordValue() bool {
- me.NewAstChildDescend(AstTypeWordValue)
- res := me.ParseValue() || me.ParseWord()
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseParametersNonempty() bool {
- res := false
- for me.ParseParameter() {
- res = true
- }
- return res
- }
- func (me *ManualParser) ParseCallArgs() bool {
- me.NewAstChildDescend(AstTypeCallArgs)
- res := me.ParseParameters() && me.ParseEOX()
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseOperator() bool {
- return me.Consume(AstTypeOperator, TokenOperator)
- }
- func (me *ManualParser) NewAstChild(tyty AstType) *Ast {
- return me.now.NewChild(tyty, me.lookahead)
- }
- func (me *ManualParser) NewAstChildDescend(tyty AstType) {
- node := me.NewAstChild(tyty)
- me.now = node
- }
- func (me *ManualParser) AstAscend(keep bool) {
- if me.now.Parent() != nil {
- now := me.now
- me.now = now.Parent().(*Ast)
- if !keep {
- now.Remove()
- }
- }
- }
- func (me TokenType) BlockCloseForOpen() (TokenType, bool) {
- switch me {
- case TokenOpenBrace:
- return TokenCloseBrace, true
- case TokenDo:
- return TokenEnd, true
- default:
- return TokenError, false
- }
- }
- func (me TokenType) ParenthesisCloseForOpen() (TokenType, bool) {
- switch me {
- case TokenOpenBracket:
- return TokenCloseBracket, true
- case TokenOpenParen:
- return TokenCloseParen, true
- default:
- return TokenError, false
- }
- }
- func (me *ManualParser) ParseBlock() bool {
- me.Advance()
- open := me.LookaheadType()
- done, ok := open.BlockCloseForOpen()
- if !ok {
- /* Not an opening of a block, so no block found. */
- return false
- }
- me.DropLookahead()
- me.NewAstChildDescend(AstTypeBlock)
- res := me.ParseStatements()
- me.AstAscend(res)
- if res {
- me.Advance()
- if me.LookaheadType() != done {
- return me.ParseError()
- }
- me.DropLookahead()
- }
- return res
- }
- func (me *ManualParser) 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 *ManualParser) ParseWords() bool {
- me.NewAstChildDescend(AstTypeWords)
- res := me.ParseWord()
- for me.ParseWord() {
- }
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseDefinition() bool {
- me.Advance()
- res := me.Consume(AstTypeDefinition, TokenDef)
- if !res {
- return false
- }
- res = res && (me.ParseWord() || me.ParseOperator())
- if !res {
- _ = me.ParseError()
- }
- res = res && me.ParseParametersNonempty()
- if !res {
- _ = me.ParseError()
- }
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseParameter() bool {
- me.NewAstChildDescend(AstTypeParameter)
- res := me.ParseWordValue() || me.ParseOperator() ||
- me.ParseParenthesis() || me.ParseBlock()
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseParameters() bool {
- for me.ParseParameter() {
- }
- return true
- }
- func (me *ManualParser) ParseError() bool {
- me.now.NewChild(AstTypeError, me.lookahead)
- fmt.Printf("Parse error: at %s\n", me.lookahead)
- return false
- }
- func (me *ManualParser) ParseExpression() bool {
- return (me.ParseWordValue() || me.ParseOperator()) && me.ParseParameters()
- }
- func (me *ManualParser) ParseStatement() bool {
- me.NewAstChildDescend(AstTypeStatement)
- /* First case is for an empty expression/statement. */
- res := me.ParseEOX() ||
- me.ParseDefinition() ||
- (me.ParseExpression() && me.ParseEOX()) ||
- me.ParseBlock()
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseEOF() bool {
- return me.Consume(AstTypeEox, TokenEOF)
- }
- func (me *ManualParser) ParseStatements() bool {
- me.NewAstChildDescend(AstTypeStatements)
- res := me.ParseStatement()
- for me.ParseStatement() {
- }
- me.AstAscend(res)
- return res
- }
- func (me *ManualParser) ParseProgram() bool {
- return me.ParseStatements() && me.ParseEOF()
- }
- func (me *Ast) DotID() string {
- return fmt.Sprintf("ast_%p", me)
- }
- func (me *Ast) ToGraph() *graphviz.Digraph {
- g := graphviz.NewDigraph("rankdir", "LR")
- me.Walk(func(ast *Ast) *Ast {
- label := ast.AstType.String()
- if ast.Token != nil {
- token := ast.Token.ShortString()
- label = label + "\n" + token
- }
- g.AddNode(ast.DotID(), "label", label)
- if ast.Parent() != nil {
- g.AddEdgeByName(ast.Parent().(*Ast).DotID(), ast.DotID())
- }
- return nil
- })
- return g
- }
- func (me *Ast) Dotty() {
- g := me.ToGraph()
- g.Dotty()
- }
- func (me *Ast) ToAscii() {
- me.Walk(func(ast *Ast) *Ast {
- depth := tree.Depth(ast)
- nchild:= tree.CountChildren(ast)
- label := ast.AstType.String()
- indent:= strings.Repeat("--", depth)
- if ast.Token != nil {
- token := ast.Token.ShortString()
- fmt.Printf("%s>%s: %s\n", indent, label, token);
- } else {
- fmt.Printf("%s>%s: (%d)\n", indent, label, nchild );
- }
- return nil
- })
- }
- /*
- PROGRAM -> STATEMENTS.
- STATEMENTS -> STATEMENT STATEMENTS | .
- STATEMENT -> EXPRESSION EOX | DEFINITION | BLOCK .
- DEFINITION -> define WORDOP WORDOPS BLOCK.
- WORDOPS -> WORDOP WORDOPS | .
- EXPRESSION -> WORDVALUE PARAMETERS.
- PARAMETERS -> PARAMETER PARAMETERS | .
- PARAMETER -> WORDVALUE | PARENTHESIS | BLOCK | operator.
- PARENTHESIS -> '(' EXPRESSION ')' | ot EXPRESSION ct.
- BLOCK -> oe STATEMENTS ce | do STATEMENTS end .
- WORDOP -> word | operator | a | the.
- WORDVALUE -> word | VALUE | a | the.
- VALUE -> string | number | symbol.
- EOX -> eol | period.
- )
- */
|