Bento
 
SourceForge.net Logo
> Bento Home > Bento Documentation > Bento Specifications
Bento Specifications
 
 

Language Specification

Grammar

Language Specification

Concepts

Objects

Bento is an object-oriented language. Objects are software components which provide simple interfaces to complex data and logic. Bento objects have the key features that objects in all OO languages have: the ability to hide data and logic in an object (encapsulation); to define a new kind of object as an extension of an existing kind, specifying only the differences (inheritance); and to use such an extended object wherever the original object is expected (polymorphism).

However, there is one way in which Bento objects are unique. In Bento, all objects are considered data; they may contain logic, but this logic is not directly visible to a user of the object. All the user sees is the data generated by the logic.

Because Bento objects are data, not logic, Bento objects do not have callable functions in the conventional sense. The only methods in Bento are constructors.

This is a feature, not a flaw. Bento is capable of performing any computation or implementing any algorithm, but the logic must be properly encapsulated. This up front architectural cost is minor compared to the increased reliability and ease of maintenance which is achieved.

Processors

A Bento processor is a program capable of reading Bento code and instantiating Bento objects. Bento processors include Bento compilers, which write HTML (or other output language) files to disk, and Bento servers, which generate HTML (or other output language) on the fly in response to requests.

A Bento site is defined in one or more Bento files, which generally have a ".bento" extension. The Bento processor reads these files and builds an internal representation of their contents. This representation is then used to generate pages.

Elements

Comments

Comments contain text which is ignored by the Bento processor. There are two kinds of comments in Bento, documenting and nondocumenting. Documenting comments, bracketed by the special character sequences /* and */, contain useful information about the code, suitable for extraction by automated document generation tools. Nondocumenting comments, delimited by the special character sequences [-- and -], serve other purposes, such as improving readability or commenting out (disabling) code; they are ignored by documentation generators.

Comments may appear anywhere except inside static blocks or quoted strings. Comments may be nested.

Statements

Bento files contain statements in the Bento language (and comments, which are ignored). Bento statements come in three varieties: directives, definitions and constructions.

  • A directive provides information and structions to the Bento processor, such as linkage information for external objects.
  • A definition specifies how an object is constructed.
  • A construction generates data for an object.
The first statement of every Bento file must be one of two special types of definitions: either a site or core statement. The former defines a particular site, while the latter defines objects available to all sites.

Contained in the site and core definitions are object definitions, which may in turn contain more definitions. Object definitions may also contain constructions, which are the Bento statements that actually build the object.

Blocks

Many Bento statements contain blocks, which can be static or dynamic. A static block is delimited by the special character pairs [| and |] and contains data suitable for output as is. Here is a static block containing an HTML fragment:


    [|
        <table border="1" bgcolor="#DDDDDD" cellpadding="16">
            <tr><td>This HTML code is inside of a static block.</td></tr>
        </table>
    |]

                

A dynamic block is delimited by the special character pairs [= and =] and contains Bento statements. Here is a dynamic block containing three Bento statements:



    [=
        prologue;
        story;
        epilogue;
    =]

                
(The three statements in the above block are named constructions.)

Static blocks may have embedded dynamic blocks and vice versa. Here is the same dynamic block as above, but with three static blocks embedded in it:



    [=
        [| <h2>Prologue</h2> |]
        prologue;

        [| <h2>The Story</h2> |]
        story;

        [| <h2>Epilogue</h2> |]
        epilogue;
    =]

                
Because of the way blocks work in Bento, there is always more than one way to represent a block. For example, the following block will generate exactly the same output as the preceding one:


    [|
        <h2>Prologue</h2>
        [= prologue; =]

        <h2>The Story</h2>
        [= story; =]

        <h2>Epilogue</h2>
        [= epilogue; =]
    |]

                
There are three other special kinds of blocks in Bento: null, external and abstract. A null block is represented as [/] and generates a null string if instantiated. An external block is represented as [&] and indicates an implementation outside of Bento. Instantiation of an external block generally translates to a call to a module written in another language. An abstract block is represented as [?] and throws an exception if an attempt is made to instantiate it.

Directives

You don't need to know about directives to get started with Bento. You only need to learn about directives when you need to reference objects beyond this site, or after you've implemented a Bento site and are ready to optimize it. When you get to that point, look here.

Definitions

There are three main kinds of Bento definitions:

  • top-level definitions, either site or core statements. They contain definitions that are global within a site or among all sites, respectively.

  • object definitions, which contain the logic and data for constructing an object. Object definitions can optionally be typed, specify parameters or both.

  • array definitions, which specify arrays of objects. Arrays can either be fixed in size or growable, and either typed or untyped.
Every definition has a name and contents. The contents may be a value or a block. Such a block may contain constructions as well as additional definitions.

The following example consists of a site definition containing a typed, unparamaterized object definition, which itself contains an untyped array definition.



    site simple_site [=

        page foo [=

            itemlist[] = [ "item 1", "item 2", "item 3" ]

        =]
    =]

                

Constructions

Constructions constitute the logic which a Bento processor executes in order to build an object. There are several different kinds of constructions:

  • anonymous constructions, consisting of unnamed static or dynamic blocks.

  • named constructions, which instantiate specific objects.
  • conditional constructions, which execute blocks if specified conditions hold true.
  • iterated constructions, which execute blocks for all the members of a group, or until a specified condition holds true.
  • sub and super constructions, which execute the constructions in the current object's subclass or superclass.

The following example consists of an object definition containing a number of different kinds of constructions, along with an object definition.



    thingamabob [=

        /* an anonymous construction */
        [| <h3> |]

        /* a conditional construction */
        if (label) [=

            /* a named construction */
            label;

        =] else [|
             (Untitled)
        |]

        /* another anonymous construction */
        [| </h3> |]

        /* sub construction */
        sub;

        /* abstract object definition */
        label [?]
    =]

                

Names

Types

Parameters

Grammar for the Bento Language

Name := IDENTIFIERThere is one namespace in Bento, but the meaning of a name depends on its scope, and there are many scopes.
Value := Block | ValueExpr | ArrayBody | TableBodyA value is something which can be evaluated: an expression, a block or a collection.
Block := ("[/]" | "[?]" | "[&]" | DataBlock | BentoBlock) [ CatchBlock ]A block is a container, possibly empty, of code or data.
Literal := NullLiteral | BooleanLiteral | NumericLiteral | TextLiteral
NullLiteral := "null"
BooleanLiteral := "true" | "false"
NumericLiteral := DECIMAL_INTEGER | HEX_INTEGER | FLOATING_POINT_NUMBER
TextLiteral := CHARACTER | STRING
DataBlock := StaticBlock | LiteralBlock
StaticBlock := ("[|" | "[/") [STATIC_TEXT] (Block [STATIC_TEXT])* ("|]" | "/]")
LiteralBlock := \"[``\" [LITERAL_TEXT] \"``]\"
BentoBlock := "[=" (Directive | Definition | Construction)* "=]"
CatchBlock := "catch" [DefinitionNameExpr] Block
DefinitionNameExpr := "(" DefinitionNameExpr ")" | DefinitionName
Directive := "keep" Name ("," Name)* | "discard" Name ("," Name)*
Comment := DocComment | NondocComment
DocComment := "/*" [COMMENT_TEXT] (Comment [COMMENT_TEXT])* "*/"
NondocComment := "/--" [COMMENT_TEXT] (Comment [COMMENT_TEXT])* "--/"
Type := SimpleType | CollectionType
SimpleType := TypeName [ArgumentList] | PrimitiveType [SingleArgument]
CollectionType := SimpleType (IndefiniteDim)+
TypeName := Name ("." Name)*
ArgumentList := "(" [Argument ("," Argument)*] ")"
Argument := DefinitionRef | Value
DefinitionRef := ["super" | "this" | "owner" "."] TypeName
PrimitiveType := "boolean" | "byte" | "char" | "double" | "float" | "int" | "long" | "string"
SingleArgument := "(" Argument ")"
ValueExpr := LogicalOrExpr ["?" ValueExpr ":" ValueExpr]
LogicalOrExpr := LogicalAndExpr ("||" LogicalAndExpr)*
LogicalAndExpr := OrExpr ("&&" OrExpr)*
OrExpr := XorExpr ("|" XorExpr)*
XorExpr := AndExpr ("^" AndExpr)*
AndExpr := EqualityExpr ("&" EqualityExpr)*
EqualityExpr := RelationalExpr (("==" | "!=") RelationalExpr)*
RelationalExpr := IsaExpr | ShiftExpr (("<" | ">" | "<=" | ">=") ShiftExpr)*
IsaExpr := PrimaryExpr ("isa" | "?=") Type
ShiftExpr := AdditiveExpr (("<<" | ">>" | ">>>") AdditiveExpr)*
AdditiveExpr := MultiplicativeExpr (("+" | "-") MultiplicativeExpr)*
MultiplicativeExpr := UnaryExpr (("*" | "/" | "%") UnaryExpr)*
UnaryExpr := ("+" | "-" | "~" | "!" | "(" Type ")") PrimaryExpr
PrimaryExpr := "(" ValueExpr() ")" | Literal | ComplexName
Definition := [Modifier] (ComplexDefinition | ElementDefinition | ArrayDefinition | TableDefinition)
Modifier := AccessModifier [DurabilityModifier] | DurabilityModifier [AccessModifier]
AccessModifier := "local" | "public"
DurabilityModifier := "static" | "dynamic"
ComplexDefinition := [SimpleTypeList] DefinitionName Block
SimpleTypeList := SimpleType ("," SimpleType)*
DefinitionName := Name [ParameterList ("," ParameterList)*]
ParameterList := "(" [Parameter ("," Parameter)*] ")"
Parameter := FormalParameter | "*"
FormalParameter := [TypeName (IndefiniteDim)*] Name (IndefiniteDim)*
ElementDefinition := ElementName "=" Value) [";"]
ElementName := DefinitionName ("[" ("+" | ValueExpr) "]" | "{" ValueExpr "}")*
Construction := TypeConstruction | LogicConstruction | Redirection | AnonConstruction | NamedConstruction
Instance := "(" Instance ")" | ComplexName
TypeConstruction := ("sub" | "super") ";"
Redirection := "redirect" Instance [";"]
AnonConstruction := "(" ValueExpr() ")" ";" | StringLiteral ";" | AnonDefinition rule(";" ]
AnonDefinition := [ ParameterList ("," ParameterList)* ] Block
NamedConstruction := ComplexName ["." NameSuffix] ";"
ComplexName := [NamePrefix "."] (NamePart ".")* NamePart
NamePrefix := "super" | "this" | "owner"
NamePart := Name [ArgumentList] ("[" ValueExpr "]" | "{" ValueExpr "}")*
NameSuffix := "type" | "count"
LogicConstruction := Conditional | Loop
Conditional := ("if" ValueExpr | "with" WithPredicate) Block ("else" ("if" ValueExpr | "with" WithPredicate) Block)* ["else" Block]
WithPredicate := "(" WithPredicate ")" | Name
Loop := "for" Iterator (("and" | "or") Iterator)* Block
Iterator := FormalParamter ("in" Instance | "from" ValueExpr ["to" ValueExpr] ["by" ValueExpr]) ["where" ValueExpr] ["until" ValueExpr]
CollectionDefinition := ArrayDefinition | TableDefinition
Dim := "[" [ValueExpr] "]" | "{" [ValueExpr] "}"
IndefiniteDim := "[" "]" | "{" "}"
ArrayDefinition := ([Type] ArrayName | ArrayType ElementName) "=" ArrayConstruction
ArrayName := DefinitionName ArrayDim (Dim)*
ArrayType := SimpleType ArrayDim (IndefiniteDim)*
ArrayDim := "[" [ValueExpr] "]"
TableDefinition := ([Type] TableName | TableType ElementName) "=" TableConstruction
TableName := DefinitionName TableDim (Dim)*
TableType := SimpleType TableDim (IndefiniteDim)*
TableDim := "{" [ValueExpr] "}"
ArrayConstruction := (Instance | ArrayBody | "[&]") [";"]
TableConstruction := (Instance | TableBody | "[&]") [";"]
ArrayBody := ( "[" "]" | "[" "..." ("," ArrayElement)* "]" | "[" ArrayElement ("," ArrayElement)* ["," "..." ("," ArrayElement)*] "]")
ArrayElement := DefinitionReference | Value | ArrayComprehension
TableBody := ( "[" "]" | "[" [DefaultTableElement ","] TableElement ("," TableElement)* "]")
DefaultTableElement := "{" (DefinitionReference | Value) "}"
TableElement := "{" ValueExpr "," (DefinitionReference | Value) "}" | TableComprehension
ArrayComprehension := ArrayConditional | ArrayFor | ArrayBlock
ArrayConditional := ("if" ValueExpr | "with" WithPredicate) ArrayBlock ("else" ("if" ValueExpr | "with" WithPredicate) ArrayBlock)* ["else" ArrayBlock]
ArrayFor := "for" Iterator (("and" | "or") Iterator())* ArrayBlock
ArrayBlock := "[[" [ ArrayElement ("," ArrayElement)* ] "]]" [ArrayCatchBlock]
ArrayCatchBlock := "catch" [DefinitionNameExpr] ArrayBlock
TableComprehension := TableConditional | TableFor | TableBlock
TableConditional := ("if" ValueExpr | "with" WithPredicate) TableBlock ("else" ("if" ValueExpr | "with" WithPredicate) TableBlock)* ["else" TableBlock]
TableFor := "for" Iterator (("and" | "or") Iterator())* TableBlock
TableBlock := "[[" [ TableElement ("," TableElement)* ] "]]" [TableCatchBlock]
TableCatchBlock := "catch" [InstanceExpr] TableBlock
BentoFile := (CoreDefinition | SiteDefinition)+
CoreDefinition := "core" SiteBlock
SiteDefinition := "site" Name SiteBlock
SiteBlock := "[=" (SiteLevelDirective)* (SiteLevelDefinition)* "=]"
SiteLevelDirective := "join" NameRange | "extern" Name NameRange
NameRange := Name ("." (Name | "*"))* ["." "**"]
SiteLevelDefinition := SiteDefinition | Definition
STATIC_TEXT := ~<"[|" | "[/" | "[``" | "[=" | "|]" | "/]">*
LITERAL_TEXT := ~<\"``]\">*
COMMENT_TEXT := ~<"/*" | "/--">*
DECIMAL_INTEGER := <"1"-"9"> * <"l" | "L">?
HEX_INTEGER := <"0x" | "0X" | "#"> + <"l" | "L">?
FLOATING_POINT_NUMBER := + <"."> * ? ? | <"."> + ? ? | + ? | + ?
EXPONENT := <"e" | "E"> <"+" | "-">? +
FP_MARK := <"f" | "F" | "d" | "D">
CHARACTER := <"'"> (~<"'" | "\" | "\n" | "\r"> | ) <"'">
STRING := <"""> (~<""", [``\", [``\n", [``\r"> | )* <""">
ESCAPE_SEQUENCE := <"\"> (<"n","t","b","r","f","\","'","""> | <"0"-"7"> <"0"-"7">? | <"0"-"3"> <"0"-"7"> <"0"-"7">)
IDENTIFIER := *
LETTER := <"A"-"Z", [``a"-"z">
DIGIT := <"0"-"9">
SPACE := <" " | "\t" | "\n" | "\r" | "\f">*


top


Use of any software, source code and documentation obtained from this site is governed by the Bento Poetic License.

Copyright © 2003 by bentodev.org