2007-04-28

DSL vs. Rich Native Syntax

It's interesting - there is so many different projects which authors declare as an advantage that a project does not use (strange) Domain Specific Language, but where everything is implemented in the same host language.

Sometimes it comes out more beautiful, sometimes it is not.

Tried ZestyParser.

Here is the banal parsing of a phrase "create or replace"
from ZestyParser import *

sp = Omit((RE('\s+')) + Skip((RE('#[^\n]*\n') | RE('\s+'))))
create_package = RawToken('create') + sp
+ ((RawToken('or') + sp + RawToken('replace')) | EmptyToken)
ZestyParser('create or replace').scan(create_package)

I have to dig it further, so far it comes out ugly enough.

2007-04-20

There is only one right include strategy

There is only one right way of the implementation of searching of included files. In case if include contains a relative path it should be relative to the folder where the inclusive file is placed. Actually, it is so in C/C++.

Either I do not understand something, or Nant has surprised me
Let's take the following folders structure:

./
a/
a.build
all.build
common.build

I'd like to build project «a» if I'm located at folder «a» and if I'm in the root I'd like to build all projects.
The situation has become complicated because of the common file common.build which contains required useful settings.

At a first sight nant includes files relative to a current working directory (basedir project attribute)

The contents of a.build file

<project name="all" basedir="..">
<include buildfile="common.build"/>
<echo message="building a type - ${type}"/>
<echo message="base-dir ${project::get-base-directory()}"/>
</project>


The contents of all.build file

<project name="all" basedir=".">
<include buildfile="common.build"/>
<include buildfile="a/a.build"/>
<echo message="building all type - ${type}"/>
</project>


Run a.build being in folder a - everything is cool.

Being in the folder with the file all.build - run:

NAnt 0.85 (Build 0.85.2478.0; release; 14.10.2006)
Copyright (C) 2001-2006 Gerry Shaw
http://nant.sourceforge.net

Buildfile: file:///D:/Temp/2007-04-19/all.build
Target framework: Microsoft .NET Framework 2.0


BUILD FAILED

D:\Temp\2007-04-19\a\a.build(3,7):
Build file 'D:\Temp\2007-04-19\a\common.build' does not exist.

Total time: 0 seconds.


I have the impression that files included in the main file are searched relative to the working directory, but the files included into included files are searches relative to the inclusive file.

2007-04-06

Generic Visitor Combinators

It's simple and practical - Visitor Combination and Traversal Control.

The main idea is to separate specific code that executes concrete actions from the code that effects visits check.








IdentyDo nothing
Sequence(v1,v2)Sequentially perform visitor v2 after v1.
FailRaise exception.
Choice(v1,v2)Try visitor v1. If v1 fails, try v2 (left-biased choice).
All(v)Apply visitor v sequentially to every immediate subtree.
One(v)Apply visitor v sequentially to the immediate subtrees until it succeeds.


So, it's rather flexible to implement different actions by combine it and inherit from it.


TopDown(v) = def Sequence(v,All(TopDown(v)))
BottomUp(v) = def Sequence(All(BottomUp(v)),v)
IfZeroAddOne = def TopDown(Try(Sequence(IsZero,AddOne)))