- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Fwd: Re: parsing incomplete expressions
Tue, 2009-02-24, 01:23
(fwd... i forgot reply-all)
Ishaaq,
I have made a ugly but fast way to tab completion. It was made for just a prototype and is very very simple. All work is done by overriding the implicit function keyword of StdTokenParsers.
Look this example:
import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._
import scala.collection.mutable._
object AutoComplete extends StandardTokenParsers with ImplicitConversions
{
lexical.reserved ++= List("victor", "victoria", "come", "compra", "roberta", "ronildo")
val tried_keywords: ListBuffer[String] = new ListBuffer[String]
var matched: String = ""
def matchKeyword(expect: String)(e: Elem): Boolean = {
println("matching: " e.chars + " - expect: " + expect)
if (expect == e.chars) {
matched = expect
true
}
else if (expect.startsWith(e.chars)) {
println("---> " + expect + " startsWith " + e)
//keep only matched words in list tried_keywords
for(val v <- tried_keywords if !v.startsWith(e.chars)) tried_keywords -= v
tried_words += expect
matched = ""
false
}
else
false
}
def errReport(e: Elem): String = {
"Err: " + e + " found."
}
override implicit def keyword(chars: String): Parser[String] =
acceptIf(m(chars))(e) ^^ (_.chars)
//the keywords *must* to be ordened to auto-complete works properly!!! major -> minor
def cmd: Parser[String] =
"victoria" | "victor" | "roberta" | "ronildo"
//the keywords *must* to be ordened to auto-complete works properly!!! major -> minor
def args: Parser[String] =
"comprar" | "come"
def line: Parser[String] =
cmd ~ args ^^ { case cmd ~ args => cmd + " " + args }
def parse(r: String) : ParseResult[Any] = {
tried_words.clear
matched = ""
val ret = phrase(line)(new lexical.Scanner(r))
ret match {
case Success(_, _) => tried_words.clear; matched = ""
case _ =>
}
ret
}
}
object Main extends Application
{
var line: String = ""
while (true) {
val c = readLine
line += c
println(AutoComplete.parse(line))
println(AutoComplete.tried_words + AutoComplete.matched)
}
}
When running, you enter part of the command, hit enter, and it will print the list of matched keywords, then hit the rest of the command.
Feel free to improve this. I think that a better way is to improve the scala combinators parsers library, but it works for while :-)
[]s
Victor
On Mon, Feb 23, 2009 at 7:05 PM, Ishaaq Chandy <ishaaq@gmail.com> wrote:
--
GNU/Linux user #5f5f5f - http://counter.li.org
--
GNU/Linux user #5f5f5f - http://counter.li.org
Ishaaq,
I have made a ugly but fast way to tab completion. It was made for just a prototype and is very very simple. All work is done by overriding the implicit function keyword of StdTokenParsers.
Look this example:
import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._
import scala.collection.mutable._
object AutoComplete extends StandardTokenParsers with ImplicitConversions
{
lexical.reserved ++= List("victor", "victoria", "come", "compra", "roberta", "ronildo")
val tried_keywords: ListBuffer[String] = new ListBuffer[String]
var matched: String = ""
def matchKeyword(expect: String)(e: Elem): Boolean = {
println("matching: " e.chars + " - expect: " + expect)
if (expect == e.chars) {
matched = expect
true
}
else if (expect.startsWith(e.chars)) {
println("---> " + expect + " startsWith " + e)
//keep only matched words in list tried_keywords
for(val v <- tried_keywords if !v.startsWith(e.chars)) tried_keywords -= v
tried_words += expect
matched = ""
false
}
else
false
}
def errReport(e: Elem): String = {
"Err: " + e + " found."
}
override implicit def keyword(chars: String): Parser[String] =
acceptIf(m(chars))(e) ^^ (_.chars)
//the keywords *must* to be ordened to auto-complete works properly!!! major -> minor
def cmd: Parser[String] =
"victoria" | "victor" | "roberta" | "ronildo"
//the keywords *must* to be ordened to auto-complete works properly!!! major -> minor
def args: Parser[String] =
"comprar" | "come"
def line: Parser[String] =
cmd ~ args ^^ { case cmd ~ args => cmd + " " + args }
def parse(r: String) : ParseResult[Any] = {
tried_words.clear
matched = ""
val ret = phrase(line)(new lexical.Scanner(r))
ret match {
case Success(_, _) => tried_words.clear; matched = ""
case _ =>
}
ret
}
}
object Main extends Application
{
var line: String = ""
while (true) {
val c = readLine
line += c
println(AutoComplete.parse(line))
println(AutoComplete.tried_words + AutoComplete.matched)
}
}
When running, you enter part of the command, hit enter, and it will print the list of matched keywords, then hit the rest of the command.
Feel free to improve this. I think that a better way is to improve the scala combinators parsers library, but it works for while :-)
[]s
Victor
On Mon, Feb 23, 2009 at 7:05 PM, Ishaaq Chandy <ishaaq@gmail.com> wrote:
Yes, I agree writing a parser is relatively easy and I have been able to achieve quite a bit of complexity relatively easily using scala's parser library. Before this I would have had to whip out ANTLR to do what I needed. I do wonder though about how performant writing a parser combinator in scala is when compared to something like a parser compiled from something like ANTLR. Has anyone done any profiling on this?
What I meant in my earlier post was I should read up on how parser combinators are implemented and see if I can come up with my own library (or at least an extension to the scala one) to be able to do all the funky tab-completion and line-completion detection stuff I want to do - but this is pie in the sky stuff - doubt I'll be able to get to that stage any time soon!!! Baby steps first! :)
Ishaaq
2009/2/24 Harshad <harshad.rj@gmail.com>Ishaaq Chandy wrote:
> Thanks but this is a small side-app that I am writing that may or may not
> be used internally by my team if I am successful with it - I'm doing this
> on my own time more for my own enjoyment and self-improvement rather than
> as part of my day job so I can't really justify buying licenses for third
> party dependencies for it at this point.
>
> But your answer does tell me something - this obviously isn't possible
> with the current parser combinator API in scala or you wouldn't have
> rolled your own. Maybe I should read up on parser combinators and write
> something myself - though that may be a bit more than I can chew at this
> point being a newbie to scala.
IMO, writing the parser combinators in Scala is the easy part. See this link
for a nice exposition on the topic:
http://www.cs.kuleuven.be/publicaties/rapporten/cw/CW491.abs.html
The challenging part is designing the combinator library to do things you
want it to do.
Cheers,
Harshad
--
GNU/Linux user #5f5f5f - http://counter.li.org
--
GNU/Linux user #5f5f5f - http://counter.li.org