bea
Version:
96 lines (72 loc) • 2.68 kB
text/coffeescript
_ = require 'underscore'
class BeaNode
constructor: (, , = "", = 0)->
= []
= null
addChild: (node)->
if typeof node == "string" then node = new BeaNode node, + 1,
node.parent = this
.push node
node
#find child by exact text
findChild: (text)->
_.detect , (node)-> node.text == text
#returns the 'type' of the node. Basically the first word of the line or 'comment'
type: ->
if /^\/\/|^\#/.test then return ''
tmp = .split(' ')
return tmp[0]
#flattens children into a joined string (???) - make a string out of all children
toString: (joinStr = '\n') ->
if .length == 0 then return ""
_.compact(_.flatten(_.map , (node) -> [node.text, node.toString(joinStr)])).join joinStr
#returns a child of type() type
childType: (type) ->
_.detect , (node) -> node.type() == type
#return list of children which match re
matchChildren: (re) ->
_.select , (node) -> re.test node.text
class BeaParser
#preserveWhitespace means preserve starting whitespace. Trailing whitespace is removed
constructor: ( = "", = false, = false) ->
= new BeaNode "", 0, , 0
=
#parse a line of text.
#Indentation determines the node's level
#Throws exception if indentation is invalid
parseLine: (txt, linenumber) ->
level = txt.match(/(^\s+)/g)?[0].length; level?=0; level++
rawTxt = txt.replace(/^\s+|\s+$/g, '')
return null unless rawTxt.length
if !
#internal comments can start with #
#escaped hash must be added as node: \#
return null if rawTxt[0] == '#'
#in-string comments
rawTxt = rawTxt.replace /[^\\]\#.*/, ''
rawTxt = rawTxt.replace /\\#/g, '#'
if !
txt = rawTxt
else
txt = txt.replace(/\s+$/g, '') #trailing whitespace
return null unless txt.length
#replace all tab chars with spaces
txt = txt.replace /\t/g, ' '
node = new BeaNode txt, level, , linenumber + 1
if level == .level
.parent.addChild node
else if level >= .level + 1
.addChild node
else if level < .level
#walk up until we find the parent
tmp =
while tmp && tmp.level > level
tmp = tmp.parent
if tmp && tmp.parent
tmp.parent.addChild node
else
throw "Invalid indent on line " + (linenumber + 1) + ": '" + txt + "'"
= node
parse: (txt) ->
_.each txt.split('\n'), , this
exports.BeaParser = BeaParser